blob: 5a9e5c34fc06c754e9ec82ae8118ace37d9a0c40 [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 Rodgman7ff79652023-11-03 12:04:52 +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"
15#include "mbedtls/rsa_internal.h"
16
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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +010073 const size_t num_primes = sizeof(primes) / sizeof(*primes);
Hanno Beckera565f542017-10-11 11:00:19 +010074
Gilles Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +010091 mbedtls_mpi_init(&K);
92 mbedtls_mpi_init(&T);
Hanno Beckera565f542017-10-11 11:00:19 +010093
94 /* T := DE - 1 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +0100112 if (N->p[0] % 8 == 1) {
Hanno Beckera565f542017-10-11 11:00:19 +0100113 attempt = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100114 }
Hanno Beckera565f542017-10-11 11:00:19 +0100115
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100116 for (; attempt < num_primes; ++attempt) {
Chien Wong0118a1d2023-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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +0100134 if (mbedtls_mpi_cmp_int(&K, 1) == 0) {
Hanno Becker5d42b532017-10-11 15:58:00 +0100135 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100136 }
Hanno Becker5d42b532017-10-11 15:58:00 +0100137
Gilles Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +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 Peskine1b6c09a2023-01-11 14:52:35 +0100215 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100216
217cleanup:
218
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 mbedtls_mpi_free(&K);
220 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100221
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100222 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100223}
224
225/*
226 * Check that RSA CRT parameters are in accordance with core parameters.
227 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100228int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
229 const mbedtls_mpi *D, const mbedtls_mpi *DP,
230 const mbedtls_mpi *DQ, const mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100231{
232 int ret = 0;
233
234 mbedtls_mpi K, L;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100235 mbedtls_mpi_init(&K);
236 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100237
238 /* Check that DP - D == 0 mod P - 1 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100239 if (DP != NULL) {
240 if (P == NULL) {
Hanno Beckera565f542017-10-11 11:00:19 +0100241 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
242 goto cleanup;
243 }
244
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100245 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
246 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));
247 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100248
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100249 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100250 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
251 goto cleanup;
252 }
253 }
254
255 /* Check that DQ - D == 0 mod Q - 1 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100256 if (DQ != NULL) {
257 if (Q == NULL) {
Hanno Beckera565f542017-10-11 11:00:19 +0100258 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
259 goto cleanup;
260 }
261
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100262 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
263 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));
264 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100265
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100266 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100267 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
268 goto cleanup;
269 }
270 }
271
272 /* Check that QP * Q - 1 == 0 mod P */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100273 if (QP != NULL) {
274 if (P == NULL || Q == NULL) {
Hanno Beckera565f542017-10-11 11:00:19 +0100275 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
276 goto cleanup;
277 }
278
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100279 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));
280 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
281 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));
282 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100283 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
284 goto cleanup;
285 }
286 }
287
288cleanup:
289
290 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100291 if (ret != 0 &&
Hanno Beckera565f542017-10-11 11:00:19 +0100292 ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100293 ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {
Hanno Beckera565f542017-10-11 11:00:19 +0100294 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
295 }
296
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297 mbedtls_mpi_free(&K);
298 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100299
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100300 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100301}
302
303/*
304 * Check that core RSA parameters are sane.
305 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100306int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
307 const mbedtls_mpi *Q, const mbedtls_mpi *D,
308 const mbedtls_mpi *E,
309 int (*f_rng)(void *, unsigned char *, size_t),
310 void *p_rng)
Hanno Beckera565f542017-10-11 11:00:19 +0100311{
312 int ret = 0;
313 mbedtls_mpi K, L;
314
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100315 mbedtls_mpi_init(&K);
316 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100317
318 /*
319 * Step 1: If PRNG provided, check that P and Q are prime
320 */
321
322#if defined(MBEDTLS_GENPRIME)
Janos Follatha0b67c22018-09-18 14:48:23 +0100323 /*
324 * When generating keys, the strongest security we support aims for an error
325 * rate of at most 2^-100 and we are aiming for the same certainty here as
326 * well.
327 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100328 if (f_rng != NULL && P != NULL &&
329 (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100330 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
331 goto cleanup;
332 }
333
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100334 if (f_rng != NULL && Q != NULL &&
335 (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100336 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
337 goto cleanup;
338 }
339#else
340 ((void) f_rng);
341 ((void) p_rng);
342#endif /* MBEDTLS_GENPRIME */
343
344 /*
Hanno Beckerf8c028a2017-10-17 09:20:57 +0100345 * Step 2: Check that 1 < N = P * Q
Hanno Beckera565f542017-10-11 11:00:19 +0100346 */
347
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100348 if (P != NULL && Q != NULL && N != NULL) {
349 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));
350 if (mbedtls_mpi_cmp_int(N, 1) <= 0 ||
351 mbedtls_mpi_cmp_mpi(&K, N) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100352 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
353 goto cleanup;
354 }
355 }
356
357 /*
358 * Step 3: Check and 1 < D, E < N if present.
359 */
360
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100361 if (N != NULL && D != NULL && E != NULL) {
362 if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||
363 mbedtls_mpi_cmp_int(E, 1) <= 0 ||
364 mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
365 mbedtls_mpi_cmp_mpi(E, N) >= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100366 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
367 goto cleanup;
368 }
369 }
370
371 /*
372 * Step 4: Check that D, E are inverse modulo P-1 and Q-1
373 */
374
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100375 if (P != NULL && Q != NULL && D != NULL && E != NULL) {
376 if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
377 mbedtls_mpi_cmp_int(Q, 1) <= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100378 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
379 goto cleanup;
380 }
381
382 /* Compute DE-1 mod P-1 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100383 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
384 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
385 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));
386 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
387 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100388 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
389 goto cleanup;
390 }
391
392 /* Compute DE-1 mod Q-1 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100393 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
394 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
395 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
396 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
397 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100398 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
399 goto cleanup;
400 }
401 }
402
403cleanup:
404
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100405 mbedtls_mpi_free(&K);
406 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100407
408 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100409 if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {
Hanno Beckera565f542017-10-11 11:00:19 +0100410 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
411 }
412
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100413 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100414}
415
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100416int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
417 const mbedtls_mpi *D, mbedtls_mpi *DP,
418 mbedtls_mpi *DQ, mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100419{
420 int ret = 0;
421 mbedtls_mpi K;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100422 mbedtls_mpi_init(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100423
424 /* DP = D mod P-1 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100425 if (DP != NULL) {
426 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
427 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100428 }
429
430 /* DQ = D mod Q-1 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100431 if (DQ != NULL) {
432 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
433 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100434 }
435
436 /* QP = Q^{-1} mod P */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100437 if (QP != NULL) {
438 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P));
Hanno Beckera565f542017-10-11 11:00:19 +0100439 }
440
441cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100442 mbedtls_mpi_free(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100443
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100444 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100445}
446
447#endif /* MBEDTLS_RSA_C */