xref: /freebsd/crypto/openssl/test/provider_pkey_test.c (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1 /*
2  * Copyright 2021-2022 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 <stddef.h>
11 #include <string.h>
12 #include <openssl/provider.h>
13 #include <openssl/params.h>
14 #include <openssl/core_names.h>
15 #include <openssl/evp.h>
16 #include <openssl/store.h>
17 #include "testutil.h"
18 #include "fake_rsaprov.h"
19 
20 static OSSL_LIB_CTX *libctx = NULL;
21 
22 /* Fetch SIGNATURE method using a libctx and propq */
23 static int fetch_sig(OSSL_LIB_CTX *ctx, const char *alg, const char *propq,
24                      OSSL_PROVIDER *expected_prov)
25 {
26     OSSL_PROVIDER *prov;
27     EVP_SIGNATURE *sig = EVP_SIGNATURE_fetch(ctx, "RSA", propq);
28     int ret = 0;
29 
30     if (!TEST_ptr(sig))
31         return 0;
32 
33     if (!TEST_ptr(prov = EVP_SIGNATURE_get0_provider(sig)))
34         goto end;
35 
36     if (!TEST_ptr_eq(prov, expected_prov)) {
37         TEST_info("Fetched provider: %s, Expected provider: %s",
38                   OSSL_PROVIDER_get0_name(prov),
39                   OSSL_PROVIDER_get0_name(expected_prov));
40         goto end;
41     }
42 
43     ret = 1;
44 end:
45     EVP_SIGNATURE_free(sig);
46     return ret;
47 }
48 
49 
50 static int test_pkey_sig(void)
51 {
52     OSSL_PROVIDER *deflt = NULL;
53     OSSL_PROVIDER *fake_rsa = NULL;
54     int i, ret = 0;
55     EVP_PKEY *pkey = NULL;
56     EVP_PKEY_CTX *ctx = NULL;
57 
58     if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
59         return 0;
60 
61     if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
62         goto end;
63 
64     /* Do a direct fetch to see it works */
65     if (!TEST_true(fetch_sig(libctx, "RSA", "provider=fake-rsa", fake_rsa))
66         || !TEST_true(fetch_sig(libctx, "RSA", "?provider=fake-rsa", fake_rsa)))
67         goto end;
68 
69     /* Construct a pkey using precise propq to use our provider */
70     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
71                                                    "provider=fake-rsa"))
72         || !TEST_true(EVP_PKEY_fromdata_init(ctx))
73         || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, NULL))
74         || !TEST_ptr(pkey))
75         goto end;
76 
77     EVP_PKEY_CTX_free(ctx);
78     ctx = NULL;
79 
80     /* try exercising signature_init ops a few times */
81     for (i = 0; i < 3; i++) {
82         size_t siglen;
83 
84         /*
85          * Create a signing context for our pkey with optional propq.
86          * The sign init should pick both keymgmt and signature from
87          * fake-rsa as the key is not exportable.
88          */
89         if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey,
90                                                        "?provider=default")))
91             goto end;
92 
93         /*
94          * If this picks the wrong signature without realizing it
95          * we can get a segfault or some internal error. At least watch
96          * whether fake-rsa sign_init is is exercised by calling sign.
97          */
98         if (!TEST_int_eq(EVP_PKEY_sign_init(ctx), 1))
99             goto end;
100 
101         if (!TEST_int_eq(EVP_PKEY_sign(ctx, NULL, &siglen, NULL, 0), 1)
102             || !TEST_size_t_eq(siglen, 256))
103             goto end;
104 
105         EVP_PKEY_CTX_free(ctx);
106         ctx = NULL;
107     }
108 
109     ret = 1;
110 
111 end:
112     fake_rsa_finish(fake_rsa);
113     OSSL_PROVIDER_unload(deflt);
114     EVP_PKEY_CTX_free(ctx);
115     EVP_PKEY_free(pkey);
116     return ret;
117 }
118 
119 static int test_alternative_keygen_init(void)
120 {
121     EVP_PKEY_CTX *ctx = NULL;
122     OSSL_PROVIDER *deflt = NULL;
123     OSSL_PROVIDER *fake_rsa = NULL;
124     const OSSL_PROVIDER *provider;
125     const char *provname;
126     int ret = 0;
127 
128     if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
129         goto end;
130 
131     /* first try without the fake RSA provider loaded */
132     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL)))
133         goto end;
134 
135     if (!TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0))
136         goto end;
137 
138     if (!TEST_ptr(provider = EVP_PKEY_CTX_get0_provider(ctx)))
139         goto end;
140 
141     if (!TEST_ptr(provname = OSSL_PROVIDER_get0_name(provider)))
142         goto end;
143 
144     if (!TEST_str_eq(provname, "default"))
145         goto end;
146 
147     EVP_PKEY_CTX_free(ctx);
148     ctx = NULL;
149 
150     /* now load fake RSA and try again */
151     if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
152         return 0;
153 
154     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
155                                                    "?provider=fake-rsa")))
156         goto end;
157 
158     if (!TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0))
159         goto end;
160 
161     if (!TEST_ptr(provider = EVP_PKEY_CTX_get0_provider(ctx)))
162         goto end;
163 
164     if (!TEST_ptr(provname = OSSL_PROVIDER_get0_name(provider)))
165         goto end;
166 
167     if (!TEST_str_eq(provname, "fake-rsa"))
168         goto end;
169 
170     ret = 1;
171 
172 end:
173     fake_rsa_finish(fake_rsa);
174     OSSL_PROVIDER_unload(deflt);
175     EVP_PKEY_CTX_free(ctx);
176     return ret;
177 }
178 
179 static int test_pkey_eq(void)
180 {
181     OSSL_PROVIDER *deflt = NULL;
182     OSSL_PROVIDER *fake_rsa = NULL;
183     EVP_PKEY *pkey_fake = NULL;
184     EVP_PKEY *pkey_dflt = NULL;
185     EVP_PKEY_CTX *ctx = NULL;
186     OSSL_PARAM *params = NULL;
187     int ret = 0;
188 
189     if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
190         return 0;
191 
192     if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
193         goto end;
194 
195     /* Construct a public key for fake-rsa */
196     if (!TEST_ptr(params = fake_rsa_key_params(0))
197         || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
198                                                       "provider=fake-rsa"))
199         || !TEST_true(EVP_PKEY_fromdata_init(ctx))
200         || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_fake, EVP_PKEY_PUBLIC_KEY,
201                                         params))
202         || !TEST_ptr(pkey_fake))
203         goto end;
204 
205     EVP_PKEY_CTX_free(ctx);
206     ctx = NULL;
207     OSSL_PARAM_free(params);
208     params = NULL;
209 
210     /* Construct a public key for default */
211     if (!TEST_ptr(params = fake_rsa_key_params(0))
212         || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
213                                                       "provider=default"))
214         || !TEST_true(EVP_PKEY_fromdata_init(ctx))
215         || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_dflt, EVP_PKEY_PUBLIC_KEY,
216                                         params))
217         || !TEST_ptr(pkey_dflt))
218         goto end;
219 
220     EVP_PKEY_CTX_free(ctx);
221     ctx = NULL;
222     OSSL_PARAM_free(params);
223     params = NULL;
224 
225     /* now test for equality */
226     if (!TEST_int_eq(EVP_PKEY_eq(pkey_fake, pkey_dflt), 1))
227         goto end;
228 
229     ret = 1;
230 end:
231     fake_rsa_finish(fake_rsa);
232     OSSL_PROVIDER_unload(deflt);
233     EVP_PKEY_CTX_free(ctx);
234     EVP_PKEY_free(pkey_fake);
235     EVP_PKEY_free(pkey_dflt);
236     OSSL_PARAM_free(params);
237     return ret;
238 }
239 
240 static int test_pkey_store(int idx)
241 {
242     OSSL_PROVIDER *deflt = NULL;
243     OSSL_PROVIDER *fake_rsa = NULL;
244     int ret = 0;
245     EVP_PKEY *pkey = NULL;
246     OSSL_STORE_LOADER *loader = NULL;
247     OSSL_STORE_CTX *ctx = NULL;
248     OSSL_STORE_INFO *info;
249     const char *propq = idx == 0 ? "?provider=fake-rsa"
250                                  : "?provider=default";
251 
252     /* It's important to load the default provider first for this test */
253     if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
254         goto end;
255 
256     if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
257         goto end;
258 
259     if (!TEST_ptr(loader = OSSL_STORE_LOADER_fetch(libctx, "fake_rsa",
260                                                    propq)))
261         goto end;
262 
263     OSSL_STORE_LOADER_free(loader);
264 
265     if (!TEST_ptr(ctx = OSSL_STORE_open_ex("fake_rsa:test", libctx, propq,
266                                            NULL, NULL, NULL, NULL, NULL)))
267         goto end;
268 
269     while (!OSSL_STORE_eof(ctx)
270            && (info = OSSL_STORE_load(ctx)) != NULL
271            && pkey == NULL) {
272         if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY)
273             pkey = OSSL_STORE_INFO_get1_PKEY(info);
274         OSSL_STORE_INFO_free(info);
275         info = NULL;
276     }
277 
278     if (!TEST_ptr(pkey) || !TEST_int_eq(EVP_PKEY_is_a(pkey, "RSA"), 1))
279         goto end;
280 
281     ret = 1;
282 
283 end:
284     fake_rsa_finish(fake_rsa);
285     OSSL_PROVIDER_unload(deflt);
286     OSSL_STORE_close(ctx);
287     EVP_PKEY_free(pkey);
288     return ret;
289 }
290 
291 int setup_tests(void)
292 {
293     libctx = OSSL_LIB_CTX_new();
294     if (libctx == NULL)
295         return 0;
296 
297     ADD_TEST(test_pkey_sig);
298     ADD_TEST(test_alternative_keygen_init);
299     ADD_TEST(test_pkey_eq);
300     ADD_ALL_TESTS(test_pkey_store, 2);
301 
302     return 1;
303 }
304 
305 void cleanup_tests(void)
306 {
307     OSSL_LIB_CTX_free(libctx);
308 }
309