blob: 08adbe3eb8e4cdb84c436898cf3f2c047c23b5f9 [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
201 mbedtls_mpi_init(&K);
202 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100203
204 /* Temporarily put K := P-1 and L := Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
206 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
Hanno Beckera565f542017-10-11 11:00:19 +0100207
208 /* Temporarily put D := gcd(P-1, Q-1) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L));
Hanno Beckera565f542017-10-11 11:00:19 +0100210
211 /* K := LCM(P-1, Q-1) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L));
213 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D));
Hanno Beckera565f542017-10-11 11:00:19 +0100214
Manuel Pégourié-Gonnarda4bf6802025-07-10 10:48:23 +0200215 /* Compute modular inverse of E mod LCM(P-1, Q-1)
216 * This is FIPS 186-4 §B.3.1 criterion 3(b).
217 * This will return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if E is not coprime to
218 * (P-1)(Q-1), also validating FIPS 186-4 §B.3.1 criterion 2(a). */
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100220
221cleanup:
222
Gilles Peskine449bd832023-01-11 14:50:10 +0100223 mbedtls_mpi_free(&K);
224 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100225
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100227}
228
Gilles Peskine449bd832023-01-11 14:50:10 +0100229int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
230 const mbedtls_mpi *D, mbedtls_mpi *DP,
231 mbedtls_mpi *DQ, mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100232{
233 int ret = 0;
Chris Jones66a4cd42021-03-09 16:04:12 +0000234 mbedtls_mpi K;
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 mbedtls_mpi_init(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100236
Chris Jones66a4cd42021-03-09 16:04:12 +0000237 /* DP = D mod P-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100238 if (DP != NULL) {
239 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
240 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100241 }
242
Chris Jones66a4cd42021-03-09 16:04:12 +0000243 /* DQ = D mod Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 if (DQ != NULL) {
245 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
246 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100247 }
248
Chris Jones66a4cd42021-03-09 16:04:12 +0000249 /* QP = Q^{-1} mod P */
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 if (QP != NULL) {
Manuel Pégourié-Gonnard630148e2025-08-13 13:57:35 +0200251 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod_odd(QP, Q, P));
Hanno Beckera565f542017-10-11 11:00:19 +0100252 }
253
254cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 mbedtls_mpi_free(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100258}
259
260/*
261 * Check that core RSA parameters are sane.
262 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100263int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
264 const mbedtls_mpi *Q, const mbedtls_mpi *D,
265 const mbedtls_mpi *E,
266 int (*f_rng)(void *, unsigned char *, size_t),
267 void *p_rng)
Hanno Beckera565f542017-10-11 11:00:19 +0100268{
269 int ret = 0;
270 mbedtls_mpi K, L;
271
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 mbedtls_mpi_init(&K);
273 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100274
275 /*
276 * Step 1: If PRNG provided, check that P and Q are prime
277 */
278
279#if defined(MBEDTLS_GENPRIME)
Janos Follatha0b67c22018-09-18 14:48:23 +0100280 /*
281 * When generating keys, the strongest security we support aims for an error
282 * rate of at most 2^-100 and we are aiming for the same certainty here as
283 * well.
284 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 if (f_rng != NULL && P != NULL &&
286 (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100287 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
288 goto cleanup;
289 }
290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 if (f_rng != NULL && Q != NULL &&
292 (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100293 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
294 goto cleanup;
295 }
296#else
297 ((void) f_rng);
298 ((void) p_rng);
299#endif /* MBEDTLS_GENPRIME */
300
301 /*
Hanno Beckerf8c028a2017-10-17 09:20:57 +0100302 * Step 2: Check that 1 < N = P * Q
Hanno Beckera565f542017-10-11 11:00:19 +0100303 */
304
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 if (P != NULL && Q != NULL && N != NULL) {
306 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));
307 if (mbedtls_mpi_cmp_int(N, 1) <= 0 ||
308 mbedtls_mpi_cmp_mpi(&K, N) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100309 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
310 goto cleanup;
311 }
312 }
313
314 /*
315 * Step 3: Check and 1 < D, E < N if present.
316 */
317
Gilles Peskine449bd832023-01-11 14:50:10 +0100318 if (N != NULL && D != NULL && E != NULL) {
319 if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||
320 mbedtls_mpi_cmp_int(E, 1) <= 0 ||
321 mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
322 mbedtls_mpi_cmp_mpi(E, N) >= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100323 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
324 goto cleanup;
325 }
326 }
327
328 /*
329 * Step 4: Check that D, E are inverse modulo P-1 and Q-1
330 */
331
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 if (P != NULL && Q != NULL && D != NULL && E != NULL) {
333 if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
334 mbedtls_mpi_cmp_int(Q, 1) <= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100335 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
336 goto cleanup;
337 }
338
339 /* Compute DE-1 mod P-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
341 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
342 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));
343 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
344 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100345 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
346 goto cleanup;
347 }
348
349 /* Compute DE-1 mod Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
351 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
352 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
353 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
354 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100355 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
356 goto cleanup;
357 }
358 }
359
360cleanup:
361
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 mbedtls_mpi_free(&K);
363 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100364
365 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {
Hanno Beckera565f542017-10-11 11:00:19 +0100367 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
368 }
369
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100371}
372
Chris Jones66a4cd42021-03-09 16:04:12 +0000373/*
374 * Check that RSA CRT parameters are in accordance with core parameters.
375 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100376int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
377 const mbedtls_mpi *D, const mbedtls_mpi *DP,
378 const mbedtls_mpi *DQ, const mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100379{
380 int ret = 0;
Hanno Beckera565f542017-10-11 11:00:19 +0100381
Chris Jones66a4cd42021-03-09 16:04:12 +0000382 mbedtls_mpi K, L;
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 mbedtls_mpi_init(&K);
384 mbedtls_mpi_init(&L);
Chris Jones66a4cd42021-03-09 16:04:12 +0000385
386 /* Check that DP - D == 0 mod P - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 if (DP != NULL) {
388 if (P == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000389 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
390 goto cleanup;
391 }
392
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
394 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));
395 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000396
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000398 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
399 goto cleanup;
400 }
Hanno Beckera565f542017-10-11 11:00:19 +0100401 }
402
Chris Jones66a4cd42021-03-09 16:04:12 +0000403 /* Check that DQ - D == 0 mod Q - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100404 if (DQ != NULL) {
405 if (Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000406 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
407 goto cleanup;
408 }
409
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
411 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));
412 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000413
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000415 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
416 goto cleanup;
417 }
Hanno Beckera565f542017-10-11 11:00:19 +0100418 }
419
Chris Jones66a4cd42021-03-09 16:04:12 +0000420 /* Check that QP * Q - 1 == 0 mod P */
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 if (QP != NULL) {
422 if (P == NULL || Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000423 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
424 goto cleanup;
425 }
426
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));
428 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
429 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));
430 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000431 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
432 goto cleanup;
433 }
Hanno Beckera565f542017-10-11 11:00:19 +0100434 }
435
436cleanup:
Chris Jones66a4cd42021-03-09 16:04:12 +0000437
438 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 if (ret != 0 &&
Chris Jones66a4cd42021-03-09 16:04:12 +0000440 ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000442 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
443 }
444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 mbedtls_mpi_free(&K);
446 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100447
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100449}
450
451#endif /* MBEDTLS_RSA_C */