diff --git a/library/bignum.c b/library/bignum.c index 4f7ca16cda..617a7abf3c 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -1968,6 +1968,35 @@ int mbedtls_mpi_random(mbedtls_mpi *X, return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng); } +/* + * Modular inverse: X = A^-1 mod N with N odd (and A any range) + */ +static int mbedtls_mpi_inv_mod_odd(mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi T, G; + + mbedtls_mpi_init(&T); + mbedtls_mpi_init(&G); + + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, A, N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(&G, &T, &T, N)); + if (mbedtls_mpi_cmp_int(&G, 1) != 0) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &T)); + +cleanup: + mbedtls_mpi_free(&T); + mbedtls_mpi_free(&G); + + return ret; +} + /* * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) */ @@ -1980,6 +2009,10 @@ int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } + if (mbedtls_mpi_get_bit(N, 0) == 1) { + return mbedtls_mpi_inv_mod_odd(X, A, N); + } + mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2); mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV); mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2);