1
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
72
73
74
75
78
79
86
87
90
91
92
93
94
95
96
97
98
102
103
104
105
106
109
110
111
112
115
116
117
118
119
120
121
124
125
127
128
130
131
132
134
137
138
139
140
141
151
152
153
154
155
156
157
164
167
168
169
170
171
172
173
174
175
176
177
178
182
183
184
185
186
187
188
189
190
193
194
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
228
229
230
231
232
233
234
235
236
237
238
239
240
244
245
246
247
248
249
253
254
255
256
257
261
262
263
264
265
266
270
271
272
273
274
278
279
280
281
282
286
287
288
289
290
291
296
297
298
299
300
301
302
303
306
307
308
309
310
311
312
313
314
315
316
317
318
321
322
323
324
325
326
327
328
333
334
339
340
342
343
344
347
348
356
357
360
361
370
371
374
375
376
381
382
383
384
385
386
387
391
392
393
394
395
396
397
401
402
403
404
405
406
407
408
409
412
413
414
415
416
417
418
419
420
421
422
423
424
425
429
430
431
435
436
437
440
441
442
443
444
445
446
447
/* ... */
#include "common.h"
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#include "mbedtls/bignum.h"
#include "mbedtls/rsa_internal.h"
/* ... */
int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N,
mbedtls_mpi const *E, mbedtls_mpi const *D,
mbedtls_mpi *P, mbedtls_mpi *Q)
{
int ret = 0;
uint16_t attempt;
uint16_t iter;
uint16_t order;
mbedtls_mpi T;
mbedtls_mpi K;
const unsigned char primes[] = { 2,
3, 5, 7, 11, 13, 17, 19, 23,
29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97,
101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227,
229, 233, 239, 241, 251 ...};
const size_t num_primes = sizeof(primes) / sizeof(*primes);
if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) { ... }
if (mbedtls_mpi_cmp_int(N, 0) <= 0 ||
mbedtls_mpi_cmp_int(D, 1) <= 0 ||
mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
mbedtls_mpi_cmp_int(E, 1) <= 0 ||
mbedtls_mpi_cmp_mpi(E, N) >= 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}if (mbedtls_mpi_cmp_int(N, 0) <= 0 || mbedtls_mpi_cmp_int(D, 1) <= 0 || mbedtls_mpi_cmp_mpi(D, N) >= 0 || mbedtls_mpi_cmp_int(E, 1) <= 0 || mbedtls_mpi_cmp_mpi(E, N) >= 0) { ... }
/* ... */
mbedtls_mpi_init(&K);
mbedtls_mpi_init(&T);
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D, E));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1));
if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) {
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
goto cleanup;
}if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) { ... }
MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order));
/* ... */
attempt = 0;
if (N->p[0] % 8 == 1) {
attempt = 1;
}if (N->p[0] % 8 == 1) { ... }
for (; attempt < num_primes; ++attempt) {
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt]));
MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
if (mbedtls_mpi_cmp_int(P, 1) != 0) {
continue;
}if (mbedtls_mpi_cmp_int(P, 1) != 0) { ... }
/* ... */
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N,
Q
/* ... */));
for (iter = 1; iter <= order; ++iter) {
/* ... */
if (mbedtls_mpi_cmp_int(&K, 1) == 0) {
break;
}if (mbedtls_mpi_cmp_int(&K, 1) == 0) { ... }
MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
if (mbedtls_mpi_cmp_int(P, 1) == 1 &&
mbedtls_mpi_cmp_mpi(P, N) == -1) {
/* ... */
MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P));
goto cleanup;
}if (mbedtls_mpi_cmp_int(P, 1) == 1 && mbedtls_mpi_cmp_mpi(P, N) == -1) { ... }
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N));
}for (iter = 1; iter <= order; ++iter) { ... }
/* ... */
if (mbedtls_mpi_cmp_int(&K, 1) != 0) {
break;
}if (mbedtls_mpi_cmp_int(&K, 1) != 0) { ... }
}for (; attempt < num_primes; ++attempt) { ... }
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
cleanup:
mbedtls_mpi_free(&K);
mbedtls_mpi_free(&T);
return ret;
}{ ... }
/* ... */
int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P,
mbedtls_mpi const *Q,
mbedtls_mpi const *E,
mbedtls_mpi *D)
{
int ret = 0;
mbedtls_mpi K, L;
if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) { ... }
if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
mbedtls_mpi_cmp_int(Q, 1) <= 0 ||
mbedtls_mpi_cmp_int(E, 0) == 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}if (mbedtls_mpi_cmp_int(P, 1) <= 0 || mbedtls_mpi_cmp_int(Q, 1) <= 0 || mbedtls_mpi_cmp_int(E, 0) == 0) { ... }
mbedtls_mpi_init(&K);
mbedtls_mpi_init(&L);
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L));
MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D));
MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K));
cleanup:
mbedtls_mpi_free(&K);
mbedtls_mpi_free(&L);
return ret;
}{ ... }
/* ... */
int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *DP,
const mbedtls_mpi *DQ, const mbedtls_mpi *QP)
{
int ret = 0;
mbedtls_mpi K, L;
mbedtls_mpi_init(&K);
mbedtls_mpi_init(&L);
if (DP != NULL) {
if (P == NULL) {
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}if (P == NULL) { ... }
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (mbedtls_mpi_cmp_int(&L, 0) != 0) { ... }
}if (DP != NULL) { ... }
if (DQ != NULL) {
if (Q == NULL) {
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}if (Q == NULL) { ... }
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (mbedtls_mpi_cmp_int(&L, 0) != 0) { ... }
}if (DQ != NULL) { ... }
if (QP != NULL) {
if (P == NULL || Q == NULL) {
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}if (P == NULL || Q == NULL) { ... }
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));
if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (mbedtls_mpi_cmp_int(&K, 0) != 0) { ... }
}if (QP != NULL) { ... }
cleanup:
if (ret != 0 &&
ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
}if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) { ... }
mbedtls_mpi_free(&K);
mbedtls_mpi_free(&L);
return ret;
}{ ... }
/* ... */
int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
const mbedtls_mpi *Q, const mbedtls_mpi *D,
const mbedtls_mpi *E,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
int ret = 0;
mbedtls_mpi K, L;
mbedtls_mpi_init(&K);
mbedtls_mpi_init(&L);
/* ... */
#if defined(MBEDTLS_GENPRIME)
/* ... */
if (f_rng != NULL && P != NULL &&
(ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (f_rng != NULL && P != NULL && (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) { ... }
if (f_rng != NULL && Q != NULL &&
(ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (f_rng != NULL && Q != NULL && (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) { ... }
/* ... */#else
((void) f_rng);
((void) p_rng);/* ... */
#endif
/* ... */
if (P != NULL && Q != NULL && N != NULL) {
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));
if (mbedtls_mpi_cmp_int(N, 1) <= 0 ||
mbedtls_mpi_cmp_mpi(&K, N) != 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (mbedtls_mpi_cmp_int(N, 1) <= 0 || mbedtls_mpi_cmp_mpi(&K, N) != 0) { ... }
}if (P != NULL && Q != NULL && N != NULL) { ... }
/* ... */
if (N != NULL && D != NULL && E != NULL) {
if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||
mbedtls_mpi_cmp_int(E, 1) <= 0 ||
mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
mbedtls_mpi_cmp_mpi(E, N) >= 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (mbedtls_mpi_cmp_int(D, 1) <= 0 || mbedtls_mpi_cmp_int(E, 1) <= 0 || mbedtls_mpi_cmp_mpi(D, N) >= 0 || mbedtls_mpi_cmp_mpi(E, N) >= 0) { ... }
}if (N != NULL && D != NULL && E != NULL) { ... }
/* ... */
if (P != NULL && Q != NULL && D != NULL && E != NULL) {
if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
mbedtls_mpi_cmp_int(Q, 1) <= 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (mbedtls_mpi_cmp_int(P, 1) <= 0 || mbedtls_mpi_cmp_int(Q, 1) <= 0) { ... }
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (mbedtls_mpi_cmp_int(&K, 0) != 0) { ... }
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}if (mbedtls_mpi_cmp_int(&K, 0) != 0) { ... }
}if (P != NULL && Q != NULL && D != NULL && E != NULL) { ... }
cleanup:
mbedtls_mpi_free(&K);
mbedtls_mpi_free(&L);
if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
}if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) { ... }
return ret;
}{ ... }
int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, mbedtls_mpi *DP,
mbedtls_mpi *DQ, mbedtls_mpi *QP)
{
int ret = 0;
mbedtls_mpi K;
mbedtls_mpi_init(&K);
if (DP != NULL) {
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));
}if (DP != NULL) { ... }
if (DQ != NULL) {
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));
}if (DQ != NULL) { ... }
if (QP != NULL) {
MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P));
}if (QP != NULL) { ... }
cleanup:
mbedtls_mpi_free(&K);
return ret;
}{ ... }
/* ... */#endif