blob: 5c265a9921b5174ce5b20fdc5c5b75377fed7c17 [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"
Chris Jones66a4cd42021-03-09 16:04:12 +000015#include "rsa_alt_helpers.h"
Hanno Beckera565f542017-10-11 11:00:19 +010016
17/*
18 * Compute RSA prime factors from public and private exponents
19 *
20 * Summary of algorithm:
21 * Setting F := lcm(P-1,Q-1), the idea is as follows:
22 *
23 * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)
24 * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the
25 * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four
26 * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)
27 * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime
28 * factors of N.
29 *
30 * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same
31 * construction still applies since (-)^K is the identity on the set of
32 * roots of 1 in Z/NZ.
33 *
34 * The public and private key primitives (-)^E and (-)^D are mutually inverse
35 * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.
36 * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.
37 * Splitting L = 2^t * K with K odd, we have
38 *
39 * DE - 1 = FL = (F/2) * (2^(t+1)) * K,
40 *
41 * so (F / 2) * K is among the numbers
42 *
43 * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord
44 *
45 * where ord is the order of 2 in (DE - 1).
46 * We can therefore iterate through these numbers apply the construction
47 * of (a) and (b) above to attempt to factor N.
48 *
49 */
Gilles Peskine449bd832023-01-11 14:50:10 +010050int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N,
51 mbedtls_mpi const *E, mbedtls_mpi const *D,
52 mbedtls_mpi *P, mbedtls_mpi *Q)
Hanno Beckera565f542017-10-11 11:00:19 +010053{
54 int ret = 0;
55
56 uint16_t attempt; /* Number of current attempt */
57 uint16_t iter; /* Number of squares computed in the current attempt */
58
59 uint16_t order; /* Order of 2 in DE - 1 */
60
61 mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */
62 mbedtls_mpi K; /* Temporary holding the current candidate */
63
Hanno Becker4055a3a2017-10-17 09:15:26 +010064 const unsigned char primes[] = { 2,
Gilles Peskine449bd832023-01-11 14:50:10 +010065 3, 5, 7, 11, 13, 17, 19, 23,
66 29, 31, 37, 41, 43, 47, 53, 59,
67 61, 67, 71, 73, 79, 83, 89, 97,
68 101, 103, 107, 109, 113, 127, 131, 137,
69 139, 149, 151, 157, 163, 167, 173, 179,
70 181, 191, 193, 197, 199, 211, 223, 227,
71 229, 233, 239, 241, 251 };
Hanno Beckera565f542017-10-11 11:00:19 +010072
Gilles Peskine449bd832023-01-11 14:50:10 +010073 const size_t num_primes = sizeof(primes) / sizeof(*primes);
Hanno Beckera565f542017-10-11 11:00:19 +010074
Gilles Peskine449bd832023-01-11 14:50:10 +010075 if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) {
76 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
77 }
Hanno Beckera565f542017-10-11 11:00:19 +010078
Gilles Peskine449bd832023-01-11 14:50:10 +010079 if (mbedtls_mpi_cmp_int(N, 0) <= 0 ||
80 mbedtls_mpi_cmp_int(D, 1) <= 0 ||
81 mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
82 mbedtls_mpi_cmp_int(E, 1) <= 0 ||
83 mbedtls_mpi_cmp_mpi(E, N) >= 0) {
84 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Hanno Beckera565f542017-10-11 11:00:19 +010085 }
86
87 /*
88 * Initializations and temporary changes
89 */
90
Gilles Peskine449bd832023-01-11 14:50:10 +010091 mbedtls_mpi_init(&K);
92 mbedtls_mpi_init(&T);
Hanno Beckera565f542017-10-11 11:00:19 +010093
94 /* T := DE - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +010095 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D, E));
96 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1));
Hanno Beckera565f542017-10-11 11:00:19 +010097
Gilles Peskine449bd832023-01-11 14:50:10 +010098 if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) {
Hanno Beckera565f542017-10-11 11:00:19 +010099 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
100 goto cleanup;
101 }
102
103 /* After this operation, T holds the largest odd divisor of DE - 1. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100104 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order));
Hanno Beckera565f542017-10-11 11:00:19 +0100105
106 /*
107 * Actual work
108 */
109
110 /* Skip trying 2 if N == 1 mod 8 */
111 attempt = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100112 if (N->p[0] % 8 == 1) {
Hanno Beckera565f542017-10-11 11:00:19 +0100113 attempt = 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 }
Hanno Beckera565f542017-10-11 11:00:19 +0100115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 for (; attempt < num_primes; ++attempt) {
Chien Wonge2caf412023-08-01 21:38:46 +0800117 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt]));
Hanno Beckera565f542017-10-11 11:00:19 +0100118
119 /* Check if gcd(K,N) = 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
121 if (mbedtls_mpi_cmp_int(P, 1) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100122 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100123 }
Hanno Beckera565f542017-10-11 11:00:19 +0100124
125 /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...
126 * and check whether they have nontrivial GCD with N. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N,
128 Q /* temporarily use Q for storing Montgomery
129 * multiplication helper values */));
Hanno Beckera565f542017-10-11 11:00:19 +0100130
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 for (iter = 1; iter <= order; ++iter) {
Hanno Becker5d42b532017-10-11 15:58:00 +0100132 /* If we reach 1 prematurely, there's no point
133 * in continuing to square K */
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 if (mbedtls_mpi_cmp_int(&K, 1) == 0) {
Hanno Becker5d42b532017-10-11 15:58:00 +0100135 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 }
Hanno Becker5d42b532017-10-11 15:58:00 +0100137
Gilles Peskine449bd832023-01-11 14:50:10 +0100138 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1));
139 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
Hanno Beckera565f542017-10-11 11:00:19 +0100140
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 if (mbedtls_mpi_cmp_int(P, 1) == 1 &&
142 mbedtls_mpi_cmp_mpi(P, N) == -1) {
Hanno Beckera565f542017-10-11 11:00:19 +0100143 /*
144 * Have found a nontrivial divisor P of N.
145 * Set Q := N / P.
146 */
147
Gilles Peskine449bd832023-01-11 14:50:10 +0100148 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P));
Hanno Beckera565f542017-10-11 11:00:19 +0100149 goto cleanup;
150 }
151
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
153 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K));
154 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N));
Hanno Beckera565f542017-10-11 11:00:19 +0100155 }
Hanno Becker14a00c02017-10-11 12:58:23 +0100156
Hanno Becker5d42b532017-10-11 15:58:00 +0100157 /*
158 * If we get here, then either we prematurely aborted the loop because
159 * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must
160 * be 1 if D,E,N were consistent.
161 * Check if that's the case and abort if not, to avoid very long,
162 * yet eventually failing, computations if N,D,E were not sane.
163 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 if (mbedtls_mpi_cmp_int(&K, 1) != 0) {
Hanno Becker14a00c02017-10-11 12:58:23 +0100165 break;
166 }
Hanno Beckera565f542017-10-11 11:00:19 +0100167 }
168
169 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
170
171cleanup:
172
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 mbedtls_mpi_free(&K);
174 mbedtls_mpi_free(&T);
175 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100176}
177
178/*
179 * Given P, Q and the public exponent E, deduce D.
180 * This is essentially a modular inversion.
181 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100182int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P,
183 mbedtls_mpi const *Q,
184 mbedtls_mpi const *E,
185 mbedtls_mpi *D)
Hanno Beckera565f542017-10-11 11:00:19 +0100186{
187 int ret = 0;
188 mbedtls_mpi K, L;
189
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) {
191 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Hanno Beckera565f542017-10-11 11:00:19 +0100192 }
193
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
195 mbedtls_mpi_cmp_int(Q, 1) <= 0 ||
196 mbedtls_mpi_cmp_int(E, 0) == 0) {
197 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
198 }
199
200 mbedtls_mpi_init(&K);
201 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100202
203 /* Temporarily put K := P-1 and L := Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
205 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
Hanno Beckera565f542017-10-11 11:00:19 +0100206
207 /* Temporarily put D := gcd(P-1, Q-1) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L));
Hanno Beckera565f542017-10-11 11:00:19 +0100209
210 /* K := LCM(P-1, Q-1) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L));
212 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D));
Hanno Beckera565f542017-10-11 11:00:19 +0100213
214 /* Compute modular inverse of E in LCM(P-1, Q-1) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100216
217cleanup:
218
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 mbedtls_mpi_free(&K);
220 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100223}
224
Gilles Peskine449bd832023-01-11 14:50:10 +0100225int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
226 const mbedtls_mpi *D, mbedtls_mpi *DP,
227 mbedtls_mpi *DQ, mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100228{
229 int ret = 0;
Chris Jones66a4cd42021-03-09 16:04:12 +0000230 mbedtls_mpi K;
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 mbedtls_mpi_init(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100232
Chris Jones66a4cd42021-03-09 16:04:12 +0000233 /* DP = D mod P-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 if (DP != NULL) {
235 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
236 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100237 }
238
Chris Jones66a4cd42021-03-09 16:04:12 +0000239 /* DQ = D mod Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 if (DQ != NULL) {
241 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
242 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100243 }
244
Chris Jones66a4cd42021-03-09 16:04:12 +0000245 /* QP = Q^{-1} mod P */
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 if (QP != NULL) {
247 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P));
Hanno Beckera565f542017-10-11 11:00:19 +0100248 }
249
250cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 mbedtls_mpi_free(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100252
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100254}
255
256/*
257 * Check that core RSA parameters are sane.
258 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100259int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
260 const mbedtls_mpi *Q, const mbedtls_mpi *D,
261 const mbedtls_mpi *E,
262 int (*f_rng)(void *, unsigned char *, size_t),
263 void *p_rng)
Hanno Beckera565f542017-10-11 11:00:19 +0100264{
265 int ret = 0;
266 mbedtls_mpi K, L;
267
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 mbedtls_mpi_init(&K);
269 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100270
271 /*
272 * Step 1: If PRNG provided, check that P and Q are prime
273 */
274
275#if defined(MBEDTLS_GENPRIME)
Janos Follatha0b67c22018-09-18 14:48:23 +0100276 /*
277 * When generating keys, the strongest security we support aims for an error
278 * rate of at most 2^-100 and we are aiming for the same certainty here as
279 * well.
280 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 if (f_rng != NULL && P != NULL &&
282 (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100283 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
284 goto cleanup;
285 }
286
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 if (f_rng != NULL && Q != NULL &&
288 (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100289 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
290 goto cleanup;
291 }
292#else
293 ((void) f_rng);
294 ((void) p_rng);
295#endif /* MBEDTLS_GENPRIME */
296
297 /*
Hanno Beckerf8c028a2017-10-17 09:20:57 +0100298 * Step 2: Check that 1 < N = P * Q
Hanno Beckera565f542017-10-11 11:00:19 +0100299 */
300
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 if (P != NULL && Q != NULL && N != NULL) {
302 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));
303 if (mbedtls_mpi_cmp_int(N, 1) <= 0 ||
304 mbedtls_mpi_cmp_mpi(&K, N) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100305 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
306 goto cleanup;
307 }
308 }
309
310 /*
311 * Step 3: Check and 1 < D, E < N if present.
312 */
313
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 if (N != NULL && D != NULL && E != NULL) {
315 if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||
316 mbedtls_mpi_cmp_int(E, 1) <= 0 ||
317 mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
318 mbedtls_mpi_cmp_mpi(E, N) >= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100319 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
320 goto cleanup;
321 }
322 }
323
324 /*
325 * Step 4: Check that D, E are inverse modulo P-1 and Q-1
326 */
327
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 if (P != NULL && Q != NULL && D != NULL && E != NULL) {
329 if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
330 mbedtls_mpi_cmp_int(Q, 1) <= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100331 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
332 goto cleanup;
333 }
334
335 /* Compute DE-1 mod P-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
337 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
338 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));
339 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
340 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100341 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
342 goto cleanup;
343 }
344
345 /* Compute DE-1 mod Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
347 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
348 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
349 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
350 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100351 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
352 goto cleanup;
353 }
354 }
355
356cleanup:
357
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 mbedtls_mpi_free(&K);
359 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100360
361 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {
Hanno Beckera565f542017-10-11 11:00:19 +0100363 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
364 }
365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100367}
368
Chris Jones66a4cd42021-03-09 16:04:12 +0000369/*
370 * Check that RSA CRT parameters are in accordance with core parameters.
371 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100372int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
373 const mbedtls_mpi *D, const mbedtls_mpi *DP,
374 const mbedtls_mpi *DQ, const mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100375{
376 int ret = 0;
Hanno Beckera565f542017-10-11 11:00:19 +0100377
Chris Jones66a4cd42021-03-09 16:04:12 +0000378 mbedtls_mpi K, L;
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 mbedtls_mpi_init(&K);
380 mbedtls_mpi_init(&L);
Chris Jones66a4cd42021-03-09 16:04:12 +0000381
382 /* Check that DP - D == 0 mod P - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 if (DP != NULL) {
384 if (P == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000385 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
386 goto cleanup;
387 }
388
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
390 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));
391 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000392
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000394 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
395 goto cleanup;
396 }
Hanno Beckera565f542017-10-11 11:00:19 +0100397 }
398
Chris Jones66a4cd42021-03-09 16:04:12 +0000399 /* Check that DQ - D == 0 mod Q - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 if (DQ != NULL) {
401 if (Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000402 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
403 goto cleanup;
404 }
405
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
407 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));
408 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000409
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000411 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
412 goto cleanup;
413 }
Hanno Beckera565f542017-10-11 11:00:19 +0100414 }
415
Chris Jones66a4cd42021-03-09 16:04:12 +0000416 /* Check that QP * Q - 1 == 0 mod P */
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 if (QP != NULL) {
418 if (P == NULL || Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000419 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
420 goto cleanup;
421 }
422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));
424 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
425 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));
426 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000427 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
428 goto cleanup;
429 }
Hanno Beckera565f542017-10-11 11:00:19 +0100430 }
431
432cleanup:
Chris Jones66a4cd42021-03-09 16:04:12 +0000433
434 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 if (ret != 0 &&
Chris Jones66a4cd42021-03-09 16:04:12 +0000436 ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000438 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
439 }
440
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 mbedtls_mpi_free(&K);
442 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100445}
446
447#endif /* MBEDTLS_RSA_C */