blob: d91949af1283c98de3035d19e4f0f5eb4694b2b1 [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
215 /* Compute modular inverse of E in LCM(P-1, Q-1) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100217
218cleanup:
219
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 mbedtls_mpi_free(&K);
221 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100222
Gilles Peskine449bd832023-01-11 14:50:10 +0100223 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100224}
225
Gilles Peskine449bd832023-01-11 14:50:10 +0100226int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
227 const mbedtls_mpi *D, mbedtls_mpi *DP,
228 mbedtls_mpi *DQ, mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100229{
230 int ret = 0;
Chris Jones66a4cd42021-03-09 16:04:12 +0000231 mbedtls_mpi K;
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 mbedtls_mpi_init(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100233
Chris Jones66a4cd42021-03-09 16:04:12 +0000234 /* DP = D mod P-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 if (DP != NULL) {
236 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
237 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100238 }
239
Chris Jones66a4cd42021-03-09 16:04:12 +0000240 /* DQ = D mod Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 if (DQ != NULL) {
242 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
243 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100244 }
245
Chris Jones66a4cd42021-03-09 16:04:12 +0000246 /* QP = Q^{-1} mod P */
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 if (QP != NULL) {
Manuel Pégourié-Gonnard630148e2025-08-13 13:57:35 +0200248 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod_odd(QP, Q, P));
Hanno Beckera565f542017-10-11 11:00:19 +0100249 }
250
251cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100252 mbedtls_mpi_free(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100253
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100255}
256
257/*
258 * Check that core RSA parameters are sane.
259 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100260int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
261 const mbedtls_mpi *Q, const mbedtls_mpi *D,
262 const mbedtls_mpi *E,
263 int (*f_rng)(void *, unsigned char *, size_t),
264 void *p_rng)
Hanno Beckera565f542017-10-11 11:00:19 +0100265{
266 int ret = 0;
267 mbedtls_mpi K, L;
268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 mbedtls_mpi_init(&K);
270 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100271
272 /*
273 * Step 1: If PRNG provided, check that P and Q are prime
274 */
275
276#if defined(MBEDTLS_GENPRIME)
Janos Follatha0b67c22018-09-18 14:48:23 +0100277 /*
278 * When generating keys, the strongest security we support aims for an error
279 * rate of at most 2^-100 and we are aiming for the same certainty here as
280 * well.
281 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 if (f_rng != NULL && P != NULL &&
283 (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100284 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
285 goto cleanup;
286 }
287
Gilles Peskine449bd832023-01-11 14:50:10 +0100288 if (f_rng != NULL && Q != NULL &&
289 (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100290 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
291 goto cleanup;
292 }
293#else
294 ((void) f_rng);
295 ((void) p_rng);
296#endif /* MBEDTLS_GENPRIME */
297
298 /*
Hanno Beckerf8c028a2017-10-17 09:20:57 +0100299 * Step 2: Check that 1 < N = P * Q
Hanno Beckera565f542017-10-11 11:00:19 +0100300 */
301
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 if (P != NULL && Q != NULL && N != NULL) {
303 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));
304 if (mbedtls_mpi_cmp_int(N, 1) <= 0 ||
305 mbedtls_mpi_cmp_mpi(&K, N) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100306 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
307 goto cleanup;
308 }
309 }
310
311 /*
312 * Step 3: Check and 1 < D, E < N if present.
313 */
314
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 if (N != NULL && D != NULL && E != NULL) {
316 if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||
317 mbedtls_mpi_cmp_int(E, 1) <= 0 ||
318 mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
319 mbedtls_mpi_cmp_mpi(E, N) >= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100320 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
321 goto cleanup;
322 }
323 }
324
325 /*
326 * Step 4: Check that D, E are inverse modulo P-1 and Q-1
327 */
328
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 if (P != NULL && Q != NULL && D != NULL && E != NULL) {
330 if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
331 mbedtls_mpi_cmp_int(Q, 1) <= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100332 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
333 goto cleanup;
334 }
335
336 /* Compute DE-1 mod P-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
338 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
339 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));
340 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
341 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100342 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
343 goto cleanup;
344 }
345
346 /* Compute DE-1 mod Q-1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
348 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
349 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
350 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
351 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100352 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
353 goto cleanup;
354 }
355 }
356
357cleanup:
358
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 mbedtls_mpi_free(&K);
360 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100361
362 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {
Hanno Beckera565f542017-10-11 11:00:19 +0100364 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
365 }
366
Gilles Peskine449bd832023-01-11 14:50:10 +0100367 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100368}
369
Chris Jones66a4cd42021-03-09 16:04:12 +0000370/*
371 * Check that RSA CRT parameters are in accordance with core parameters.
372 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100373int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
374 const mbedtls_mpi *D, const mbedtls_mpi *DP,
375 const mbedtls_mpi *DQ, const mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100376{
377 int ret = 0;
Hanno Beckera565f542017-10-11 11:00:19 +0100378
Chris Jones66a4cd42021-03-09 16:04:12 +0000379 mbedtls_mpi K, L;
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 mbedtls_mpi_init(&K);
381 mbedtls_mpi_init(&L);
Chris Jones66a4cd42021-03-09 16:04:12 +0000382
383 /* Check that DP - D == 0 mod P - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 if (DP != NULL) {
385 if (P == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000386 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
387 goto cleanup;
388 }
389
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
391 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));
392 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000393
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000395 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
396 goto cleanup;
397 }
Hanno Beckera565f542017-10-11 11:00:19 +0100398 }
399
Chris Jones66a4cd42021-03-09 16:04:12 +0000400 /* Check that DQ - D == 0 mod Q - 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 if (DQ != NULL) {
402 if (Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000403 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
404 goto cleanup;
405 }
406
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
408 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));
409 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000412 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
413 goto cleanup;
414 }
Hanno Beckera565f542017-10-11 11:00:19 +0100415 }
416
Chris Jones66a4cd42021-03-09 16:04:12 +0000417 /* Check that QP * Q - 1 == 0 mod P */
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 if (QP != NULL) {
419 if (P == NULL || Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000420 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
421 goto cleanup;
422 }
423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));
425 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
426 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));
427 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000428 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
429 goto cleanup;
430 }
Hanno Beckera565f542017-10-11 11:00:19 +0100431 }
432
433cleanup:
Chris Jones66a4cd42021-03-09 16:04:12 +0000434
435 /* Wrap MPI error codes by RSA check failure error code */
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 if (ret != 0 &&
Chris Jones66a4cd42021-03-09 16:04:12 +0000437 ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000439 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
440 }
441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 mbedtls_mpi_free(&K);
443 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100446}
447
448#endif /* MBEDTLS_RSA_C */