xref: /openssl/test/evp_fetch_prov_test.c (revision 506ff206)
1 /*
2  * Copyright 2019-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 /*
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 
test_get_options(void)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 
calculate_digest(const EVP_MD * md,const char * msg,size_t len,const unsigned char * exptd)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 
load_providers(OSSL_LIB_CTX ** libctx,OSSL_PROVIDER * prov[])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 
unload_providers(OSSL_LIB_CTX ** libctx,OSSL_PROVIDER * prov[])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 
test_legacy_provider_unloaded(void)124 static int test_legacy_provider_unloaded(void)
125 {
126     OSSL_LIB_CTX *ctx = NULL;
127     int rc = 0;
128 
129     ctx = OSSL_LIB_CTX_new();
130     if (!TEST_ptr(ctx))
131         goto err;
132 
133     if (!TEST_true(OSSL_LIB_CTX_load_config(ctx, config_file)))
134         goto err;
135 
136     if (!TEST_int_eq(OSSL_PROVIDER_available(ctx, "legacy"), 0))
137         goto err;
138 
139     rc = 1;
140 err:
141     OSSL_LIB_CTX_free(ctx);
142     return rc;
143 }
144 
make_algor(int nid)145 static X509_ALGOR *make_algor(int nid)
146 {
147     X509_ALGOR *algor;
148 
149     if (!TEST_ptr(algor = X509_ALGOR_new())
150         || !TEST_true(X509_ALGOR_set0(algor, OBJ_nid2obj(nid),
151                                       V_ASN1_UNDEF, NULL))) {
152         X509_ALGOR_free(algor);
153         return NULL;
154     }
155     return algor;
156 }
157 
158 /*
159  * Test EVP_MD_fetch()
160  */
test_md(const EVP_MD * md)161 static int test_md(const EVP_MD *md)
162 {
163     const char testmsg[] = "Hello world";
164     const unsigned char exptd[] = {
165       0x27, 0x51, 0x8b, 0xa9, 0x68, 0x30, 0x11, 0xf6, 0xb3, 0x96, 0x07, 0x2c,
166       0x05, 0xf6, 0x65, 0x6d, 0x04, 0xf5, 0xfb, 0xc3, 0x78, 0x7c, 0xf9, 0x24,
167       0x90, 0xec, 0x60, 0x6e, 0x50, 0x92, 0xe3, 0x26
168     };
169 
170     return TEST_ptr(md)
171         && TEST_true(EVP_MD_is_a(md, "SHA256"))
172         && TEST_true(calculate_digest(md, testmsg, sizeof(testmsg), exptd))
173         && TEST_int_eq(EVP_MD_get_size(md), SHA256_DIGEST_LENGTH)
174         && TEST_int_eq(EVP_MD_get_block_size(md), SHA256_CBLOCK);
175 }
176 
test_implicit_EVP_MD_fetch(void)177 static int test_implicit_EVP_MD_fetch(void)
178 {
179     OSSL_LIB_CTX *ctx = NULL;
180     OSSL_PROVIDER *prov[2] = {NULL, NULL};
181     int ret = 0;
182 
183     ret = (use_default_ctx == 0 || load_providers(&ctx, prov))
184         && test_md(EVP_sha256());
185 
186     unload_providers(&ctx, prov);
187     return ret;
188 }
189 
test_explicit_EVP_MD_fetch(const char * id)190 static int test_explicit_EVP_MD_fetch(const char *id)
191 {
192     OSSL_LIB_CTX *ctx = NULL;
193     EVP_MD *md = NULL;
194     OSSL_PROVIDER *prov[2] = {NULL, NULL};
195     int ret = 0;
196 
197     if (use_default_ctx == 0 && !load_providers(&ctx, prov))
198         goto err;
199 
200     md = EVP_MD_fetch(ctx, id, fetch_property);
201     if (expected_fetch_result != 0) {
202         if (!test_md(md))
203             goto err;
204 
205         /* Also test EVP_MD_up_ref() while we're doing this */
206         if (!TEST_true(EVP_MD_up_ref(md)))
207             goto err;
208         /* Ref count should now be 2. Release first one here */
209         EVP_MD_free(md);
210     } else {
211         if (!TEST_ptr_null(md))
212             goto err;
213     }
214     ret = 1;
215 
216  err:
217     EVP_MD_free(md);
218     unload_providers(&ctx, prov);
219     return ret;
220 }
221 
test_explicit_EVP_MD_fetch_by_name(void)222 static int test_explicit_EVP_MD_fetch_by_name(void)
223 {
224     return test_explicit_EVP_MD_fetch("SHA256");
225 }
226 
227 /*
228  * idx 0: Allow names from OBJ_obj2txt()
229  * idx 1: Force an OID in text form from OBJ_obj2txt()
230  */
test_explicit_EVP_MD_fetch_by_X509_ALGOR(int idx)231 static int test_explicit_EVP_MD_fetch_by_X509_ALGOR(int idx)
232 {
233     int ret = 0;
234     X509_ALGOR *algor = make_algor(NID_sha256);
235     const ASN1_OBJECT *obj;
236     char id[OSSL_MAX_NAME_SIZE] = { 0 };
237 
238     if (algor == NULL)
239         return 0;
240 
241     X509_ALGOR_get0(&obj, NULL, NULL, algor);
242     switch (idx) {
243     case 0:
244         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 0), 0))
245             goto end;
246         break;
247     case 1:
248         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 1), 0))
249             goto end;
250         break;
251     }
252 
253     ret = test_explicit_EVP_MD_fetch(id);
254  end:
255     X509_ALGOR_free(algor);
256     return ret;
257 }
258 
259 /*
260  * Test EVP_CIPHER_fetch()
261  */
encrypt_decrypt(const EVP_CIPHER * cipher,const unsigned char * msg,size_t len)262 static int encrypt_decrypt(const EVP_CIPHER *cipher, const unsigned char *msg,
263                            size_t len)
264 {
265     int ret = 0, ctlen, ptlen;
266     EVP_CIPHER_CTX *ctx = NULL;
267     unsigned char key[128 / 8];
268     unsigned char ct[64], pt[64];
269 
270     memset(key, 0, sizeof(key));
271     if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
272             || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, 1))
273             || !TEST_true(EVP_CipherUpdate(ctx, ct, &ctlen, msg, len))
274             || !TEST_true(EVP_CipherFinal_ex(ctx, ct, &ctlen))
275             || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, 0))
276             || !TEST_true(EVP_CipherUpdate(ctx, pt, &ptlen, ct, ctlen))
277             || !TEST_true(EVP_CipherFinal_ex(ctx, pt, &ptlen))
278             || !TEST_mem_eq(pt, ptlen, msg, len))
279         goto err;
280 
281     ret = 1;
282 err:
283     EVP_CIPHER_CTX_free(ctx);
284     return ret;
285 }
286 
test_cipher(const EVP_CIPHER * cipher)287 static int test_cipher(const EVP_CIPHER *cipher)
288 {
289     const unsigned char testmsg[] = "Hello world";
290 
291     return TEST_ptr(cipher)
292         && TEST_true(encrypt_decrypt(cipher, testmsg, sizeof(testmsg)));
293 }
294 
test_implicit_EVP_CIPHER_fetch(void)295 static int test_implicit_EVP_CIPHER_fetch(void)
296 {
297     OSSL_LIB_CTX *ctx = NULL;
298     OSSL_PROVIDER *prov[2] = {NULL, NULL};
299     int ret = 0;
300 
301     ret = (use_default_ctx == 0 || load_providers(&ctx, prov))
302         && test_cipher(EVP_aes_128_cbc());
303 
304     unload_providers(&ctx, prov);
305     return ret;
306 }
307 
test_explicit_EVP_CIPHER_fetch(const char * id)308 static int test_explicit_EVP_CIPHER_fetch(const char *id)
309 {
310     OSSL_LIB_CTX *ctx = NULL;
311     EVP_CIPHER *cipher = NULL;
312     OSSL_PROVIDER *prov[2] = {NULL, NULL};
313     int ret = 0;
314 
315     if (use_default_ctx == 0 && !load_providers(&ctx, prov))
316         goto err;
317 
318     cipher = EVP_CIPHER_fetch(ctx, id, fetch_property);
319     if (expected_fetch_result != 0) {
320         if (!test_cipher(cipher))
321             goto err;
322 
323         if (!TEST_true(EVP_CIPHER_up_ref(cipher)))
324             goto err;
325         /* Ref count should now be 2. Release first one here */
326         EVP_CIPHER_free(cipher);
327     } else {
328         if (!TEST_ptr_null(cipher))
329             goto err;
330     }
331     ret = 1;
332 err:
333     EVP_CIPHER_free(cipher);
334     unload_providers(&ctx, prov);
335     return ret;
336 }
337 
test_explicit_EVP_CIPHER_fetch_by_name(void)338 static int test_explicit_EVP_CIPHER_fetch_by_name(void)
339 {
340     return test_explicit_EVP_CIPHER_fetch("AES-128-CBC");
341 }
342 
343 /*
344  * idx 0: Allow names from OBJ_obj2txt()
345  * idx 1: Force an OID in text form from OBJ_obj2txt()
346  */
test_explicit_EVP_CIPHER_fetch_by_X509_ALGOR(int idx)347 static int test_explicit_EVP_CIPHER_fetch_by_X509_ALGOR(int idx)
348 {
349     int ret = 0;
350     X509_ALGOR *algor = make_algor(NID_aes_128_cbc);
351     const ASN1_OBJECT *obj;
352     char id[OSSL_MAX_NAME_SIZE] = { 0 };
353 
354     if (algor == NULL)
355         return 0;
356 
357     X509_ALGOR_get0(&obj, NULL, NULL, algor);
358     switch (idx) {
359     case 0:
360         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 0), 0))
361             goto end;
362         break;
363     case 1:
364         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 1), 0))
365             goto end;
366         break;
367     }
368 
369     ret = test_explicit_EVP_CIPHER_fetch(id);
370  end:
371     X509_ALGOR_free(algor);
372     return ret;
373 }
374 
setup_tests(void)375 int setup_tests(void)
376 {
377     OPTION_CHOICE o;
378 
379     while ((o = opt_next()) != OPT_EOF) {
380         switch (o) {
381         case OPT_CONFIG_FILE:
382             config_file = opt_arg();
383             break;
384         case OPT_ALG_FETCH_TYPE:
385             alg = opt_arg();
386             break;
387         case OPT_FETCH_PROPERTY:
388             fetch_property = opt_arg();
389             break;
390         case OPT_FETCH_FAILURE:
391             expected_fetch_result = 0;
392             break;
393         case OPT_USE_DEFAULTCTX:
394             use_default_ctx = 1;
395             break;
396         case OPT_TEST_CASES:
397            break;
398         default:
399         case OPT_ERR:
400             return 0;
401         }
402     }
403     ADD_TEST(test_legacy_provider_unloaded);
404     if (strcmp(alg, "digest") == 0) {
405         ADD_TEST(test_implicit_EVP_MD_fetch);
406         ADD_TEST(test_explicit_EVP_MD_fetch_by_name);
407         ADD_ALL_TESTS_NOSUBTEST(test_explicit_EVP_MD_fetch_by_X509_ALGOR, 2);
408     } else {
409         ADD_TEST(test_implicit_EVP_CIPHER_fetch);
410         ADD_TEST(test_explicit_EVP_CIPHER_fetch_by_name);
411         ADD_ALL_TESTS_NOSUBTEST(test_explicit_EVP_CIPHER_fetch_by_X509_ALGOR, 2);
412     }
413     return 1;
414 }
415