blob: 3451469b982c513f943c5b06a8da33c5b95656c1 [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
Hanno Beckera565f542017-10-11 11:00:19 +01005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
Hanno Beckera565f542017-10-11 11:00:19 +010019 */
20
Gilles Peskinedb09ef62020-06-03 01:43:33 +020021#include "common.h"
Hanno Beckera565f542017-10-11 11:00:19 +010022
23#if defined(MBEDTLS_RSA_C)
24
25#include "mbedtls/rsa.h"
26#include "mbedtls/bignum.h"
Chris Jones66a4cd42021-03-09 16:04:12 +000027#include "rsa_alt_helpers.h"
Hanno Beckera565f542017-10-11 11:00:19 +010028
29/*
30 * Compute RSA prime factors from public and private exponents
31 *
32 * Summary of algorithm:
33 * Setting F := lcm(P-1,Q-1), the idea is as follows:
34 *
35 * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)
36 * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the
37 * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four
38 * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)
39 * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime
40 * factors of N.
41 *
42 * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same
43 * construction still applies since (-)^K is the identity on the set of
44 * roots of 1 in Z/NZ.
45 *
46 * The public and private key primitives (-)^E and (-)^D are mutually inverse
47 * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.
48 * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.
49 * Splitting L = 2^t * K with K odd, we have
50 *
51 * DE - 1 = FL = (F/2) * (2^(t+1)) * K,
52 *
53 * so (F / 2) * K is among the numbers
54 *
55 * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord
56 *
57 * where ord is the order of 2 in (DE - 1).
58 * We can therefore iterate through these numbers apply the construction
59 * of (a) and (b) above to attempt to factor N.
60 *
61 */
David Horstmann8b6068b2023-01-05 15:42:32 +000062int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N,
63 mbedtls_mpi const *E, mbedtls_mpi const *D,
64 mbedtls_mpi *P, mbedtls_mpi *Q)
Hanno Beckera565f542017-10-11 11:00:19 +010065{
66 int ret = 0;
67
68 uint16_t attempt; /* Number of current attempt */
69 uint16_t iter; /* Number of squares computed in the current attempt */
70
71 uint16_t order; /* Order of 2 in DE - 1 */
72
73 mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */
74 mbedtls_mpi K; /* Temporary holding the current candidate */
75
Hanno Becker4055a3a2017-10-17 09:15:26 +010076 const unsigned char primes[] = { 2,
David Horstmann8b6068b2023-01-05 15:42:32 +000077 3, 5, 7, 11, 13, 17, 19, 23,
78 29, 31, 37, 41, 43, 47, 53, 59,
79 61, 67, 71, 73, 79, 83, 89, 97,
80 101, 103, 107, 109, 113, 127, 131, 137,
81 139, 149, 151, 157, 163, 167, 173, 179,
82 181, 191, 193, 197, 199, 211, 223, 227,
83 229, 233, 239, 241, 251 };
Hanno Beckera565f542017-10-11 11:00:19 +010084
David Horstmann8b6068b2023-01-05 15:42:32 +000085 const size_t num_primes = sizeof(primes) / sizeof(*primes);
Hanno Beckera565f542017-10-11 11:00:19 +010086
David Horstmann8b6068b2023-01-05 15:42:32 +000087 if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) {
88 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
89 }
Hanno Beckera565f542017-10-11 11:00:19 +010090
David Horstmann8b6068b2023-01-05 15:42:32 +000091 if (mbedtls_mpi_cmp_int(N, 0) <= 0 ||
92 mbedtls_mpi_cmp_int(D, 1) <= 0 ||
93 mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
94 mbedtls_mpi_cmp_int(E, 1) <= 0 ||
95 mbedtls_mpi_cmp_mpi(E, N) >= 0) {
96 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Hanno Beckera565f542017-10-11 11:00:19 +010097 }
98
99 /*
100 * Initializations and temporary changes
101 */
102
David Horstmann8b6068b2023-01-05 15:42:32 +0000103 mbedtls_mpi_init(&K);
104 mbedtls_mpi_init(&T);
Hanno Beckera565f542017-10-11 11:00:19 +0100105
106 /* T := DE - 1 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000107 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D, E));
108 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1));
Hanno Beckera565f542017-10-11 11:00:19 +0100109
David Horstmann8b6068b2023-01-05 15:42:32 +0000110 if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100111 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
112 goto cleanup;
113 }
114
115 /* After this operation, T holds the largest odd divisor of DE - 1. */
David Horstmann8b6068b2023-01-05 15:42:32 +0000116 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order));
Hanno Beckera565f542017-10-11 11:00:19 +0100117
118 /*
119 * Actual work
120 */
121
122 /* Skip trying 2 if N == 1 mod 8 */
123 attempt = 0;
David Horstmann8b6068b2023-01-05 15:42:32 +0000124 if (N->p[0] % 8 == 1) {
Hanno Beckera565f542017-10-11 11:00:19 +0100125 attempt = 1;
David Horstmann8b6068b2023-01-05 15:42:32 +0000126 }
Hanno Beckera565f542017-10-11 11:00:19 +0100127
David Horstmann8b6068b2023-01-05 15:42:32 +0000128 for (; attempt < num_primes; ++attempt) {
129 mbedtls_mpi_lset(&K, primes[attempt]);
Hanno Beckera565f542017-10-11 11:00:19 +0100130
131 /* Check if gcd(K,N) = 1 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000132 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
133 if (mbedtls_mpi_cmp_int(P, 1) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100134 continue;
David Horstmann8b6068b2023-01-05 15:42:32 +0000135 }
Hanno Beckera565f542017-10-11 11:00:19 +0100136
137 /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...
138 * and check whether they have nontrivial GCD with N. */
David Horstmann8b6068b2023-01-05 15:42:32 +0000139 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N,
140 Q /* temporarily use Q for storing Montgomery
141 * multiplication helper values */));
Hanno Beckera565f542017-10-11 11:00:19 +0100142
David Horstmann8b6068b2023-01-05 15:42:32 +0000143 for (iter = 1; iter <= order; ++iter) {
Hanno Becker5d42b532017-10-11 15:58:00 +0100144 /* If we reach 1 prematurely, there's no point
145 * in continuing to square K */
David Horstmann8b6068b2023-01-05 15:42:32 +0000146 if (mbedtls_mpi_cmp_int(&K, 1) == 0) {
Hanno Becker5d42b532017-10-11 15:58:00 +0100147 break;
David Horstmann8b6068b2023-01-05 15:42:32 +0000148 }
Hanno Becker5d42b532017-10-11 15:58:00 +0100149
David Horstmann8b6068b2023-01-05 15:42:32 +0000150 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1));
151 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
Hanno Beckera565f542017-10-11 11:00:19 +0100152
David Horstmann8b6068b2023-01-05 15:42:32 +0000153 if (mbedtls_mpi_cmp_int(P, 1) == 1 &&
154 mbedtls_mpi_cmp_mpi(P, N) == -1) {
Hanno Beckera565f542017-10-11 11:00:19 +0100155 /*
156 * Have found a nontrivial divisor P of N.
157 * Set Q := N / P.
158 */
159
David Horstmann8b6068b2023-01-05 15:42:32 +0000160 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P));
Hanno Beckera565f542017-10-11 11:00:19 +0100161 goto cleanup;
162 }
163
David Horstmann8b6068b2023-01-05 15:42:32 +0000164 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
165 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K));
166 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N));
Hanno Beckera565f542017-10-11 11:00:19 +0100167 }
Hanno Becker14a00c02017-10-11 12:58:23 +0100168
Hanno Becker5d42b532017-10-11 15:58:00 +0100169 /*
170 * If we get here, then either we prematurely aborted the loop because
171 * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must
172 * be 1 if D,E,N were consistent.
173 * Check if that's the case and abort if not, to avoid very long,
174 * yet eventually failing, computations if N,D,E were not sane.
175 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000176 if (mbedtls_mpi_cmp_int(&K, 1) != 0) {
Hanno Becker14a00c02017-10-11 12:58:23 +0100177 break;
178 }
Hanno Beckera565f542017-10-11 11:00:19 +0100179 }
180
181 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
182
183cleanup:
184
David Horstmann8b6068b2023-01-05 15:42:32 +0000185 mbedtls_mpi_free(&K);
186 mbedtls_mpi_free(&T);
187 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100188}
189
190/*
191 * Given P, Q and the public exponent E, deduce D.
192 * This is essentially a modular inversion.
193 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000194int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P,
195 mbedtls_mpi const *Q,
196 mbedtls_mpi const *E,
197 mbedtls_mpi *D)
Hanno Beckera565f542017-10-11 11:00:19 +0100198{
199 int ret = 0;
200 mbedtls_mpi K, L;
201
David Horstmann8b6068b2023-01-05 15:42:32 +0000202 if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) {
203 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
Hanno Beckera565f542017-10-11 11:00:19 +0100204 }
205
David Horstmann8b6068b2023-01-05 15:42:32 +0000206 if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
207 mbedtls_mpi_cmp_int(Q, 1) <= 0 ||
208 mbedtls_mpi_cmp_int(E, 0) == 0) {
209 return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
210 }
211
212 mbedtls_mpi_init(&K);
213 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100214
215 /* Temporarily put K := P-1 and L := Q-1 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000216 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
217 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
Hanno Beckera565f542017-10-11 11:00:19 +0100218
219 /* Temporarily put D := gcd(P-1, Q-1) */
David Horstmann8b6068b2023-01-05 15:42:32 +0000220 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L));
Hanno Beckera565f542017-10-11 11:00:19 +0100221
222 /* K := LCM(P-1, Q-1) */
David Horstmann8b6068b2023-01-05 15:42:32 +0000223 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L));
224 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D));
Hanno Beckera565f542017-10-11 11:00:19 +0100225
226 /* Compute modular inverse of E in LCM(P-1, Q-1) */
David Horstmann8b6068b2023-01-05 15:42:32 +0000227 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100228
229cleanup:
230
David Horstmann8b6068b2023-01-05 15:42:32 +0000231 mbedtls_mpi_free(&K);
232 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100233
David Horstmann8b6068b2023-01-05 15:42:32 +0000234 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100235}
236
David Horstmann8b6068b2023-01-05 15:42:32 +0000237int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
238 const mbedtls_mpi *D, mbedtls_mpi *DP,
239 mbedtls_mpi *DQ, mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100240{
241 int ret = 0;
Chris Jones66a4cd42021-03-09 16:04:12 +0000242 mbedtls_mpi K;
David Horstmann8b6068b2023-01-05 15:42:32 +0000243 mbedtls_mpi_init(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100244
Chris Jones66a4cd42021-03-09 16:04:12 +0000245 /* DP = D mod P-1 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000246 if (DP != NULL) {
247 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
248 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100249 }
250
Chris Jones66a4cd42021-03-09 16:04:12 +0000251 /* DQ = D mod Q-1 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000252 if (DQ != NULL) {
253 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
254 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));
Hanno Beckera565f542017-10-11 11:00:19 +0100255 }
256
Chris Jones66a4cd42021-03-09 16:04:12 +0000257 /* QP = Q^{-1} mod P */
David Horstmann8b6068b2023-01-05 15:42:32 +0000258 if (QP != NULL) {
259 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P));
Hanno Beckera565f542017-10-11 11:00:19 +0100260 }
261
262cleanup:
David Horstmann8b6068b2023-01-05 15:42:32 +0000263 mbedtls_mpi_free(&K);
Hanno Beckera565f542017-10-11 11:00:19 +0100264
David Horstmann8b6068b2023-01-05 15:42:32 +0000265 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100266}
267
268/*
269 * Check that core RSA parameters are sane.
270 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000271int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
272 const mbedtls_mpi *Q, const mbedtls_mpi *D,
273 const mbedtls_mpi *E,
274 int (*f_rng)(void *, unsigned char *, size_t),
275 void *p_rng)
Hanno Beckera565f542017-10-11 11:00:19 +0100276{
277 int ret = 0;
278 mbedtls_mpi K, L;
279
David Horstmann8b6068b2023-01-05 15:42:32 +0000280 mbedtls_mpi_init(&K);
281 mbedtls_mpi_init(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100282
283 /*
284 * Step 1: If PRNG provided, check that P and Q are prime
285 */
286
287#if defined(MBEDTLS_GENPRIME)
Janos Follatha0b67c22018-09-18 14:48:23 +0100288 /*
289 * When generating keys, the strongest security we support aims for an error
290 * rate of at most 2^-100 and we are aiming for the same certainty here as
291 * well.
292 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000293 if (f_rng != NULL && P != NULL &&
294 (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100295 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
296 goto cleanup;
297 }
298
David Horstmann8b6068b2023-01-05 15:42:32 +0000299 if (f_rng != NULL && Q != NULL &&
300 (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100301 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
302 goto cleanup;
303 }
304#else
305 ((void) f_rng);
306 ((void) p_rng);
307#endif /* MBEDTLS_GENPRIME */
308
309 /*
Hanno Beckerf8c028a2017-10-17 09:20:57 +0100310 * Step 2: Check that 1 < N = P * Q
Hanno Beckera565f542017-10-11 11:00:19 +0100311 */
312
David Horstmann8b6068b2023-01-05 15:42:32 +0000313 if (P != NULL && Q != NULL && N != NULL) {
314 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));
315 if (mbedtls_mpi_cmp_int(N, 1) <= 0 ||
316 mbedtls_mpi_cmp_mpi(&K, N) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100317 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
318 goto cleanup;
319 }
320 }
321
322 /*
323 * Step 3: Check and 1 < D, E < N if present.
324 */
325
David Horstmann8b6068b2023-01-05 15:42:32 +0000326 if (N != NULL && D != NULL && E != NULL) {
327 if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||
328 mbedtls_mpi_cmp_int(E, 1) <= 0 ||
329 mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
330 mbedtls_mpi_cmp_mpi(E, N) >= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100331 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
332 goto cleanup;
333 }
334 }
335
336 /*
337 * Step 4: Check that D, E are inverse modulo P-1 and Q-1
338 */
339
David Horstmann8b6068b2023-01-05 15:42:32 +0000340 if (P != NULL && Q != NULL && D != NULL && E != NULL) {
341 if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
342 mbedtls_mpi_cmp_int(Q, 1) <= 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100343 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
344 goto cleanup;
345 }
346
347 /* Compute DE-1 mod P-1 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000348 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
349 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
350 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));
351 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
352 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100353 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
354 goto cleanup;
355 }
356
357 /* Compute DE-1 mod Q-1 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000358 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
359 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
360 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
361 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
362 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Hanno Beckera565f542017-10-11 11:00:19 +0100363 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
364 goto cleanup;
365 }
366 }
367
368cleanup:
369
David Horstmann8b6068b2023-01-05 15:42:32 +0000370 mbedtls_mpi_free(&K);
371 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100372
373 /* Wrap MPI error codes by RSA check failure error code */
David Horstmann8b6068b2023-01-05 15:42:32 +0000374 if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {
Hanno Beckera565f542017-10-11 11:00:19 +0100375 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
376 }
377
David Horstmann8b6068b2023-01-05 15:42:32 +0000378 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100379}
380
Chris Jones66a4cd42021-03-09 16:04:12 +0000381/*
382 * Check that RSA CRT parameters are in accordance with core parameters.
383 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000384int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
385 const mbedtls_mpi *D, const mbedtls_mpi *DP,
386 const mbedtls_mpi *DQ, const mbedtls_mpi *QP)
Hanno Beckera565f542017-10-11 11:00:19 +0100387{
388 int ret = 0;
Hanno Beckera565f542017-10-11 11:00:19 +0100389
Chris Jones66a4cd42021-03-09 16:04:12 +0000390 mbedtls_mpi K, L;
David Horstmann8b6068b2023-01-05 15:42:32 +0000391 mbedtls_mpi_init(&K);
392 mbedtls_mpi_init(&L);
Chris Jones66a4cd42021-03-09 16:04:12 +0000393
394 /* Check that DP - D == 0 mod P - 1 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000395 if (DP != NULL) {
396 if (P == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000397 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
398 goto cleanup;
399 }
400
David Horstmann8b6068b2023-01-05 15:42:32 +0000401 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
402 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));
403 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000404
David Horstmann8b6068b2023-01-05 15:42:32 +0000405 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000406 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
407 goto cleanup;
408 }
Hanno Beckera565f542017-10-11 11:00:19 +0100409 }
410
Chris Jones66a4cd42021-03-09 16:04:12 +0000411 /* Check that DQ - D == 0 mod Q - 1 */
David Horstmann8b6068b2023-01-05 15:42:32 +0000412 if (DQ != NULL) {
413 if (Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000414 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
415 goto cleanup;
416 }
417
David Horstmann8b6068b2023-01-05 15:42:32 +0000418 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
419 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));
420 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
Chris Jones66a4cd42021-03-09 16:04:12 +0000421
David Horstmann8b6068b2023-01-05 15:42:32 +0000422 if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000423 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
424 goto cleanup;
425 }
Hanno Beckera565f542017-10-11 11:00:19 +0100426 }
427
Chris Jones66a4cd42021-03-09 16:04:12 +0000428 /* Check that QP * Q - 1 == 0 mod P */
David Horstmann8b6068b2023-01-05 15:42:32 +0000429 if (QP != NULL) {
430 if (P == NULL || Q == NULL) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000431 ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
432 goto cleanup;
433 }
434
David Horstmann8b6068b2023-01-05 15:42:32 +0000435 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));
436 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
437 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));
438 if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000439 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
440 goto cleanup;
441 }
Hanno Beckera565f542017-10-11 11:00:19 +0100442 }
443
444cleanup:
Chris Jones66a4cd42021-03-09 16:04:12 +0000445
446 /* Wrap MPI error codes by RSA check failure error code */
David Horstmann8b6068b2023-01-05 15:42:32 +0000447 if (ret != 0 &&
Chris Jones66a4cd42021-03-09 16:04:12 +0000448 ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
David Horstmann8b6068b2023-01-05 15:42:32 +0000449 ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {
Chris Jones66a4cd42021-03-09 16:04:12 +0000450 ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
451 }
452
David Horstmann8b6068b2023-01-05 15:42:32 +0000453 mbedtls_mpi_free(&K);
454 mbedtls_mpi_free(&L);
Hanno Beckera565f542017-10-11 11:00:19 +0100455
David Horstmann8b6068b2023-01-05 15:42:32 +0000456 return ret;
Hanno Beckera565f542017-10-11 11:00:19 +0100457}
458
459#endif /* MBEDTLS_RSA_C */