xref: /freebsd/crypto/openssl/test/evp_fetch_prov_test.c (revision 95eb4b873b6a8b527c5bd78d7191975dfca38998)
1 /*
2  * Copyright 2019-2021 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  * SHA256 low level APIs are deprecated for public use, but still ok for
12  * internal use.  Note, that due to symbols not being exported, only the
13  * #defines can be accessed.  In this case SHA256_CBLOCK.
14  */
15 #include "internal/deprecated.h"
16 
17 #include <string.h>
18 #include <openssl/sha.h>
19 #include <openssl/evp.h>
20 #include <openssl/provider.h>
21 #include "internal/sizes.h"
22 #include "testutil.h"
23 
24 static char *config_file = NULL;
25 static char *alg = "digest";
26 static int use_default_ctx = 0;
27 static char *fetch_property = NULL;
28 static int expected_fetch_result = 1;
29 
30 typedef enum OPTION_choice {
31     OPT_ERR = -1,
32     OPT_EOF = 0,
33     OPT_ALG_FETCH_TYPE,
34     OPT_FETCH_PROPERTY,
35     OPT_FETCH_FAILURE,
36     OPT_USE_DEFAULTCTX,
37     OPT_CONFIG_FILE,
38     OPT_TEST_ENUM
39 } OPTION_CHOICE;
40 
41 const OPTIONS *test_get_options(void)
42 {
43     static const OPTIONS test_options[] = {
44         OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("[provname...]\n"),
45         { "config", OPT_CONFIG_FILE, '<', "The configuration file to use for the libctx" },
46         { "type", OPT_ALG_FETCH_TYPE, 's', "The fetch type to test" },
47         { "property", OPT_FETCH_PROPERTY, 's', "The fetch property e.g. provider=fips" },
48         { "fetchfail", OPT_FETCH_FAILURE, '-', "fetch is expected to fail" },
49         { "defaultctx", OPT_USE_DEFAULTCTX, '-',
50           "Use the default context if this is set" },
51         { OPT_HELP_STR, 1, '-', "file\tProvider names to explicitly load\n" },
52         { NULL }
53     };
54     return test_options;
55 }
56 
57 static int calculate_digest(const EVP_MD *md, const char *msg, size_t len,
58                             const unsigned char *exptd)
59 {
60     unsigned char out[SHA256_DIGEST_LENGTH];
61     EVP_MD_CTX *ctx;
62     int ret = 0;
63 
64     if (!TEST_ptr(ctx = EVP_MD_CTX_new())
65             || !TEST_true(EVP_DigestInit_ex(ctx, md, NULL))
66             || !TEST_true(EVP_DigestUpdate(ctx, msg, len))
67             || !TEST_true(EVP_DigestFinal_ex(ctx, out, NULL))
68             || !TEST_mem_eq(out, SHA256_DIGEST_LENGTH, exptd,
69                             SHA256_DIGEST_LENGTH)
70             || !TEST_true(md == EVP_MD_CTX_get0_md(ctx)))
71         goto err;
72 
73     ret = 1;
74  err:
75     EVP_MD_CTX_free(ctx);
76     return ret;
77 }
78 
79 static int load_providers(OSSL_LIB_CTX **libctx, OSSL_PROVIDER *prov[])
80 {
81     OSSL_LIB_CTX *ctx = NULL;
82     int ret = 0;
83     size_t i;
84 
85     ctx = OSSL_LIB_CTX_new();
86     if (!TEST_ptr(ctx))
87         goto err;
88 
89     if (!TEST_true(OSSL_LIB_CTX_load_config(ctx, config_file)))
90         goto err;
91     if (test_get_argument_count() > 2)
92         goto err;
93 
94     for (i = 0; i < test_get_argument_count(); ++i) {
95         char *provname = test_get_argument(i);
96         prov[i] = OSSL_PROVIDER_load(ctx, provname);
97         if (!TEST_ptr(prov[i]))
98             goto err;
99     }
100 
101     ret = 1;
102     *libctx = ctx;
103 err:
104     if (ret == 0)
105         OSSL_LIB_CTX_free(ctx);
106     return ret;
107 }
108 
109 static void unload_providers(OSSL_LIB_CTX **libctx, OSSL_PROVIDER *prov[])
110 {
111     if (prov[0] != NULL)
112         OSSL_PROVIDER_unload(prov[0]);
113     if (prov[1] != NULL)
114         OSSL_PROVIDER_unload(prov[1]);
115     /* Not normally needed, but we would like to test that
116      * OPENSSL_thread_stop_ex() behaves as expected.
117      */
118     if (libctx != NULL && *libctx != NULL) {
119         OPENSSL_thread_stop_ex(*libctx);
120         OSSL_LIB_CTX_free(*libctx);
121     }
122 }
123 
124 static X509_ALGOR *make_algor(int nid)
125 {
126     X509_ALGOR *algor;
127 
128     if (!TEST_ptr(algor = X509_ALGOR_new())
129         || !TEST_true(X509_ALGOR_set0(algor, OBJ_nid2obj(nid),
130                                       V_ASN1_UNDEF, NULL))) {
131         X509_ALGOR_free(algor);
132         return NULL;
133     }
134     return algor;
135 }
136 
137 /*
138  * Test EVP_MD_fetch()
139  */
140 static int test_md(const EVP_MD *md)
141 {
142     const char testmsg[] = "Hello world";
143     const unsigned char exptd[] = {
144       0x27, 0x51, 0x8b, 0xa9, 0x68, 0x30, 0x11, 0xf6, 0xb3, 0x96, 0x07, 0x2c,
145       0x05, 0xf6, 0x65, 0x6d, 0x04, 0xf5, 0xfb, 0xc3, 0x78, 0x7c, 0xf9, 0x24,
146       0x90, 0xec, 0x60, 0x6e, 0x50, 0x92, 0xe3, 0x26
147     };
148 
149     return TEST_ptr(md)
150         && TEST_true(EVP_MD_is_a(md, "SHA256"))
151         && TEST_true(calculate_digest(md, testmsg, sizeof(testmsg), exptd))
152         && TEST_int_eq(EVP_MD_get_size(md), SHA256_DIGEST_LENGTH)
153         && TEST_int_eq(EVP_MD_get_block_size(md), SHA256_CBLOCK);
154 }
155 
156 static int test_implicit_EVP_MD_fetch(void)
157 {
158     OSSL_LIB_CTX *ctx = NULL;
159     OSSL_PROVIDER *prov[2] = {NULL, NULL};
160     int ret = 0;
161 
162     ret = (use_default_ctx == 0 || load_providers(&ctx, prov))
163         && test_md(EVP_sha256());
164 
165     unload_providers(&ctx, prov);
166     return ret;
167 }
168 
169 static int test_explicit_EVP_MD_fetch(const char *id)
170 {
171     OSSL_LIB_CTX *ctx = NULL;
172     EVP_MD *md = NULL;
173     OSSL_PROVIDER *prov[2] = {NULL, NULL};
174     int ret = 0;
175 
176     if (use_default_ctx == 0 && !load_providers(&ctx, prov))
177         goto err;
178 
179     md = EVP_MD_fetch(ctx, id, fetch_property);
180     if (expected_fetch_result != 0) {
181         if (!test_md(md))
182             goto err;
183 
184         /* Also test EVP_MD_up_ref() while we're doing this */
185         if (!TEST_true(EVP_MD_up_ref(md)))
186             goto err;
187         /* Ref count should now be 2. Release first one here */
188         EVP_MD_free(md);
189     } else {
190         if (!TEST_ptr_null(md))
191             goto err;
192     }
193     ret = 1;
194 
195  err:
196     EVP_MD_free(md);
197     unload_providers(&ctx, prov);
198     return ret;
199 }
200 
201 static int test_explicit_EVP_MD_fetch_by_name(void)
202 {
203     return test_explicit_EVP_MD_fetch("SHA256");
204 }
205 
206 /*
207  * idx 0: Allow names from OBJ_obj2txt()
208  * idx 1: Force an OID in text form from OBJ_obj2txt()
209  */
210 static int test_explicit_EVP_MD_fetch_by_X509_ALGOR(int idx)
211 {
212     int ret = 0;
213     X509_ALGOR *algor = make_algor(NID_sha256);
214     const ASN1_OBJECT *obj;
215     char id[OSSL_MAX_NAME_SIZE];
216 
217     if (algor == NULL)
218         return 0;
219 
220     X509_ALGOR_get0(&obj, NULL, NULL, algor);
221     switch (idx) {
222     case 0:
223         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 0), 0))
224             goto end;
225         break;
226     case 1:
227         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 1), 0))
228             goto end;
229         break;
230     }
231 
232     ret = test_explicit_EVP_MD_fetch(id);
233  end:
234     X509_ALGOR_free(algor);
235     return ret;
236 }
237 
238 /*
239  * Test EVP_CIPHER_fetch()
240  */
241 static int encrypt_decrypt(const EVP_CIPHER *cipher, const unsigned char *msg,
242                            size_t len)
243 {
244     int ret = 0, ctlen, ptlen;
245     EVP_CIPHER_CTX *ctx = NULL;
246     unsigned char key[128 / 8];
247     unsigned char ct[64], pt[64];
248 
249     memset(key, 0, sizeof(key));
250     if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
251             || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, 1))
252             || !TEST_true(EVP_CipherUpdate(ctx, ct, &ctlen, msg, len))
253             || !TEST_true(EVP_CipherFinal_ex(ctx, ct, &ctlen))
254             || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, 0))
255             || !TEST_true(EVP_CipherUpdate(ctx, pt, &ptlen, ct, ctlen))
256             || !TEST_true(EVP_CipherFinal_ex(ctx, pt, &ptlen))
257             || !TEST_mem_eq(pt, ptlen, msg, len))
258         goto err;
259 
260     ret = 1;
261 err:
262     EVP_CIPHER_CTX_free(ctx);
263     return ret;
264 }
265 
266 static int test_cipher(const EVP_CIPHER *cipher)
267 {
268     const unsigned char testmsg[] = "Hello world";
269 
270     return TEST_ptr(cipher)
271         && TEST_true(encrypt_decrypt(cipher, testmsg, sizeof(testmsg)));
272 }
273 
274 static int test_implicit_EVP_CIPHER_fetch(void)
275 {
276     OSSL_LIB_CTX *ctx = NULL;
277     OSSL_PROVIDER *prov[2] = {NULL, NULL};
278     int ret = 0;
279 
280     ret = (use_default_ctx == 0 || load_providers(&ctx, prov))
281         && test_cipher(EVP_aes_128_cbc());
282 
283     unload_providers(&ctx, prov);
284     return ret;
285 }
286 
287 static int test_explicit_EVP_CIPHER_fetch(const char *id)
288 {
289     OSSL_LIB_CTX *ctx = NULL;
290     EVP_CIPHER *cipher = NULL;
291     OSSL_PROVIDER *prov[2] = {NULL, NULL};
292     int ret = 0;
293 
294     if (use_default_ctx == 0 && !load_providers(&ctx, prov))
295         goto err;
296 
297     cipher = EVP_CIPHER_fetch(ctx, id, fetch_property);
298     if (expected_fetch_result != 0) {
299         if (!test_cipher(cipher))
300             goto err;
301 
302         if (!TEST_true(EVP_CIPHER_up_ref(cipher)))
303             goto err;
304         /* Ref count should now be 2. Release first one here */
305         EVP_CIPHER_free(cipher);
306     } else {
307         if (!TEST_ptr_null(cipher))
308             goto err;
309     }
310     ret = 1;
311 err:
312     EVP_CIPHER_free(cipher);
313     unload_providers(&ctx, prov);
314     return ret;
315 }
316 
317 static int test_explicit_EVP_CIPHER_fetch_by_name(void)
318 {
319     return test_explicit_EVP_CIPHER_fetch("AES-128-CBC");
320 }
321 
322 /*
323  * idx 0: Allow names from OBJ_obj2txt()
324  * idx 1: Force an OID in text form from OBJ_obj2txt()
325  */
326 static int test_explicit_EVP_CIPHER_fetch_by_X509_ALGOR(int idx)
327 {
328     int ret = 0;
329     X509_ALGOR *algor = make_algor(NID_aes_128_cbc);
330     const ASN1_OBJECT *obj;
331     char id[OSSL_MAX_NAME_SIZE];
332 
333     if (algor == NULL)
334         return 0;
335 
336     X509_ALGOR_get0(&obj, NULL, NULL, algor);
337     switch (idx) {
338     case 0:
339         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 0), 0))
340             goto end;
341         break;
342     case 1:
343         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 1), 0))
344             goto end;
345         break;
346     }
347 
348     ret = test_explicit_EVP_CIPHER_fetch(id);
349  end:
350     X509_ALGOR_free(algor);
351     return ret;
352 }
353 
354 int setup_tests(void)
355 {
356     OPTION_CHOICE o;
357 
358     while ((o = opt_next()) != OPT_EOF) {
359         switch (o) {
360         case OPT_CONFIG_FILE:
361             config_file = opt_arg();
362             break;
363         case OPT_ALG_FETCH_TYPE:
364             alg = opt_arg();
365             break;
366         case OPT_FETCH_PROPERTY:
367             fetch_property = opt_arg();
368             break;
369         case OPT_FETCH_FAILURE:
370             expected_fetch_result = 0;
371             break;
372         case OPT_USE_DEFAULTCTX:
373             use_default_ctx = 1;
374             break;
375         case OPT_TEST_CASES:
376            break;
377         default:
378         case OPT_ERR:
379             return 0;
380         }
381     }
382     if (strcmp(alg, "digest") == 0) {
383         ADD_TEST(test_implicit_EVP_MD_fetch);
384         ADD_TEST(test_explicit_EVP_MD_fetch_by_name);
385         ADD_ALL_TESTS_NOSUBTEST(test_explicit_EVP_MD_fetch_by_X509_ALGOR, 2);
386     } else {
387         ADD_TEST(test_implicit_EVP_CIPHER_fetch);
388         ADD_TEST(test_explicit_EVP_CIPHER_fetch_by_name);
389         ADD_ALL_TESTS_NOSUBTEST(test_explicit_EVP_CIPHER_fetch_by_X509_ALGOR, 2);
390     }
391     return 1;
392 }
393