INSTALL.md: Restore $ as command prompt indicator
[oweals/openssl.git] / test / keymgmt_internal_test.c
1 /*
2  * Copyright 2019-2020 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 #include <string.h>
11
12 #include <openssl/bio.h>
13 #include <openssl/bn.h>
14 #include <openssl/rsa.h>
15 #include <openssl/evp.h>
16 #include <openssl/provider.h>
17 #include <openssl/core_names.h>
18 #include "internal/core.h"
19 #include "internal/nelem.h"
20 #include "crypto/evp.h"          /* For the internal API */
21 #include "testutil.h"
22
23 typedef struct {
24     OPENSSL_CTX *ctx1;
25     OSSL_PROVIDER *prov1;
26     OPENSSL_CTX *ctx2;
27     OSSL_PROVIDER *prov2;
28 } FIXTURE;
29
30 static void tear_down(FIXTURE *fixture)
31 {
32     if (fixture != NULL) {
33         OSSL_PROVIDER_unload(fixture->prov1);
34         OSSL_PROVIDER_unload(fixture->prov2);
35         OPENSSL_CTX_free(fixture->ctx1);
36         OPENSSL_CTX_free(fixture->ctx2);
37         OPENSSL_free(fixture);
38     }
39 }
40
41 static FIXTURE *set_up(const char *testcase_name)
42 {
43     FIXTURE *fixture;
44
45     if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture)))
46         || !TEST_ptr(fixture->ctx1 = OPENSSL_CTX_new())
47         || !TEST_ptr(fixture->prov1 = OSSL_PROVIDER_load(fixture->ctx1,
48                                                          "default"))
49         || !TEST_ptr(fixture->ctx2 = OPENSSL_CTX_new())
50         || !TEST_ptr(fixture->prov2 = OSSL_PROVIDER_load(fixture->ctx2,
51                                                          "default"))) {
52         tear_down(fixture);
53         return NULL;
54     }
55     return fixture;
56 }
57
58 /* Array indexes */
59 #define N       0
60 #define E       1
61 #define D       2
62 #define P       3
63 #define Q       4
64 #define F3      5                /* Extra factor */
65 #define DP      6
66 #define DQ      7
67 #define E3      8                /* Extra exponent */
68 #define QINV    9
69 #define C2      10               /* Extra coefficient */
70
71 /*
72  * We have to do this because OSSL_PARAM_get_ulong() can't handle params
73  * holding data that isn't exactly sizeof(uint32_t) or sizeof(uint64_t),
74  * and because the other end deals with BIGNUM, the resulting param might
75  * be any size.  In this particular test, we know that the expected data
76  * fits within an unsigned long, and we want to get the data in that form
77  * to make testing of values easier.
78  */
79 static int get_ulong_via_BN(const OSSL_PARAM *p, unsigned long *goal)
80 {
81     BIGNUM *n = NULL;
82     int ret = 1;                 /* Ever so hopeful */
83
84     if (!TEST_true(OSSL_PARAM_get_BN(p, &n))
85         || !TEST_true(BN_bn2nativepad(n, (unsigned char *)goal, sizeof(*goal))))
86         ret = 0;
87     BN_free(n);
88     return ret;
89 }
90
91 static int export_cb(const OSSL_PARAM *params, void *arg)
92 {
93     unsigned long *keydata = arg;
94     const OSSL_PARAM *p = NULL;
95
96     if (keydata == NULL)
97         return 0;
98
99     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N))
100         || !TEST_true(get_ulong_via_BN(p, &keydata[N]))
101         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E))
102         || !TEST_true(get_ulong_via_BN(p, &keydata[E]))
103         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D))
104         || !TEST_true(get_ulong_via_BN(p, &keydata[D])))
105         return 0;
106
107     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1))
108         || !TEST_true(get_ulong_via_BN(p, &keydata[P]))
109         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2))
110         || !TEST_true(get_ulong_via_BN(p, &keydata[Q]))
111         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR3))
112         || !TEST_true(get_ulong_via_BN(p, &keydata[F3])))
113         return 0;
114
115     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT1))
116         || !TEST_true(get_ulong_via_BN(p, &keydata[DP]))
117         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT2))
118         || !TEST_true(get_ulong_via_BN(p, &keydata[DQ]))
119         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT3))
120         || !TEST_true(get_ulong_via_BN(p, &keydata[E3])))
121         return 0;
122
123     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1))
124         || !TEST_true(get_ulong_via_BN(p, &keydata[QINV]))
125         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT2))
126         || !TEST_true(get_ulong_via_BN(p, &keydata[C2])))
127         return 0;
128
129     return 1;
130 }
131
132 static int test_pass_rsa(FIXTURE *fixture)
133 {
134     size_t i;
135     int ret = 0;
136     RSA *rsa = NULL;
137     BIGNUM *bn1 = NULL, *bn2 = NULL, *bn3 = NULL;
138     EVP_PKEY *pk = NULL;
139     EVP_KEYMGMT *km1 = NULL, *km2 = NULL;
140     void *provkey = NULL;
141     BIGNUM *bn_primes[1] = { NULL };
142     BIGNUM *bn_exps[1] = { NULL };
143     BIGNUM *bn_coeffs[1] = { NULL };
144     /*
145      * 32-bit RSA key, extracted from this command,
146      * executed with OpenSSL 1.0.2:
147      * An extra factor was added just for testing purposes.
148      *
149      * openssl genrsa 32 | openssl rsa -text
150      */
151     static BN_ULONG expected[] = {
152         0xbc747fc5,              /* N */
153         0x10001,                 /* E */
154         0x7b133399,              /* D */
155         0xe963,                  /* P */
156         0xceb7,                  /* Q */
157         1,                       /* F3 */
158         0x8599,                  /* DP */
159         0xbd87,                  /* DQ */
160         2,                       /* E3 */
161         0xcc3b,                  /* QINV */
162         3,                       /* C3 */
163         0                        /* Extra, should remain zero */
164     };
165     static unsigned long keydata[OSSL_NELEM(expected)] = { 0, };
166
167     if (!TEST_ptr(rsa = RSA_new()))
168         goto err;
169
170     if (!TEST_ptr(bn1 = BN_new())
171         || !TEST_true(BN_set_word(bn1, expected[N]))
172         || !TEST_ptr(bn2 = BN_new())
173         || !TEST_true(BN_set_word(bn2, expected[E]))
174         || !TEST_ptr(bn3 = BN_new())
175         || !TEST_true(BN_set_word(bn3, expected[D]))
176         || !TEST_true(RSA_set0_key(rsa, bn1, bn2, bn3)))
177         goto err;
178
179     if (!TEST_ptr(bn1 = BN_new())
180         || !TEST_true(BN_set_word(bn1, expected[P]))
181         || !TEST_ptr(bn2 = BN_new())
182         || !TEST_true(BN_set_word(bn2, expected[Q]))
183         || !TEST_true(RSA_set0_factors(rsa, bn1, bn2)))
184         goto err;
185
186     if (!TEST_ptr(bn1 = BN_new())
187         || !TEST_true(BN_set_word(bn1, expected[DP]))
188         || !TEST_ptr(bn2 = BN_new())
189         || !TEST_true(BN_set_word(bn2, expected[DQ]))
190         || !TEST_ptr(bn3 = BN_new())
191         || !TEST_true(BN_set_word(bn3, expected[QINV]))
192         || !TEST_true(RSA_set0_crt_params(rsa, bn1, bn2, bn3)))
193         goto err;
194     bn1 = bn2 = bn3 = NULL;
195
196     if (!TEST_ptr(bn_primes[0] = BN_new())
197         || !TEST_true(BN_set_word(bn_primes[0], expected[F3]))
198         || !TEST_ptr(bn_exps[0] = BN_new())
199         || !TEST_true(BN_set_word(bn_exps[0], expected[E3]))
200         || !TEST_ptr(bn_coeffs[0] = BN_new())
201         || !TEST_true(BN_set_word(bn_coeffs[0], expected[C2]))
202         || !TEST_true(RSA_set0_multi_prime_params(rsa, bn_primes, bn_exps,
203                                                   bn_coeffs, 1)))
204         goto err;
205
206     if (!TEST_ptr(pk = EVP_PKEY_new())
207         || !TEST_true(EVP_PKEY_assign_RSA(pk, rsa)))
208         goto err;
209     rsa = NULL;
210
211     if (!TEST_ptr(km1 = EVP_KEYMGMT_fetch(fixture->ctx1, "RSA", NULL))
212         || !TEST_ptr(km2 = EVP_KEYMGMT_fetch(fixture->ctx2, "RSA", NULL))
213         || !TEST_ptr_ne(km1, km2))
214         goto err;
215
216     if (!TEST_ptr(provkey = evp_pkey_export_to_provider(pk, NULL, &km1, NULL))
217         || !TEST_true(evp_keymgmt_export(km2, provkey,
218                                          OSSL_KEYMGMT_SELECT_KEYPAIR,
219                                          &export_cb, keydata)))
220         goto err;
221
222     /*
223      * At this point, the hope is that keydata will have all the numbers
224      * from the key.
225      */
226
227     for (i = 0; i < OSSL_NELEM(expected); i++) {
228         int rv = TEST_int_eq(expected[i], keydata[i]);
229
230         if (!rv)
231             TEST_info("i = %zu", i);
232         else
233             ret++;
234     }
235
236     ret = (ret == OSSL_NELEM(expected));
237
238  err:
239     RSA_free(rsa);
240     BN_free(bn1);
241     BN_free(bn2);
242     BN_free(bn3);
243     EVP_PKEY_free(pk);
244     EVP_KEYMGMT_free(km1);
245     EVP_KEYMGMT_free(km2);
246
247     return ret;
248 }
249
250 static int (*tests[])(FIXTURE *) = {
251     test_pass_rsa
252 };
253
254 static int test_pass_key(int n)
255 {
256     SETUP_TEST_FIXTURE(FIXTURE, set_up);
257     EXECUTE_TEST(tests[n], tear_down);
258     return result;
259 }
260
261 int setup_tests(void)
262 {
263     ADD_ALL_TESTS(test_pass_key, 1);
264     return 1;
265 }