From 3be31bf21b500722d2faa2571a600bddfec2011b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 18 Nov 2025 11:19:10 +0100 Subject: [PATCH 1/3] rsa: extract helper function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Will gain a new implementation using the CRT, so we want to hide the upcoming complexity in a dedicated function. Signed-off-by: Manuel Pégourié-Gonnard --- library/rsa.c | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/library/rsa.c b/library/rsa.c index 08267dbfce17..8de6e9129f2a 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1268,6 +1268,35 @@ int mbedtls_rsa_public(mbedtls_rsa_context *ctx, return 0; } +/* Generate random A and B such that A^-1 = B mod N */ +static int rsa_gen_rand_with_inverse(const mbedtls_rsa_context *ctx, + mbedtls_mpi *A, + mbedtls_mpi *B, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + int ret, count = 0; + mbedtls_mpi G; + + mbedtls_mpi_init(&G); + + mbedtls_mpi_lset(&G, 0); + do { + if (count++ > 10) { + ret = MBEDTLS_ERR_RSA_RNG_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_random(A, 1, &ctx->N, f_rng, p_rng)); + MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(&G, B, A, &ctx->N)); + } while (mbedtls_mpi_cmp_int(&G, 1) != 0); + +cleanup: + mbedtls_mpi_free(&G); + + return ret; +} + /* * Generate or update blinding values, see section 10 of: * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, @@ -1277,10 +1306,7 @@ int mbedtls_rsa_public(mbedtls_rsa_context *ctx, static int rsa_prepare_blinding(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { - int ret, count = 0; - mbedtls_mpi R; - - mbedtls_mpi_init(&R); + int ret; if (ctx->Vf.p != NULL) { /* We already have blinding values, just update them by squaring */ @@ -1288,30 +1314,17 @@ static int rsa_prepare_blinding(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->N)); - goto cleanup; } /* Unblinding value: Vf = random number, invertible mod N */ - mbedtls_mpi_lset(&R, 0); - do { - if (count++ > 10) { - ret = MBEDTLS_ERR_RSA_RNG_FAILED; - goto cleanup; - } - - MBEDTLS_MPI_CHK(mbedtls_mpi_random(&ctx->Vf, 1, &ctx->N, f_rng, p_rng)); - MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(&R, &ctx->Vi, &ctx->Vf, &ctx->N)); - } while (mbedtls_mpi_cmp_int(&R, 1) != 0); + MBEDTLS_MPI_CHK(rsa_gen_rand_with_inverse(ctx, &ctx->Vf, &ctx->Vi, f_rng, p_rng)); /* Blinding value: Vi = Vf^(-e) mod N * (Vi already contains Vf^-1 at this point) */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN)); - cleanup: - mbedtls_mpi_free(&R); - return ret; } From b13033dd3e4cf6c7568189868e83a07a2eb0a815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 18 Nov 2025 11:39:40 +0100 Subject: [PATCH 2/3] rsa: extract helper function for CRT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Was only used in one place so far, but will be used in rsa_gen_rand_with_inverse()'s upcoming CRT-based implementation. Signed-off-by: Manuel Pégourié-Gonnard --- library/rsa.c | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/library/rsa.c b/library/rsa.c index 8de6e9129f2a..0c3973b8d530 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1268,6 +1268,38 @@ int mbedtls_rsa_public(mbedtls_rsa_context *ctx, return 0; } +#if !defined(MBEDTLS_RSA_NO_CRT) +/* + * Compute T such that T = TP mod P and T = TP mod Q. + * (This is the Chinese Remainder Theorem - CRT.) + * + * WARNING: uses TP as a temporary, so its value is lost! + */ +static int rsa_apply_crt(mbedtls_mpi *T, + mbedtls_mpi *TP, + const mbedtls_mpi *TQ, + const mbedtls_rsa_context *ctx) +{ + int ret; + + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(T, TP, TQ)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(TP, T, &ctx->QP)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(T, TP, &ctx->P)); + + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(TP, T, &ctx->Q)); + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(T, TQ, TP)); + +cleanup: + return ret; +} +#endif + /* Generate random A and B such that A^-1 = B mod N */ static int rsa_gen_rand_with_inverse(const mbedtls_rsa_context *ctx, mbedtls_mpi *A, @@ -1524,19 +1556,7 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, &DP_blind, &ctx->P, &ctx->RP)); MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, &DQ_blind, &ctx->Q, &ctx->RQ)); - - /* - * T = (TP - TQ) * (Q^-1 mod P) mod P - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&T, &TP, &TQ)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->QP)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &TP, &ctx->P)); - - /* - * T = TQ + T * Q - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->Q)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP)); + MBEDTLS_MPI_CHK(rsa_apply_crt(&T, &TP, &TQ, ctx)); #endif /* MBEDTLS_RSA_NO_CRT */ /* Verify the result to prevent glitching attacks. */ From 8b0ee342fac4d7c3cd3c910af2ee9c5e9622f982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 18 Nov 2025 12:00:07 +0100 Subject: [PATCH 3/3] rsa: use the CRT to generate blinding values 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 | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/library/rsa.c b/library/rsa.c index 0c3973b8d530..b0194cefe630 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1307,6 +1307,7 @@ static int rsa_gen_rand_with_inverse(const mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { +#if defined(MBEDTLS_RSA_NO_CRT) int ret, count = 0; mbedtls_mpi G; @@ -1327,6 +1328,31 @@ static int rsa_gen_rand_with_inverse(const mbedtls_rsa_context *ctx, mbedtls_mpi_free(&G); return ret; +#else + int ret; + mbedtls_mpi Ap, Aq, Bp, Bq; + + mbedtls_mpi_init(&Ap); mbedtls_mpi_init(&Aq); + mbedtls_mpi_init(&Bp); mbedtls_mpi_init(&Bq); + + /* Generate Ap in [1, P) and compute Bp = Ap^-1 mod P */ + MBEDTLS_MPI_CHK(mbedtls_mpi_random(&Ap, 1, &ctx->P, f_rng, p_rng)); + MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(NULL, &Bp, &Ap, &ctx->P)); + + /* Generate Ap in [1, Q) and compute Bq = Aq^-1 mod P */ + MBEDTLS_MPI_CHK(mbedtls_mpi_random(&Aq, 1, &ctx->Q, f_rng, p_rng)); + MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(NULL, &Bq, &Aq, &ctx->Q)); + + /* Reconstruct A and B */ + MBEDTLS_MPI_CHK(rsa_apply_crt(A, &Ap, &Aq, ctx)); + MBEDTLS_MPI_CHK(rsa_apply_crt(B, &Bp, &Bq, ctx)); + +cleanup: + mbedtls_mpi_free(&Ap); mbedtls_mpi_free(&Aq); + mbedtls_mpi_free(&Bp); mbedtls_mpi_free(&Bq); + + return ret; +#endif } /*