1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * Helper functions for the RSA module 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 5a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6a8e1175bSopenharmony_ci * 7a8e1175bSopenharmony_ci */ 8a8e1175bSopenharmony_ci 9a8e1175bSopenharmony_ci#include "common.h" 10a8e1175bSopenharmony_ci 11a8e1175bSopenharmony_ci#if defined(MBEDTLS_RSA_C) 12a8e1175bSopenharmony_ci 13a8e1175bSopenharmony_ci#include "mbedtls/rsa.h" 14a8e1175bSopenharmony_ci#include "mbedtls/bignum.h" 15a8e1175bSopenharmony_ci#include "rsa_alt_helpers.h" 16a8e1175bSopenharmony_ci 17a8e1175bSopenharmony_ci/* 18a8e1175bSopenharmony_ci * Compute RSA prime factors from public and private exponents 19a8e1175bSopenharmony_ci * 20a8e1175bSopenharmony_ci * Summary of algorithm: 21a8e1175bSopenharmony_ci * Setting F := lcm(P-1,Q-1), the idea is as follows: 22a8e1175bSopenharmony_ci * 23a8e1175bSopenharmony_ci * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) 24a8e1175bSopenharmony_ci * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the 25a8e1175bSopenharmony_ci * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four 26a8e1175bSopenharmony_ci * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) 27a8e1175bSopenharmony_ci * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime 28a8e1175bSopenharmony_ci * factors of N. 29a8e1175bSopenharmony_ci * 30a8e1175bSopenharmony_ci * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same 31a8e1175bSopenharmony_ci * construction still applies since (-)^K is the identity on the set of 32a8e1175bSopenharmony_ci * roots of 1 in Z/NZ. 33a8e1175bSopenharmony_ci * 34a8e1175bSopenharmony_ci * The public and private key primitives (-)^E and (-)^D are mutually inverse 35a8e1175bSopenharmony_ci * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. 36a8e1175bSopenharmony_ci * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. 37a8e1175bSopenharmony_ci * Splitting L = 2^t * K with K odd, we have 38a8e1175bSopenharmony_ci * 39a8e1175bSopenharmony_ci * DE - 1 = FL = (F/2) * (2^(t+1)) * K, 40a8e1175bSopenharmony_ci * 41a8e1175bSopenharmony_ci * so (F / 2) * K is among the numbers 42a8e1175bSopenharmony_ci * 43a8e1175bSopenharmony_ci * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord 44a8e1175bSopenharmony_ci * 45a8e1175bSopenharmony_ci * where ord is the order of 2 in (DE - 1). 46a8e1175bSopenharmony_ci * We can therefore iterate through these numbers apply the construction 47a8e1175bSopenharmony_ci * of (a) and (b) above to attempt to factor N. 48a8e1175bSopenharmony_ci * 49a8e1175bSopenharmony_ci */ 50a8e1175bSopenharmony_ciint mbedtls_rsa_deduce_primes(mbedtls_mpi const *N, 51a8e1175bSopenharmony_ci mbedtls_mpi const *E, mbedtls_mpi const *D, 52a8e1175bSopenharmony_ci mbedtls_mpi *P, mbedtls_mpi *Q) 53a8e1175bSopenharmony_ci{ 54a8e1175bSopenharmony_ci int ret = 0; 55a8e1175bSopenharmony_ci 56a8e1175bSopenharmony_ci uint16_t attempt; /* Number of current attempt */ 57a8e1175bSopenharmony_ci uint16_t iter; /* Number of squares computed in the current attempt */ 58a8e1175bSopenharmony_ci 59a8e1175bSopenharmony_ci uint16_t order; /* Order of 2 in DE - 1 */ 60a8e1175bSopenharmony_ci 61a8e1175bSopenharmony_ci mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ 62a8e1175bSopenharmony_ci mbedtls_mpi K; /* Temporary holding the current candidate */ 63a8e1175bSopenharmony_ci 64a8e1175bSopenharmony_ci const unsigned char primes[] = { 2, 65a8e1175bSopenharmony_ci 3, 5, 7, 11, 13, 17, 19, 23, 66a8e1175bSopenharmony_ci 29, 31, 37, 41, 43, 47, 53, 59, 67a8e1175bSopenharmony_ci 61, 67, 71, 73, 79, 83, 89, 97, 68a8e1175bSopenharmony_ci 101, 103, 107, 109, 113, 127, 131, 137, 69a8e1175bSopenharmony_ci 139, 149, 151, 157, 163, 167, 173, 179, 70a8e1175bSopenharmony_ci 181, 191, 193, 197, 199, 211, 223, 227, 71a8e1175bSopenharmony_ci 229, 233, 239, 241, 251 }; 72a8e1175bSopenharmony_ci 73a8e1175bSopenharmony_ci const size_t num_primes = sizeof(primes) / sizeof(*primes); 74a8e1175bSopenharmony_ci 75a8e1175bSopenharmony_ci if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) { 76a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 77a8e1175bSopenharmony_ci } 78a8e1175bSopenharmony_ci 79a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(N, 0) <= 0 || 80a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(D, 1) <= 0 || 81a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(D, N) >= 0 || 82a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(E, 1) <= 0 || 83a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(E, N) >= 0) { 84a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 85a8e1175bSopenharmony_ci } 86a8e1175bSopenharmony_ci 87a8e1175bSopenharmony_ci /* 88a8e1175bSopenharmony_ci * Initializations and temporary changes 89a8e1175bSopenharmony_ci */ 90a8e1175bSopenharmony_ci 91a8e1175bSopenharmony_ci mbedtls_mpi_init(&K); 92a8e1175bSopenharmony_ci mbedtls_mpi_init(&T); 93a8e1175bSopenharmony_ci 94a8e1175bSopenharmony_ci /* T := DE - 1 */ 95a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D, E)); 96a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1)); 97a8e1175bSopenharmony_ci 98a8e1175bSopenharmony_ci if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) { 99a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 100a8e1175bSopenharmony_ci goto cleanup; 101a8e1175bSopenharmony_ci } 102a8e1175bSopenharmony_ci 103a8e1175bSopenharmony_ci /* After this operation, T holds the largest odd divisor of DE - 1. */ 104a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order)); 105a8e1175bSopenharmony_ci 106a8e1175bSopenharmony_ci /* 107a8e1175bSopenharmony_ci * Actual work 108a8e1175bSopenharmony_ci */ 109a8e1175bSopenharmony_ci 110a8e1175bSopenharmony_ci /* Skip trying 2 if N == 1 mod 8 */ 111a8e1175bSopenharmony_ci attempt = 0; 112a8e1175bSopenharmony_ci if (N->p[0] % 8 == 1) { 113a8e1175bSopenharmony_ci attempt = 1; 114a8e1175bSopenharmony_ci } 115a8e1175bSopenharmony_ci 116a8e1175bSopenharmony_ci for (; attempt < num_primes; ++attempt) { 117a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt])); 118a8e1175bSopenharmony_ci 119a8e1175bSopenharmony_ci /* Check if gcd(K,N) = 1 */ 120a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N)); 121a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(P, 1) != 0) { 122a8e1175bSopenharmony_ci continue; 123a8e1175bSopenharmony_ci } 124a8e1175bSopenharmony_ci 125a8e1175bSopenharmony_ci /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... 126a8e1175bSopenharmony_ci * and check whether they have nontrivial GCD with N. */ 127a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N, 128a8e1175bSopenharmony_ci Q /* temporarily use Q for storing Montgomery 129a8e1175bSopenharmony_ci * multiplication helper values */)); 130a8e1175bSopenharmony_ci 131a8e1175bSopenharmony_ci for (iter = 1; iter <= order; ++iter) { 132a8e1175bSopenharmony_ci /* If we reach 1 prematurely, there's no point 133a8e1175bSopenharmony_ci * in continuing to square K */ 134a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&K, 1) == 0) { 135a8e1175bSopenharmony_ci break; 136a8e1175bSopenharmony_ci } 137a8e1175bSopenharmony_ci 138a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1)); 139a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N)); 140a8e1175bSopenharmony_ci 141a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(P, 1) == 1 && 142a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(P, N) == -1) { 143a8e1175bSopenharmony_ci /* 144a8e1175bSopenharmony_ci * Have found a nontrivial divisor P of N. 145a8e1175bSopenharmony_ci * Set Q := N / P. 146a8e1175bSopenharmony_ci */ 147a8e1175bSopenharmony_ci 148a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P)); 149a8e1175bSopenharmony_ci goto cleanup; 150a8e1175bSopenharmony_ci } 151a8e1175bSopenharmony_ci 152a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); 153a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K)); 154a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N)); 155a8e1175bSopenharmony_ci } 156a8e1175bSopenharmony_ci 157a8e1175bSopenharmony_ci /* 158a8e1175bSopenharmony_ci * If we get here, then either we prematurely aborted the loop because 159a8e1175bSopenharmony_ci * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must 160a8e1175bSopenharmony_ci * be 1 if D,E,N were consistent. 161a8e1175bSopenharmony_ci * Check if that's the case and abort if not, to avoid very long, 162a8e1175bSopenharmony_ci * yet eventually failing, computations if N,D,E were not sane. 163a8e1175bSopenharmony_ci */ 164a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&K, 1) != 0) { 165a8e1175bSopenharmony_ci break; 166a8e1175bSopenharmony_ci } 167a8e1175bSopenharmony_ci } 168a8e1175bSopenharmony_ci 169a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 170a8e1175bSopenharmony_ci 171a8e1175bSopenharmony_cicleanup: 172a8e1175bSopenharmony_ci 173a8e1175bSopenharmony_ci mbedtls_mpi_free(&K); 174a8e1175bSopenharmony_ci mbedtls_mpi_free(&T); 175a8e1175bSopenharmony_ci return ret; 176a8e1175bSopenharmony_ci} 177a8e1175bSopenharmony_ci 178a8e1175bSopenharmony_ci/* 179a8e1175bSopenharmony_ci * Given P, Q and the public exponent E, deduce D. 180a8e1175bSopenharmony_ci * This is essentially a modular inversion. 181a8e1175bSopenharmony_ci */ 182a8e1175bSopenharmony_ciint mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P, 183a8e1175bSopenharmony_ci mbedtls_mpi const *Q, 184a8e1175bSopenharmony_ci mbedtls_mpi const *E, 185a8e1175bSopenharmony_ci mbedtls_mpi *D) 186a8e1175bSopenharmony_ci{ 187a8e1175bSopenharmony_ci int ret = 0; 188a8e1175bSopenharmony_ci mbedtls_mpi K, L; 189a8e1175bSopenharmony_ci 190a8e1175bSopenharmony_ci if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) { 191a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 192a8e1175bSopenharmony_ci } 193a8e1175bSopenharmony_ci 194a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(P, 1) <= 0 || 195a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(Q, 1) <= 0 || 196a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(E, 0) == 0) { 197a8e1175bSopenharmony_ci return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 198a8e1175bSopenharmony_ci } 199a8e1175bSopenharmony_ci 200a8e1175bSopenharmony_ci mbedtls_mpi_init(&K); 201a8e1175bSopenharmony_ci mbedtls_mpi_init(&L); 202a8e1175bSopenharmony_ci 203a8e1175bSopenharmony_ci /* Temporarily put K := P-1 and L := Q-1 */ 204a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); 205a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1)); 206a8e1175bSopenharmony_ci 207a8e1175bSopenharmony_ci /* Temporarily put D := gcd(P-1, Q-1) */ 208a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L)); 209a8e1175bSopenharmony_ci 210a8e1175bSopenharmony_ci /* K := LCM(P-1, Q-1) */ 211a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L)); 212a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D)); 213a8e1175bSopenharmony_ci 214a8e1175bSopenharmony_ci /* Compute modular inverse of E in LCM(P-1, Q-1) */ 215a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K)); 216a8e1175bSopenharmony_ci 217a8e1175bSopenharmony_cicleanup: 218a8e1175bSopenharmony_ci 219a8e1175bSopenharmony_ci mbedtls_mpi_free(&K); 220a8e1175bSopenharmony_ci mbedtls_mpi_free(&L); 221a8e1175bSopenharmony_ci 222a8e1175bSopenharmony_ci return ret; 223a8e1175bSopenharmony_ci} 224a8e1175bSopenharmony_ci 225a8e1175bSopenharmony_ciint mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, 226a8e1175bSopenharmony_ci const mbedtls_mpi *D, mbedtls_mpi *DP, 227a8e1175bSopenharmony_ci mbedtls_mpi *DQ, mbedtls_mpi *QP) 228a8e1175bSopenharmony_ci{ 229a8e1175bSopenharmony_ci int ret = 0; 230a8e1175bSopenharmony_ci mbedtls_mpi K; 231a8e1175bSopenharmony_ci mbedtls_mpi_init(&K); 232a8e1175bSopenharmony_ci 233a8e1175bSopenharmony_ci /* DP = D mod P-1 */ 234a8e1175bSopenharmony_ci if (DP != NULL) { 235a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); 236a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K)); 237a8e1175bSopenharmony_ci } 238a8e1175bSopenharmony_ci 239a8e1175bSopenharmony_ci /* DQ = D mod Q-1 */ 240a8e1175bSopenharmony_ci if (DQ != NULL) { 241a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1)); 242a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K)); 243a8e1175bSopenharmony_ci } 244a8e1175bSopenharmony_ci 245a8e1175bSopenharmony_ci /* QP = Q^{-1} mod P */ 246a8e1175bSopenharmony_ci if (QP != NULL) { 247a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P)); 248a8e1175bSopenharmony_ci } 249a8e1175bSopenharmony_ci 250a8e1175bSopenharmony_cicleanup: 251a8e1175bSopenharmony_ci mbedtls_mpi_free(&K); 252a8e1175bSopenharmony_ci 253a8e1175bSopenharmony_ci return ret; 254a8e1175bSopenharmony_ci} 255a8e1175bSopenharmony_ci 256a8e1175bSopenharmony_ci/* 257a8e1175bSopenharmony_ci * Check that core RSA parameters are sane. 258a8e1175bSopenharmony_ci */ 259a8e1175bSopenharmony_ciint mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P, 260a8e1175bSopenharmony_ci const mbedtls_mpi *Q, const mbedtls_mpi *D, 261a8e1175bSopenharmony_ci const mbedtls_mpi *E, 262a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 263a8e1175bSopenharmony_ci void *p_rng) 264a8e1175bSopenharmony_ci{ 265a8e1175bSopenharmony_ci int ret = 0; 266a8e1175bSopenharmony_ci mbedtls_mpi K, L; 267a8e1175bSopenharmony_ci 268a8e1175bSopenharmony_ci mbedtls_mpi_init(&K); 269a8e1175bSopenharmony_ci mbedtls_mpi_init(&L); 270a8e1175bSopenharmony_ci 271a8e1175bSopenharmony_ci /* 272a8e1175bSopenharmony_ci * Step 1: If PRNG provided, check that P and Q are prime 273a8e1175bSopenharmony_ci */ 274a8e1175bSopenharmony_ci 275a8e1175bSopenharmony_ci#if defined(MBEDTLS_GENPRIME) 276a8e1175bSopenharmony_ci /* 277a8e1175bSopenharmony_ci * When generating keys, the strongest security we support aims for an error 278a8e1175bSopenharmony_ci * rate of at most 2^-100 and we are aiming for the same certainty here as 279a8e1175bSopenharmony_ci * well. 280a8e1175bSopenharmony_ci */ 281a8e1175bSopenharmony_ci if (f_rng != NULL && P != NULL && 282a8e1175bSopenharmony_ci (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) { 283a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 284a8e1175bSopenharmony_ci goto cleanup; 285a8e1175bSopenharmony_ci } 286a8e1175bSopenharmony_ci 287a8e1175bSopenharmony_ci if (f_rng != NULL && Q != NULL && 288a8e1175bSopenharmony_ci (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) { 289a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 290a8e1175bSopenharmony_ci goto cleanup; 291a8e1175bSopenharmony_ci } 292a8e1175bSopenharmony_ci#else 293a8e1175bSopenharmony_ci ((void) f_rng); 294a8e1175bSopenharmony_ci ((void) p_rng); 295a8e1175bSopenharmony_ci#endif /* MBEDTLS_GENPRIME */ 296a8e1175bSopenharmony_ci 297a8e1175bSopenharmony_ci /* 298a8e1175bSopenharmony_ci * Step 2: Check that 1 < N = P * Q 299a8e1175bSopenharmony_ci */ 300a8e1175bSopenharmony_ci 301a8e1175bSopenharmony_ci if (P != NULL && Q != NULL && N != NULL) { 302a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q)); 303a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(N, 1) <= 0 || 304a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(&K, N) != 0) { 305a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 306a8e1175bSopenharmony_ci goto cleanup; 307a8e1175bSopenharmony_ci } 308a8e1175bSopenharmony_ci } 309a8e1175bSopenharmony_ci 310a8e1175bSopenharmony_ci /* 311a8e1175bSopenharmony_ci * Step 3: Check and 1 < D, E < N if present. 312a8e1175bSopenharmony_ci */ 313a8e1175bSopenharmony_ci 314a8e1175bSopenharmony_ci if (N != NULL && D != NULL && E != NULL) { 315a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(D, 1) <= 0 || 316a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(E, 1) <= 0 || 317a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(D, N) >= 0 || 318a8e1175bSopenharmony_ci mbedtls_mpi_cmp_mpi(E, N) >= 0) { 319a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 320a8e1175bSopenharmony_ci goto cleanup; 321a8e1175bSopenharmony_ci } 322a8e1175bSopenharmony_ci } 323a8e1175bSopenharmony_ci 324a8e1175bSopenharmony_ci /* 325a8e1175bSopenharmony_ci * Step 4: Check that D, E are inverse modulo P-1 and Q-1 326a8e1175bSopenharmony_ci */ 327a8e1175bSopenharmony_ci 328a8e1175bSopenharmony_ci if (P != NULL && Q != NULL && D != NULL && E != NULL) { 329a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(P, 1) <= 0 || 330a8e1175bSopenharmony_ci mbedtls_mpi_cmp_int(Q, 1) <= 0) { 331a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 332a8e1175bSopenharmony_ci goto cleanup; 333a8e1175bSopenharmony_ci } 334a8e1175bSopenharmony_ci 335a8e1175bSopenharmony_ci /* Compute DE-1 mod P-1 */ 336a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E)); 337a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); 338a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1)); 339a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L)); 340a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&K, 0) != 0) { 341a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 342a8e1175bSopenharmony_ci goto cleanup; 343a8e1175bSopenharmony_ci } 344a8e1175bSopenharmony_ci 345a8e1175bSopenharmony_ci /* Compute DE-1 mod Q-1 */ 346a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E)); 347a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); 348a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1)); 349a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L)); 350a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&K, 0) != 0) { 351a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 352a8e1175bSopenharmony_ci goto cleanup; 353a8e1175bSopenharmony_ci } 354a8e1175bSopenharmony_ci } 355a8e1175bSopenharmony_ci 356a8e1175bSopenharmony_cicleanup: 357a8e1175bSopenharmony_ci 358a8e1175bSopenharmony_ci mbedtls_mpi_free(&K); 359a8e1175bSopenharmony_ci mbedtls_mpi_free(&L); 360a8e1175bSopenharmony_ci 361a8e1175bSopenharmony_ci /* Wrap MPI error codes by RSA check failure error code */ 362a8e1175bSopenharmony_ci if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) { 363a8e1175bSopenharmony_ci ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 364a8e1175bSopenharmony_ci } 365a8e1175bSopenharmony_ci 366a8e1175bSopenharmony_ci return ret; 367a8e1175bSopenharmony_ci} 368a8e1175bSopenharmony_ci 369a8e1175bSopenharmony_ci/* 370a8e1175bSopenharmony_ci * Check that RSA CRT parameters are in accordance with core parameters. 371a8e1175bSopenharmony_ci */ 372a8e1175bSopenharmony_ciint mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, 373a8e1175bSopenharmony_ci const mbedtls_mpi *D, const mbedtls_mpi *DP, 374a8e1175bSopenharmony_ci const mbedtls_mpi *DQ, const mbedtls_mpi *QP) 375a8e1175bSopenharmony_ci{ 376a8e1175bSopenharmony_ci int ret = 0; 377a8e1175bSopenharmony_ci 378a8e1175bSopenharmony_ci mbedtls_mpi K, L; 379a8e1175bSopenharmony_ci mbedtls_mpi_init(&K); 380a8e1175bSopenharmony_ci mbedtls_mpi_init(&L); 381a8e1175bSopenharmony_ci 382a8e1175bSopenharmony_ci /* Check that DP - D == 0 mod P - 1 */ 383a8e1175bSopenharmony_ci if (DP != NULL) { 384a8e1175bSopenharmony_ci if (P == NULL) { 385a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; 386a8e1175bSopenharmony_ci goto cleanup; 387a8e1175bSopenharmony_ci } 388a8e1175bSopenharmony_ci 389a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); 390a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D)); 391a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); 392a8e1175bSopenharmony_ci 393a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&L, 0) != 0) { 394a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 395a8e1175bSopenharmony_ci goto cleanup; 396a8e1175bSopenharmony_ci } 397a8e1175bSopenharmony_ci } 398a8e1175bSopenharmony_ci 399a8e1175bSopenharmony_ci /* Check that DQ - D == 0 mod Q - 1 */ 400a8e1175bSopenharmony_ci if (DQ != NULL) { 401a8e1175bSopenharmony_ci if (Q == NULL) { 402a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; 403a8e1175bSopenharmony_ci goto cleanup; 404a8e1175bSopenharmony_ci } 405a8e1175bSopenharmony_ci 406a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1)); 407a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D)); 408a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); 409a8e1175bSopenharmony_ci 410a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&L, 0) != 0) { 411a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 412a8e1175bSopenharmony_ci goto cleanup; 413a8e1175bSopenharmony_ci } 414a8e1175bSopenharmony_ci } 415a8e1175bSopenharmony_ci 416a8e1175bSopenharmony_ci /* Check that QP * Q - 1 == 0 mod P */ 417a8e1175bSopenharmony_ci if (QP != NULL) { 418a8e1175bSopenharmony_ci if (P == NULL || Q == NULL) { 419a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; 420a8e1175bSopenharmony_ci goto cleanup; 421a8e1175bSopenharmony_ci } 422a8e1175bSopenharmony_ci 423a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q)); 424a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); 425a8e1175bSopenharmony_ci MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P)); 426a8e1175bSopenharmony_ci if (mbedtls_mpi_cmp_int(&K, 0) != 0) { 427a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 428a8e1175bSopenharmony_ci goto cleanup; 429a8e1175bSopenharmony_ci } 430a8e1175bSopenharmony_ci } 431a8e1175bSopenharmony_ci 432a8e1175bSopenharmony_cicleanup: 433a8e1175bSopenharmony_ci 434a8e1175bSopenharmony_ci /* Wrap MPI error codes by RSA check failure error code */ 435a8e1175bSopenharmony_ci if (ret != 0 && 436a8e1175bSopenharmony_ci ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && 437a8e1175bSopenharmony_ci ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) { 438a8e1175bSopenharmony_ci ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 439a8e1175bSopenharmony_ci } 440a8e1175bSopenharmony_ci 441a8e1175bSopenharmony_ci mbedtls_mpi_free(&K); 442a8e1175bSopenharmony_ci mbedtls_mpi_free(&L); 443a8e1175bSopenharmony_ci 444a8e1175bSopenharmony_ci return ret; 445a8e1175bSopenharmony_ci} 446a8e1175bSopenharmony_ci 447a8e1175bSopenharmony_ci#endif /* MBEDTLS_RSA_C */ 448