From a4bf680e92dc5be758a730daaad7bf6eac5d7353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 10 Jul 2025 10:48:23 +0200 Subject: [PATCH] RSA: refactor: avoid code duplication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Pégourié-Gonnard --- library/rsa.c | 35 ++++++++++++----------------------- library/rsa_alt_helpers.c | 5 ++++- library/rsa_alt_helpers.h | 13 ++++++++----- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/library/rsa.c b/library/rsa.c index b7df690fb5..08267dbfce 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1047,7 +1047,7 @@ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, unsigned int nbits, int exponent) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi H, G, L; + mbedtls_mpi H; int prime_quality = 0; /* @@ -1060,8 +1060,6 @@ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, } mbedtls_mpi_init(&H); - mbedtls_mpi_init(&G); - mbedtls_mpi_init(&L); if (exponent < 3 || nbits % 2 != 0) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; @@ -1099,35 +1097,28 @@ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, mbedtls_mpi_swap(&ctx->P, &ctx->Q); } - /* Temporarily replace P,Q by P-1, Q-1 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->P, &ctx->P, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->Q, &ctx->Q, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&H, &ctx->P, &ctx->Q)); - - /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ - MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->E, &H)); - if (mbedtls_mpi_cmp_int(&G, 1) != 0) { + /* Compute D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) + * if it exists (FIPS 186-4 §B.3.1 criterion 2(a)) */ + ret = mbedtls_rsa_deduce_private_exponent(&ctx->P, &ctx->Q, &ctx->E, &ctx->D); + if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { + mbedtls_mpi_lset(&ctx->D, 0); /* needed for the next call */ continue; } + if (ret != 0) { + goto cleanup; + } - /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ - MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->P, &ctx->Q)); - MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&L, NULL, &H, &G)); - MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->D, &ctx->E, &L)); - - if (mbedtls_mpi_bitlen(&ctx->D) <= ((nbits + 1) / 2)) { // (FIPS 186-4 §B.3.1 criterion 3(a)) + /* (FIPS 186-4 §B.3.1 criterion 3(a)) */ + if (mbedtls_mpi_bitlen(&ctx->D) <= ((nbits + 1) / 2)) { continue; } break; } while (1); - /* Restore P,Q */ - MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->P, &ctx->P, 1)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->Q, &ctx->Q, 1)); + /* N = P * Q */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q)); - ctx->len = mbedtls_mpi_size(&ctx->N); #if !defined(MBEDTLS_RSA_NO_CRT) @@ -1146,8 +1137,6 @@ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, cleanup: mbedtls_mpi_free(&H); - mbedtls_mpi_free(&G); - mbedtls_mpi_free(&L); if (ret != 0) { mbedtls_rsa_free(ctx); diff --git a/library/rsa_alt_helpers.c b/library/rsa_alt_helpers.c index d91949af12..08adbe3eb8 100644 --- a/library/rsa_alt_helpers.c +++ b/library/rsa_alt_helpers.c @@ -212,7 +212,10 @@ int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P, MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L)); MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D)); - /* Compute modular inverse of E in LCM(P-1, Q-1) */ + /* Compute modular inverse of E mod LCM(P-1, Q-1) + * This is FIPS 186-4 §B.3.1 criterion 3(b). + * This will return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if E is not coprime to + * (P-1)(Q-1), also validating FIPS 186-4 §B.3.1 criterion 2(a). */ MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K)); cleanup: diff --git a/library/rsa_alt_helpers.h b/library/rsa_alt_helpers.h index 052b02491e..580ffb2fba 100644 --- a/library/rsa_alt_helpers.h +++ b/library/rsa_alt_helpers.h @@ -89,12 +89,15 @@ int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N, mbedtls_mpi const *E, * \param P First prime factor of RSA modulus * \param Q Second prime factor of RSA modulus * \param E RSA public exponent - * \param D Pointer to MPI holding the private exponent on success. + * \param D Pointer to MPI holding the private exponent on success, + * ie the modular inverse of E modulo LCM(P-1,Q-1). * - * \return - * - 0 if successful. In this case, D is set to a simultaneous - * modular inverse of E modulo both P-1 and Q-1. - * - A non-zero error code otherwise. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if E is not coprime to P-1 + * and Q-1, that is, if GCD( E, (P-1)*(Q-1) ) != 1. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if inputs are otherwise + * invalid. * * \note This function does not check whether P and Q are primes. *