]>
Commit | Line | Data |
---|---|---|
2039c421 | 1 | /* |
da1c088f | 2 | * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. |
6519b2cb | 3 | * |
2a7b6f39 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
2039c421 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
6519b2cb BM |
8 | */ |
9 | ||
c5f87134 P |
10 | /* |
11 | * RSA low level APIs are deprecated for public use, but still ok for | |
12 | * internal use. | |
13 | */ | |
14 | #include "internal/deprecated.h" | |
15 | ||
6519b2cb BM |
16 | #include <openssl/bn.h> |
17 | #include <openssl/err.h> | |
12603de6 | 18 | #include "crypto/rsa.h" |
706457b7 | 19 | #include "rsa_local.h" |
6519b2cb | 20 | |
f844f9eb | 21 | #ifndef FIPS_MODULE |
12603de6 | 22 | static int rsa_validate_keypair_multiprime(const RSA *key, BN_GENCB *cb) |
0f113f3e | 23 | { |
0f113f3e MC |
24 | BIGNUM *i, *j, *k, *l, *m; |
25 | BN_CTX *ctx; | |
665d899f PY |
26 | int ret = 1, ex_primes = 0, idx; |
27 | RSA_PRIME_INFO *pinfo; | |
0f113f3e | 28 | |
464d59a5 RS |
29 | if (key->p == NULL || key->q == NULL || key->n == NULL |
30 | || key->e == NULL || key->d == NULL) { | |
9311d0c4 | 31 | ERR_raise(ERR_LIB_RSA, RSA_R_VALUE_MISSING); |
0f113f3e MC |
32 | return 0; |
33 | } | |
34 | ||
665d899f | 35 | /* multi-prime? */ |
3bded9cd AP |
36 | if (key->version == RSA_ASN1_VERSION_MULTI) { |
37 | ex_primes = sk_RSA_PRIME_INFO_num(key->prime_infos); | |
38 | if (ex_primes <= 0 | |
4158b0dc | 39 | || (ex_primes + 2) > ossl_rsa_multip_cap(BN_num_bits(key->n))) { |
9311d0c4 | 40 | ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MULTI_PRIME_KEY); |
3bded9cd AP |
41 | return 0; |
42 | } | |
665d899f PY |
43 | } |
44 | ||
0f113f3e MC |
45 | i = BN_new(); |
46 | j = BN_new(); | |
47 | k = BN_new(); | |
48 | l = BN_new(); | |
49 | m = BN_new(); | |
d11f644b | 50 | ctx = BN_CTX_new_ex(key->libctx); |
464d59a5 RS |
51 | if (i == NULL || j == NULL || k == NULL || l == NULL |
52 | || m == NULL || ctx == NULL) { | |
0f113f3e | 53 | ret = -1; |
e077455e | 54 | ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); |
0f113f3e MC |
55 | goto err; |
56 | } | |
57 | ||
464d59a5 RS |
58 | if (BN_is_one(key->e)) { |
59 | ret = 0; | |
9311d0c4 | 60 | ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE); |
464d59a5 RS |
61 | } |
62 | if (!BN_is_odd(key->e)) { | |
63 | ret = 0; | |
9311d0c4 | 64 | ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE); |
464d59a5 RS |
65 | } |
66 | ||
0f113f3e | 67 | /* p prime? */ |
d11f644b | 68 | if (BN_check_prime(key->p, ctx, cb) != 1) { |
464d59a5 | 69 | ret = 0; |
9311d0c4 | 70 | ERR_raise(ERR_LIB_RSA, RSA_R_P_NOT_PRIME); |
0f113f3e MC |
71 | } |
72 | ||
73 | /* q prime? */ | |
d11f644b | 74 | if (BN_check_prime(key->q, ctx, cb) != 1) { |
464d59a5 | 75 | ret = 0; |
9311d0c4 | 76 | ERR_raise(ERR_LIB_RSA, RSA_R_Q_NOT_PRIME); |
0f113f3e MC |
77 | } |
78 | ||
665d899f PY |
79 | /* r_i prime? */ |
80 | for (idx = 0; idx < ex_primes; idx++) { | |
81 | pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); | |
d11f644b | 82 | if (BN_check_prime(pinfo->r, ctx, cb) != 1) { |
665d899f | 83 | ret = 0; |
9311d0c4 | 84 | ERR_raise(ERR_LIB_RSA, RSA_R_MP_R_NOT_PRIME); |
665d899f PY |
85 | } |
86 | } | |
87 | ||
88 | /* n = p*q * r_3...r_i? */ | |
464d59a5 | 89 | if (!BN_mul(i, key->p, key->q, ctx)) { |
0f113f3e MC |
90 | ret = -1; |
91 | goto err; | |
92 | } | |
665d899f PY |
93 | for (idx = 0; idx < ex_primes; idx++) { |
94 | pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); | |
95 | if (!BN_mul(i, i, pinfo->r, ctx)) { | |
96 | ret = -1; | |
97 | goto err; | |
98 | } | |
99 | } | |
0f113f3e MC |
100 | if (BN_cmp(i, key->n) != 0) { |
101 | ret = 0; | |
665d899f | 102 | if (ex_primes) |
9311d0c4 | 103 | ERR_raise(ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES); |
665d899f | 104 | else |
9311d0c4 | 105 | ERR_raise(ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_P_Q); |
0f113f3e MC |
106 | } |
107 | ||
665d899f | 108 | /* d*e = 1 mod \lambda(n)? */ |
464d59a5 | 109 | if (!BN_sub(i, key->p, BN_value_one())) { |
0f113f3e MC |
110 | ret = -1; |
111 | goto err; | |
112 | } | |
464d59a5 | 113 | if (!BN_sub(j, key->q, BN_value_one())) { |
0f113f3e MC |
114 | ret = -1; |
115 | goto err; | |
116 | } | |
117 | ||
665d899f | 118 | /* now compute k = \lambda(n) = LCM(i, j, r_3 - 1...) */ |
464d59a5 | 119 | if (!BN_mul(l, i, j, ctx)) { |
0f113f3e MC |
120 | ret = -1; |
121 | goto err; | |
122 | } | |
464d59a5 | 123 | if (!BN_gcd(m, i, j, ctx)) { |
0f113f3e MC |
124 | ret = -1; |
125 | goto err; | |
126 | } | |
efbff4de TM |
127 | if (!BN_div(m, NULL, l, m, ctx)) { /* remainder is 0 */ |
128 | ret = -1; | |
129 | goto err; | |
130 | } | |
665d899f PY |
131 | for (idx = 0; idx < ex_primes; idx++) { |
132 | pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); | |
133 | if (!BN_sub(k, pinfo->r, BN_value_one())) { | |
134 | ret = -1; | |
135 | goto err; | |
136 | } | |
efbff4de | 137 | if (!BN_mul(l, m, k, ctx)) { |
665d899f PY |
138 | ret = -1; |
139 | goto err; | |
140 | } | |
141 | if (!BN_gcd(m, m, k, ctx)) { | |
142 | ret = -1; | |
143 | goto err; | |
144 | } | |
efbff4de TM |
145 | if (!BN_div(m, NULL, l, m, ctx)) { /* remainder is 0 */ |
146 | ret = -1; | |
147 | goto err; | |
148 | } | |
665d899f | 149 | } |
efbff4de | 150 | if (!BN_mod_mul(i, key->d, key->e, m, ctx)) { |
0f113f3e MC |
151 | ret = -1; |
152 | goto err; | |
153 | } | |
154 | ||
155 | if (!BN_is_one(i)) { | |
156 | ret = 0; | |
9311d0c4 | 157 | ERR_raise(ERR_LIB_RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1); |
0f113f3e MC |
158 | } |
159 | ||
160 | if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) { | |
161 | /* dmp1 = d mod (p-1)? */ | |
464d59a5 | 162 | if (!BN_sub(i, key->p, BN_value_one())) { |
0f113f3e MC |
163 | ret = -1; |
164 | goto err; | |
165 | } | |
464d59a5 | 166 | if (!BN_mod(j, key->d, i, ctx)) { |
0f113f3e MC |
167 | ret = -1; |
168 | goto err; | |
169 | } | |
0f113f3e MC |
170 | if (BN_cmp(j, key->dmp1) != 0) { |
171 | ret = 0; | |
9311d0c4 | 172 | ERR_raise(ERR_LIB_RSA, RSA_R_DMP1_NOT_CONGRUENT_TO_D); |
0f113f3e MC |
173 | } |
174 | ||
175 | /* dmq1 = d mod (q-1)? */ | |
464d59a5 | 176 | if (!BN_sub(i, key->q, BN_value_one())) { |
0f113f3e MC |
177 | ret = -1; |
178 | goto err; | |
179 | } | |
464d59a5 | 180 | if (!BN_mod(j, key->d, i, ctx)) { |
0f113f3e MC |
181 | ret = -1; |
182 | goto err; | |
183 | } | |
0f113f3e MC |
184 | if (BN_cmp(j, key->dmq1) != 0) { |
185 | ret = 0; | |
9311d0c4 | 186 | ERR_raise(ERR_LIB_RSA, RSA_R_DMQ1_NOT_CONGRUENT_TO_D); |
0f113f3e MC |
187 | } |
188 | ||
189 | /* iqmp = q^-1 mod p? */ | |
190 | if (!BN_mod_inverse(i, key->q, key->p, ctx)) { | |
191 | ret = -1; | |
192 | goto err; | |
193 | } | |
0f113f3e MC |
194 | if (BN_cmp(i, key->iqmp) != 0) { |
195 | ret = 0; | |
9311d0c4 | 196 | ERR_raise(ERR_LIB_RSA, RSA_R_IQMP_NOT_INVERSE_OF_Q); |
0f113f3e MC |
197 | } |
198 | } | |
4f6235f7 | 199 | |
665d899f PY |
200 | for (idx = 0; idx < ex_primes; idx++) { |
201 | pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); | |
202 | /* d_i = d mod (r_i - 1)? */ | |
203 | if (!BN_sub(i, pinfo->r, BN_value_one())) { | |
204 | ret = -1; | |
205 | goto err; | |
206 | } | |
207 | if (!BN_mod(j, key->d, i, ctx)) { | |
208 | ret = -1; | |
209 | goto err; | |
210 | } | |
211 | if (BN_cmp(j, pinfo->d) != 0) { | |
212 | ret = 0; | |
9311d0c4 | 213 | ERR_raise(ERR_LIB_RSA, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D); |
665d899f PY |
214 | } |
215 | /* t_i = R_i ^ -1 mod r_i ? */ | |
216 | if (!BN_mod_inverse(i, pinfo->pp, pinfo->r, ctx)) { | |
217 | ret = -1; | |
218 | goto err; | |
219 | } | |
220 | if (BN_cmp(i, pinfo->t) != 0) { | |
221 | ret = 0; | |
9311d0c4 | 222 | ERR_raise(ERR_LIB_RSA, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R); |
665d899f PY |
223 | } |
224 | } | |
225 | ||
6519b2cb | 226 | err: |
23a1d5e9 RS |
227 | BN_free(i); |
228 | BN_free(j); | |
229 | BN_free(k); | |
230 | BN_free(l); | |
231 | BN_free(m); | |
232 | BN_CTX_free(ctx); | |
464d59a5 | 233 | return ret; |
12603de6 | 234 | } |
f844f9eb | 235 | #endif /* FIPS_MODULE */ |
12603de6 | 236 | |
23b2fc0b | 237 | int ossl_rsa_validate_public(const RSA *key) |
12603de6 | 238 | { |
23b2fc0b | 239 | return ossl_rsa_sp800_56b_check_public(key); |
12603de6 SL |
240 | } |
241 | ||
23b2fc0b | 242 | int ossl_rsa_validate_private(const RSA *key) |
12603de6 | 243 | { |
23b2fc0b | 244 | return ossl_rsa_sp800_56b_check_private(key); |
12603de6 SL |
245 | } |
246 | ||
23b2fc0b | 247 | int ossl_rsa_validate_pairwise(const RSA *key) |
12603de6 | 248 | { |
f844f9eb | 249 | #ifdef FIPS_MODULE |
23b2fc0b | 250 | return ossl_rsa_sp800_56b_check_keypair(key, NULL, -1, RSA_bits(key)); |
12603de6 | 251 | #else |
518f1ee8 | 252 | return rsa_validate_keypair_multiprime(key, NULL) > 0; |
12603de6 SL |
253 | #endif |
254 | } | |
255 | ||
256 | int RSA_check_key(const RSA *key) | |
257 | { | |
258 | return RSA_check_key_ex(key, NULL); | |
259 | } | |
260 | ||
261 | int RSA_check_key_ex(const RSA *key, BN_GENCB *cb) | |
262 | { | |
f844f9eb | 263 | #ifdef FIPS_MODULE |
23b2fc0b P |
264 | return ossl_rsa_validate_public(key) |
265 | && ossl_rsa_validate_private(key) | |
266 | && ossl_rsa_validate_pairwise(key); | |
12603de6 SL |
267 | #else |
268 | return rsa_validate_keypair_multiprime(key, cb); | |
f844f9eb | 269 | #endif /* FIPS_MODULE */ |
0f113f3e | 270 | } |