1 /*
2 * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
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
8 */
9
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
16 #include <string.h>
17
18 #include <openssl/bio.h>
19 #include <openssl/bn.h>
20 #include <openssl/rsa.h>
21 #include <openssl/evp.h>
22 #include <openssl/pem.h>
23 #include <openssl/provider.h>
24 #include <openssl/core_names.h>
25 #include "internal/core.h"
26 #include "internal/nelem.h"
27 #include "crypto/evp.h" /* For the internal API */
28 #include "testutil.h"
29
30 typedef struct {
31 OSSL_LIB_CTX *ctx1;
32 OSSL_PROVIDER *prov1;
33 OSSL_LIB_CTX *ctx2;
34 OSSL_PROVIDER *prov2;
35 } FIXTURE;
36
37 /* Collected arguments */
38 static const char *cert_filename = NULL;
39
tear_down(FIXTURE * fixture)40 static void tear_down(FIXTURE *fixture)
41 {
42 if (fixture != NULL) {
43 OSSL_PROVIDER_unload(fixture->prov1);
44 OSSL_PROVIDER_unload(fixture->prov2);
45 OSSL_LIB_CTX_free(fixture->ctx1);
46 OSSL_LIB_CTX_free(fixture->ctx2);
47 OPENSSL_free(fixture);
48 }
49 }
50
set_up(const char * testcase_name)51 static FIXTURE *set_up(const char *testcase_name)
52 {
53 FIXTURE *fixture;
54
55 if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture)))
56 || !TEST_ptr(fixture->ctx1 = OSSL_LIB_CTX_new())
57 || !TEST_ptr(fixture->prov1 = OSSL_PROVIDER_load(fixture->ctx1,
58 "default"))
59 || !TEST_ptr(fixture->ctx2 = OSSL_LIB_CTX_new())
60 || !TEST_ptr(fixture->prov2 = OSSL_PROVIDER_load(fixture->ctx2,
61 "default"))) {
62 tear_down(fixture);
63 return NULL;
64 }
65 return fixture;
66 }
67
68 /* Array indexes */
69 #define N 0
70 #define E 1
71 #define D 2
72 #define P 3
73 #define Q 4
74 #define F3 5 /* Extra factor */
75 #define DP 6
76 #define DQ 7
77 #define E3 8 /* Extra exponent */
78 #define QINV 9
79 #define C2 10 /* Extra coefficient */
80
81 /*
82 * We have to do this because OSSL_PARAM_get_ulong() can't handle params
83 * holding data that isn't exactly sizeof(uint32_t) or sizeof(uint64_t),
84 * and because the other end deals with BIGNUM, the resulting param might
85 * be any size. In this particular test, we know that the expected data
86 * fits within an unsigned long, and we want to get the data in that form
87 * to make testing of values easier.
88 */
get_ulong_via_BN(const OSSL_PARAM * p,unsigned long * goal)89 static int get_ulong_via_BN(const OSSL_PARAM *p, unsigned long *goal)
90 {
91 BIGNUM *n = NULL;
92 int ret = 1; /* Ever so hopeful */
93
94 if (!TEST_true(OSSL_PARAM_get_BN(p, &n))
95 || !TEST_int_ge(BN_bn2nativepad(n, (unsigned char *)goal, sizeof(*goal)), 0))
96 ret = 0;
97 BN_free(n);
98 return ret;
99 }
100
export_cb(const OSSL_PARAM * params,void * arg)101 static int export_cb(const OSSL_PARAM *params, void *arg)
102 {
103 unsigned long *keydata = arg;
104 const OSSL_PARAM *p = NULL;
105
106 if (keydata == NULL)
107 return 0;
108
109 if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N))
110 || !TEST_true(get_ulong_via_BN(p, &keydata[N]))
111 || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E))
112 || !TEST_true(get_ulong_via_BN(p, &keydata[E]))
113 || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D))
114 || !TEST_true(get_ulong_via_BN(p, &keydata[D])))
115 return 0;
116
117 if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1))
118 || !TEST_true(get_ulong_via_BN(p, &keydata[P]))
119 || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2))
120 || !TEST_true(get_ulong_via_BN(p, &keydata[Q]))
121 || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR3))
122 || !TEST_true(get_ulong_via_BN(p, &keydata[F3])))
123 return 0;
124
125 if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT1))
126 || !TEST_true(get_ulong_via_BN(p, &keydata[DP]))
127 || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT2))
128 || !TEST_true(get_ulong_via_BN(p, &keydata[DQ]))
129 || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT3))
130 || !TEST_true(get_ulong_via_BN(p, &keydata[E3])))
131 return 0;
132
133 if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1))
134 || !TEST_true(get_ulong_via_BN(p, &keydata[QINV]))
135 || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT2))
136 || !TEST_true(get_ulong_via_BN(p, &keydata[C2])))
137 return 0;
138
139 return 1;
140 }
141
test_pass_rsa(FIXTURE * fixture)142 static int test_pass_rsa(FIXTURE *fixture)
143 {
144 size_t i;
145 int ret = 0;
146 RSA *rsa = NULL;
147 BIGNUM *bn1 = NULL, *bn2 = NULL, *bn3 = NULL;
148 EVP_PKEY *pk = NULL, *dup_pk = NULL;
149 EVP_KEYMGMT *km = NULL, *km1 = NULL, *km2 = NULL, *km3 = NULL;
150 void *provkey = NULL, *provkey2 = NULL;
151 BIGNUM *bn_primes[1] = { NULL };
152 BIGNUM *bn_exps[1] = { NULL };
153 BIGNUM *bn_coeffs[1] = { NULL };
154 /*
155 * 32-bit RSA key, extracted from this command,
156 * executed with OpenSSL 1.0.2:
157 * An extra factor was added just for testing purposes.
158 *
159 * openssl genrsa 32 | openssl rsa -text
160 */
161 static BN_ULONG expected[] = {
162 0xbc747fc5, /* N */
163 0x10001, /* E */
164 0x7b133399, /* D */
165 0xe963, /* P */
166 0xceb7, /* Q */
167 1, /* F3 */
168 0x8599, /* DP */
169 0xbd87, /* DQ */
170 2, /* E3 */
171 0xcc3b, /* QINV */
172 3, /* C3 */
173 0 /* Extra, should remain zero */
174 };
175 static unsigned long keydata[OSSL_NELEM(expected)] = { 0, };
176
177 if (!TEST_ptr(rsa = RSA_new()))
178 goto err;
179
180 if (!TEST_ptr(bn1 = BN_new())
181 || !TEST_true(BN_set_word(bn1, expected[N]))
182 || !TEST_ptr(bn2 = BN_new())
183 || !TEST_true(BN_set_word(bn2, expected[E]))
184 || !TEST_ptr(bn3 = BN_new())
185 || !TEST_true(BN_set_word(bn3, expected[D]))
186 || !TEST_true(RSA_set0_key(rsa, bn1, bn2, bn3)))
187 goto err;
188
189 if (!TEST_ptr(bn1 = BN_new())
190 || !TEST_true(BN_set_word(bn1, expected[P]))
191 || !TEST_ptr(bn2 = BN_new())
192 || !TEST_true(BN_set_word(bn2, expected[Q]))
193 || !TEST_true(RSA_set0_factors(rsa, bn1, bn2)))
194 goto err;
195
196 if (!TEST_ptr(bn1 = BN_new())
197 || !TEST_true(BN_set_word(bn1, expected[DP]))
198 || !TEST_ptr(bn2 = BN_new())
199 || !TEST_true(BN_set_word(bn2, expected[DQ]))
200 || !TEST_ptr(bn3 = BN_new())
201 || !TEST_true(BN_set_word(bn3, expected[QINV]))
202 || !TEST_true(RSA_set0_crt_params(rsa, bn1, bn2, bn3)))
203 goto err;
204 bn1 = bn2 = bn3 = NULL;
205
206 if (!TEST_ptr(bn_primes[0] = BN_new())
207 || !TEST_true(BN_set_word(bn_primes[0], expected[F3]))
208 || !TEST_ptr(bn_exps[0] = BN_new())
209 || !TEST_true(BN_set_word(bn_exps[0], expected[E3]))
210 || !TEST_ptr(bn_coeffs[0] = BN_new())
211 || !TEST_true(BN_set_word(bn_coeffs[0], expected[C2]))
212 || !TEST_true(RSA_set0_multi_prime_params(rsa, bn_primes, bn_exps,
213 bn_coeffs, 1)))
214 goto err;
215
216 if (!TEST_ptr(pk = EVP_PKEY_new())
217 || !TEST_true(EVP_PKEY_assign_RSA(pk, rsa)))
218 goto err;
219 rsa = NULL;
220
221 if (!TEST_ptr(km1 = EVP_KEYMGMT_fetch(fixture->ctx1, "RSA", NULL))
222 || !TEST_ptr(km2 = EVP_KEYMGMT_fetch(fixture->ctx2, "RSA", NULL))
223 || !TEST_ptr(km3 = EVP_KEYMGMT_fetch(fixture->ctx1, "RSA-PSS", NULL))
224 || !TEST_ptr_ne(km1, km2))
225 goto err;
226
227 for (;;) {
228 ret = 0;
229 km = km3;
230 /* Check that we can't export an RSA key into an RSA-PSS keymanager */
231 if (!TEST_ptr_null(provkey2 = evp_pkey_export_to_provider(pk, NULL,
232 &km,
233 NULL)))
234 goto err;
235
236 if (!TEST_ptr(provkey = evp_pkey_export_to_provider(pk, NULL, &km1,
237 NULL))
238 || !TEST_true(evp_keymgmt_export(km2, provkey,
239 OSSL_KEYMGMT_SELECT_KEYPAIR,
240 &export_cb, keydata)))
241 goto err;
242
243 /*
244 * At this point, the hope is that keydata will have all the numbers
245 * from the key.
246 */
247
248 for (i = 0; i < OSSL_NELEM(expected); i++) {
249 int rv = TEST_int_eq(expected[i], keydata[i]);
250
251 if (!rv)
252 TEST_info("i = %zu", i);
253 else
254 ret++;
255 }
256
257 ret = (ret == OSSL_NELEM(expected));
258
259 if (!ret || dup_pk != NULL)
260 break;
261
262 if (!TEST_ptr(dup_pk = EVP_PKEY_dup(pk)))
263 goto err;
264
265 ret = TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1);
266 EVP_PKEY_free(pk);
267 pk = dup_pk;
268 if (!ret)
269 goto err;
270 }
271
272 err:
273 RSA_free(rsa);
274 BN_free(bn1);
275 BN_free(bn2);
276 BN_free(bn3);
277 EVP_PKEY_free(pk);
278 EVP_KEYMGMT_free(km1);
279 EVP_KEYMGMT_free(km2);
280 EVP_KEYMGMT_free(km3);
281
282 return ret;
283 }
284
285 static int (*tests[])(FIXTURE *) = {
286 test_pass_rsa
287 };
288
test_pass_key(int n)289 static int test_pass_key(int n)
290 {
291 SETUP_TEST_FIXTURE(FIXTURE, set_up);
292 EXECUTE_TEST(tests[n], tear_down);
293 return result;
294 }
295
test_evp_pkey_export_to_provider(int n)296 static int test_evp_pkey_export_to_provider(int n)
297 {
298 OSSL_LIB_CTX *libctx = NULL;
299 OSSL_PROVIDER *prov = NULL;
300 X509 *cert = NULL;
301 BIO *bio = NULL;
302 X509_PUBKEY *pubkey = NULL;
303 EVP_KEYMGMT *keymgmt = NULL;
304 EVP_PKEY *pkey = NULL;
305 void *keydata = NULL;
306 int ret = 0;
307
308 if (!TEST_ptr(libctx = OSSL_LIB_CTX_new())
309 || !TEST_ptr(prov = OSSL_PROVIDER_load(libctx, "default")))
310 goto end;
311
312 if ((bio = BIO_new_file(cert_filename, "r")) == NULL) {
313 TEST_error("Couldn't open '%s' for reading\n", cert_filename);
314 TEST_openssl_errors();
315 goto end;
316 }
317
318 if ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) {
319 TEST_error("'%s' doesn't appear to be a X.509 certificate in PEM format\n",
320 cert_filename);
321 TEST_openssl_errors();
322 goto end;
323 }
324
325 pubkey = X509_get_X509_PUBKEY(cert);
326 pkey = X509_PUBKEY_get0(pubkey);
327
328 if (n == 0) {
329 if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL,
330 NULL, NULL)))
331 goto end;
332 } else if (n == 1) {
333 if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL,
334 &keymgmt, NULL)))
335 goto end;
336 } else {
337 keymgmt = EVP_KEYMGMT_fetch(libctx, "RSA", NULL);
338
339 if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL,
340 &keymgmt, NULL)))
341 goto end;
342 }
343
344 ret = 1;
345 end:
346 BIO_free(bio);
347 X509_free(cert);
348 EVP_KEYMGMT_free(keymgmt);
349 OSSL_PROVIDER_unload(prov);
350 OSSL_LIB_CTX_free(libctx);
351 return ret;
352 }
353
setup_tests(void)354 int setup_tests(void)
355 {
356 if (!TEST_ptr(cert_filename = test_get_argument(0)))
357 return 0;
358
359 ADD_ALL_TESTS(test_pass_key, 1);
360 ADD_ALL_TESTS(test_evp_pkey_export_to_provider, 3);
361 return 1;
362 }
363