blob: 50a5c4e0d74fa145e80cf414b3e033cc00443bbd [file] [log] [blame]
Hanno Beckera565f542017-10-11 11:00:19 +01001/*
2 * Helper functions for the RSA module
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Hanno Beckera565f542017-10-11 11:00:19 +01006 *
Hanno Beckera565f542017-10-11 11:00:19 +01007 */
8
Gilles Peskinedb09ef62020-06-03 01:43:33 +02009#include "common.h"
Hanno Beckera565f542017-10-11 11:00:19 +010010
11#if defined(MBEDTLS_RSA_C)
12
13#include "mbedtls/rsa.h"
14#include "mbedtls/bignum.h"
Manuel Pégourié-Gonnard7dcfd732025-07-10 09:57:29 +020015#include "bignum_internal.h"
Chris Jones66a4cd42021-03-09 16:04:12 +000016#include "rsa_alt_helpers.h"
Hanno Beckera565f542017-10-11 11:00:19 +010017
18/*
19 * Compute RSA prime factors from public and private exponents
20 *
21 * Summary of algorithm:
22 * Setting F := lcm(P-1,Q-1), the idea is as follows:
23 *
24 * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)
25 * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the
26 * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four
27 * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)
28 * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime
29 * factors of N.
30 *
31 * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same
32 * construction still applies since (-)^K is the identity on the set of
33 * roots of 1 in Z/NZ.
34 *
35 * The public and private key primitives (-)^E and (-)^D are mutually inverse
36 * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.
37 * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.
38 * Splitting L = 2^t * K with K odd, we have
39 *
40 * DE - 1 = FL = (F/2) * (2^(t+1)) * K,
41 *
42 * so (F / 2) * K is among the numbers
43 *
44 * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord
45 *
46 * where ord is the order of 2 in (DE - 1).
47 * We can therefore iterate through these numbers apply the construction
48 * of (a) and (b) above to attempt to factor N.
49 *
50 */
Gilles Peskine449bd832023-01-11 14:50:10 +010051int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N,
52 mbedtls_mpi const *E, mbedtls_mpi const *D,
53 mbedtls_mpi *P, mbedtls_mpi *Q)
Hanno Beckera565f542017-10-11 11:00:19 +010054{
55 int ret = 0;
56
57 uint16_t attempt; /* Number of current attempt */
58 uint16_t iter; /* Number of squares computed in the current attempt */
59
60 uint16_t order; /* Order of 2 in DE - 1 */
61
62 mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */
63 mbedtls_mpi K; /* Temporary holding the current candidate */
64
Hanno Becker4055a3a2017-10-17 09:15:26 +010065 const unsigned char primes[] = { 2,
Gilles Peskine449bd832023-01-11 14:50:10 +010066 3, 5, 7, 11, 13, 17, 19, 23,
67 29, 31, 37, 41, 43, 47, 53, 59,
68 61, 67, 71, 73, 79, 83, 89, 97,
69 101, 103, 107, 109, 113, 127, 131, 137,
70 139, 149, 151, 157, 163, 167, 173, 179,
71 181, 191, 193, 197, 199, 211, 223, 227,
72 229, 233, 239, 241, 251 };
Hanno Beckera565f542017-10-11 11:00:19 +010073
Gilles Peskine449bd832023-01-11 14:50:10 +010074 const size_t num_primes = sizeof(primes) / sizeof(*primes);
Hanno Beckera565f542017-10-11 11:00:19 +010075
Gilles Peskine449bd832023-01-11 14:50:10 +010076 if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) {
77 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
78 }
Hanno Beckera565f542017-10-11 11:00:19 +010079
Gilles Peskine449bd832023-01-11 14:50:10 +010080 if (mbedtls_mpi_cmp_int(N, 0) <= 0 ||
81 mbedtls_mpi_cmp_int(D, 1) <= 0 ||
82 mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
83 mbedtls_mpi_cmp_int(E, 1) <= 0 ||
84 mbedtls_mpi_cmp_mpi(E, N) >= 0) {
85 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Hanno Beckera565f542017-10-11 11:00:19 +010086 }
87
88 /*
89 * Initializations and temporary changes
90 */
91
Gilles Peskine449bd832023-01-11 14:50:10 +010092 mbedtls_mpi_init(&K);
93 mbedtls_mpi_init(&T);
Hanno Beckera565f542017-10-11 11:00:19 +010094
95 /* T := DE - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +010096 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D, E));
97 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1));
Hanno Beckera565f542017-10-11 11:00:19 +010098
Gilles Peskine449bd832023-01-11 14:50:10 +010099 if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100100 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
101 goto cleanup;
102 }
103
104 /* After this operation, T holds the largest odd divisor of DE - 1. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100105 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order));
Hanno Beckera565f542017-10-11 11:00:19 +0100106
107 /*
108 * Actual work
109 */
110
111 /* Skip trying 2 if N == 1 mod 8 */
112 attempt = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 if (N->p[0] % 8 == 1) {
Hanno Beckera565f542017-10-11 11:00:19 +0100114 attempt = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 }
Hanno Beckera565f542017-10-11 11:00:19 +0100116
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 for (; attempt < num_primes; ++attempt) {
Chien Wonge2caf412023-08-01 21:38:46 +0800118 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt]));
Hanno Beckera565f542017-10-11 11:00:19 +0100119
120 /* Check if gcd(K,N) = 1 */
Manuel Pégourié-Gonnard7dcfd732025-07-10 09:57:29 +0200121 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(P, NULL, &K, N));
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 if (mbedtls_mpi_cmp_int(P, 1) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100123 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100124 }
Hanno Beckera565f542017-10-11 11:00:19 +0100125
126 /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...
127 * and check whether they have nontrivial GCD with N. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100128 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N,
129 Q /* temporarily use Q for storing Montgomery
130 * multiplication helper values */));
Hanno Beckera565f542017-10-11 11:00:19 +0100131
Gilles Peskine449bd832023-01-11 14:50:10 +0100132 for (iter = 1; iter <= order; ++iter) {
Hanno Becker5d42b532017-10-11 15:58:00 +0100133 /* If we reach 1 prematurely, there's no point
134 * in continuing to square K */
Gilles Peskine449bd832023-01-11 14:50:10 +0100135 if (mbedtls_mpi_cmp_int(&K, 1) == 0) {
Hanno Becker5d42b532017-10-11 15:58:00 +0100136 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 }
Hanno Becker5d42b532017-10-11 15:58:00 +0100138
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1));
Manuel Pégourié-Gonnard7dcfd732025-07-10 09:57:29 +0200140 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(P, NULL, &K, N));
Hanno Beckera565f542017-10-11 11:00:19 +0100141
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 if (mbedtls_mpi_cmp_int(P, 1) == 1 &&
143 mbedtls_mpi_cmp_mpi(P, N) == -1) {
Hanno Beckera565f542017-10-11 11:00:19 +0100144 /*
145 * Have found a nontrivial divisor P of N.
146 * Set Q := N / P.
147 */
148
Gilles Peskine449bd832023-01-11 14:50:10 +0100149 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P));
Hanno Beckera565f542017-10-11 11:00:19 +0100150 goto cleanup;
151 }
152
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
154 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K));
155 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N));
Hanno Beckera565f542017-10-11 11:00:19 +0100156 }
Hanno Becker14a00c02017-10-11 12:58:23 +0100157
Hanno Becker5d42b532017-10-11 15:58:00 +0100158 /*
159 * If we get here, then either we prematurely aborted the loop because
160 * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must
161 * be 1 if D,E,N were consistent.
162 * Check if that's the case and abort if not, to avoid very long,
163 * yet eventually failing, computations if N,D,E were not sane.
164 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100165 if (mbedtls_mpi_cmp_int(&K, 1) != 0) {
Hanno Becker14a00c02017-10-11 12:58:23 +0100166 break;
167 }
Hanno Beckera565f542017-10-11 11:00:19 +0100168 }
169
170 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
171
172cleanup:
173
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 mbedtls_mpi_free(&K);
175 mbedtls_mpi_free(&T);
176 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100177}
178
179/*
180 * Given P, Q and the public exponent E, deduce D.
181 * This is essentially a modular inversion.
182 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100183int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P,
184 mbedtls_mpi const *Q,
185 mbedtls_mpi const *E,
186 mbedtls_mpi *D)
Hanno Beckera565f542017-10-11 11:00:19 +0100187{
188 int ret = 0;
189 mbedtls_mpi K, L;
190
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) {
192 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Hanno Beckera565f542017-10-11 11:00:19 +0100193 }
194
Gilles Peskine449bd832023-01-11 14:50:10 +0100195 if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
196 mbedtls_mpi_cmp_int(Q, 1) <= 0 ||
197 mbedtls_mpi_cmp_int(E, 0) == 0) {
198 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
199 }
200
Manuel Pégourié-Gonnard9e1c5322025-08-13 14:14:19 +0200201 if (mbedtls_mpi_get_bit(E, 0) != 1) {
202 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
203 }
204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 mbedtls_mpi_init(&K);
206 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100207
208 /* Temporarily put K := P-1 and L := Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
210 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
Hanno Beckera565f542017-10-11 11:00:19 +0100211
212 /* Temporarily put D := gcd(P-1, Q-1) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100213 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L));
Hanno Beckera565f542017-10-11 11:00:19 +0100214
215 /* K := LCM(P-1, Q-1) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L));
217 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D));
Hanno Beckera565f542017-10-11 11:00:19 +0100218
Manuel Pégourié-Gonnarda4bf6802025-07-10 10:48:23 +0200219 /* Compute modular inverse of E mod LCM(P-1, Q-1)
220 * This is FIPS 186-4 §B.3.1 criterion 3(b).
221 * This will return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if E is not coprime to
222 * (P-1)(Q-1), also validating FIPS 186-4 §B.3.1 criterion 2(a). */
Manuel Pégourié-Gonnard9e1c5322025-08-13 14:14:19 +0200223 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod_even_in_range(D, E, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100224
225cleanup:
226
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 mbedtls_mpi_free(&K);
228 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100229
Gilles Peskine449bd832023-01-11 14:50:10 +0100230 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100231}
232
Gilles Peskine449bd832023-01-11 14:50:10 +0100233int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
234 const mbedtls_mpi *D, mbedtls_mpi *DP,
235 mbedtls_mpi *DQ, mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100236{
237 int ret = 0;
Chris Jones66a4cd42021-03-09 16:04:12 +0000238 mbedtls_mpi K;
Gilles Peskine449bd832023-01-11 14:50:10 +0100239 mbedtls_mpi_init(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100240
Chris Jones66a4cd42021-03-09 16:04:12 +0000241 /* DP = D mod P-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 if (DP != NULL) {
243 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
244 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100245 }
246
Chris Jones66a4cd42021-03-09 16:04:12 +0000247 /* DQ = D mod Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 if (DQ != NULL) {
249 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
250 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100251 }
252
Chris Jones66a4cd42021-03-09 16:04:12 +0000253 /* QP = Q^{-1} mod P */
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 if (QP != NULL) {
Manuel Pégourié-Gonnard630148e2025-08-13 13:57:35 +0200255 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod_odd(QP, Q, P));
Hanno Beckera565f542017-10-11 11:00:19 +0100256 }
257
258cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 mbedtls_mpi_free(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100260
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100262}
263
264/*
265 * Check that core RSA parameters are sane.
266 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100267int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
268 const mbedtls_mpi *Q, const mbedtls_mpi *D,
269 const mbedtls_mpi *E,
270 int (*f_rng)(void *, unsigned char *, size_t),
271 void *p_rng)
Hanno Beckera565f542017-10-11 11:00:19 +0100272{
273 int ret = 0;
274 mbedtls_mpi K, L;
275
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 mbedtls_mpi_init(&K);
277 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100278
279 /*
280 * Step 1: If PRNG provided, check that P and Q are prime
281 */
282
283#if defined(MBEDTLS_GENPRIME)
Janos Follatha0b67c22018-09-18 14:48:23 +0100284 /*
285 * When generating keys, the strongest security we support aims for an error
286 * rate of at most 2^-100 and we are aiming for the same certainty here as
287 * well.
288 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 if (f_rng != NULL && P != NULL &&
290 (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100291 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
292 goto cleanup;
293 }
294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 if (f_rng != NULL && Q != NULL &&
296 (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100297 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
298 goto cleanup;
299 }
300#else
301 ((void) f_rng);
302 ((void) p_rng);
303#endif /* MBEDTLS_GENPRIME */
304
305 /*
Hanno Beckerf8c028a2017-10-17 09:20:57 +0100306 * Step 2: Check that 1 < N = P * Q
Hanno Beckera565f542017-10-11 11:00:19 +0100307 */
308
Gilles Peskine449bd832023-01-11 14:50:10 +0100309 if (P != NULL && Q != NULL && N != NULL) {
310 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));
311 if (mbedtls_mpi_cmp_int(N, 1) <= 0 ||
312 mbedtls_mpi_cmp_mpi(&K, N) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100313 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
314 goto cleanup;
315 }
316 }
317
318 /*
319 * Step 3: Check and 1 < D, E < N if present.
320 */
321
Gilles Peskine449bd832023-01-11 14:50:10 +0100322 if (N != NULL && D != NULL && E != NULL) {
323 if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||
324 mbedtls_mpi_cmp_int(E, 1) <= 0 ||
325 mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
326 mbedtls_mpi_cmp_mpi(E, N) >= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100327 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
328 goto cleanup;
329 }
330 }
331
332 /*
333 * Step 4: Check that D, E are inverse modulo P-1 and Q-1
334 */
335
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 if (P != NULL && Q != NULL && D != NULL && E != NULL) {
337 if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
338 mbedtls_mpi_cmp_int(Q, 1) <= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100339 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
340 goto cleanup;
341 }
342
343 /* Compute DE-1 mod P-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100344 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
345 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
346 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));
347 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
348 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100349 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
350 goto cleanup;
351 }
352
353 /* Compute DE-1 mod Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
355 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
356 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
357 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
358 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100359 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
360 goto cleanup;
361 }
362 }
363
364cleanup:
365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 mbedtls_mpi_free(&K);
367 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100368
369 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {
Hanno Beckera565f542017-10-11 11:00:19 +0100371 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
372 }
373
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100375}
376
Chris Jones66a4cd42021-03-09 16:04:12 +0000377/*
378 * Check that RSA CRT parameters are in accordance with core parameters.
379 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100380int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
381 const mbedtls_mpi *D, const mbedtls_mpi *DP,
382 const mbedtls_mpi *DQ, const mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100383{
384 int ret = 0;
Hanno Beckera565f542017-10-11 11:00:19 +0100385
Chris Jones66a4cd42021-03-09 16:04:12 +0000386 mbedtls_mpi K, L;
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 mbedtls_mpi_init(&K);
388 mbedtls_mpi_init(&L);
Chris Jones66a4cd42021-03-09 16:04:12 +0000389
390 /* Check that DP - D == 0 mod P - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100391 if (DP != NULL) {
392 if (P == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000393 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
394 goto cleanup;
395 }
396
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
398 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));
399 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000400
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000402 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
403 goto cleanup;
404 }
Hanno Beckera565f542017-10-11 11:00:19 +0100405 }
406
Chris Jones66a4cd42021-03-09 16:04:12 +0000407 /* Check that DQ - D == 0 mod Q - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100408 if (DQ != NULL) {
409 if (Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000410 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
411 goto cleanup;
412 }
413
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
415 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));
416 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000417
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000419 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
420 goto cleanup;
421 }
Hanno Beckera565f542017-10-11 11:00:19 +0100422 }
423
Chris Jones66a4cd42021-03-09 16:04:12 +0000424 /* Check that QP * Q - 1 == 0 mod P */
Gilles Peskine449bd832023-01-11 14:50:10 +0100425 if (QP != NULL) {
426 if (P == NULL || Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000427 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
428 goto cleanup;
429 }
430
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));
432 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
433 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));
434 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000435 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
436 goto cleanup;
437 }
Hanno Beckera565f542017-10-11 11:00:19 +0100438 }
439
440cleanup:
Chris Jones66a4cd42021-03-09 16:04:12 +0000441
442 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine449bd832023-01-11 14:50:10 +0100443 if (ret != 0 &&
Chris Jones66a4cd42021-03-09 16:04:12 +0000444 ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000446 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
447 }
448
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 mbedtls_mpi_free(&K);
450 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100451
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100453}
454
455#endif /* MBEDTLS_RSA_C */