Fix PEM certificate loading that sometimes fails
[openssl.git] / test / evp_fetch_prov_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 /*
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 "testutil.h"
22
23 static char *config_file = NULL;
24 static char *alg = "digest";
25 static int use_default_ctx = 0;
26 static char *fetch_property = NULL;
27 static int expected_fetch_result = 1;
28
29 typedef enum OPTION_choice {
30     OPT_ERR = -1,
31     OPT_EOF = 0,
32     OPT_ALG_FETCH_TYPE,
33     OPT_FETCH_PROPERTY,
34     OPT_FETCH_FAILURE,
35     OPT_USE_DEFAULTCTX,
36     OPT_CONFIG_FILE,
37     OPT_TEST_ENUM
38 } OPTION_CHOICE;
39
40 const OPTIONS *test_get_options(void)
41 {
42     static const OPTIONS test_options[] = {
43         OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("[provname...]\n"),
44         { "config", OPT_CONFIG_FILE, '<', "The configuration file to use for the libctx" },
45         { "type", OPT_ALG_FETCH_TYPE, 's', "The fetch type to test" },
46         { "property", OPT_FETCH_PROPERTY, 's', "The fetch property e.g. provider=fips" },
47         { "fetchfail", OPT_FETCH_FAILURE, '-', "fetch is expected to fail" },
48         { "defaultctx", OPT_USE_DEFAULTCTX, '-',
49           "Use the default context if this is set" },
50         { OPT_HELP_STR, 1, '-',
51           "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_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(OPENSSL_CTX **libctx, OSSL_PROVIDER *prov[])
80 {
81     OPENSSL_CTX *ctx = NULL;
82     int ret = 0;
83     size_t i;
84
85     ctx = OPENSSL_CTX_new();
86     if (!TEST_ptr(ctx))
87         goto err;
88
89     if (!TEST_true(OPENSSL_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         OPENSSL_CTX_free(ctx);
106     return ret;
107 }
108
109 /*
110  * Test EVP_MD_fetch()
111  */
112 static int test_EVP_MD_fetch(void)
113 {
114     OPENSSL_CTX *ctx = NULL;
115     EVP_MD *md = NULL;
116     OSSL_PROVIDER *prov[2] = {NULL, NULL};
117     int ret = 0;
118     const char testmsg[] = "Hello world";
119     const unsigned char exptd[] = {
120       0x27, 0x51, 0x8b, 0xa9, 0x68, 0x30, 0x11, 0xf6, 0xb3, 0x96, 0x07, 0x2c,
121       0x05, 0xf6, 0x65, 0x6d, 0x04, 0xf5, 0xfb, 0xc3, 0x78, 0x7c, 0xf9, 0x24,
122       0x90, 0xec, 0x60, 0x6e, 0x50, 0x92, 0xe3, 0x26
123     };
124
125     if (use_default_ctx == 0 && !load_providers(&ctx, prov))
126         goto err;
127
128     /* Implicit fetching of the MD should produce the expected result */
129     if (!TEST_true(calculate_digest(EVP_sha256(), testmsg, sizeof(testmsg),
130                                     exptd))
131             || !TEST_int_eq(EVP_MD_size(EVP_sha256()), SHA256_DIGEST_LENGTH)
132             || !TEST_int_eq(EVP_MD_block_size(EVP_sha256()), SHA256_CBLOCK))
133         goto err;
134
135     /* Fetch the digest from a provider using properties. */
136     md = EVP_MD_fetch(ctx, "SHA256", fetch_property);
137     if (expected_fetch_result != 0) {
138         if (!TEST_ptr(md)
139             || !TEST_int_eq(EVP_MD_nid(md), NID_sha256)
140             || !TEST_true(calculate_digest(md, testmsg, sizeof(testmsg), exptd))
141             || !TEST_int_eq(EVP_MD_size(md), SHA256_DIGEST_LENGTH)
142             || !TEST_int_eq(EVP_MD_block_size(md), SHA256_CBLOCK))
143         goto err;
144
145         /* Also test EVP_MD_up_ref() while we're doing this */
146         if (!TEST_true(EVP_MD_up_ref(md)))
147             goto err;
148         /* Ref count should now be 2. Release first one here */
149         EVP_MD_meth_free(md);
150     } else {
151         if (!TEST_ptr_null(md))
152             goto err;
153     }
154     ret = 1;
155
156 err:
157     EVP_MD_meth_free(md);
158     OSSL_PROVIDER_unload(prov[0]);
159     OSSL_PROVIDER_unload(prov[1]);
160     /* Not normally needed, but we would like to test that
161      * OPENSSL_thread_stop_ex() behaves as expected.
162      */
163     if (ctx != NULL) {
164         OPENSSL_thread_stop_ex(ctx);
165         OPENSSL_CTX_free(ctx);
166     }
167     return ret;
168 }
169
170 static int encrypt_decrypt(const EVP_CIPHER *cipher, const unsigned char *msg,
171                            size_t len)
172 {
173     int ret = 0, ctlen, ptlen;
174     EVP_CIPHER_CTX *ctx = NULL;
175     unsigned char key[128 / 8];
176     unsigned char ct[64], pt[64];
177
178     memset(key, 0, sizeof(key));
179     if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
180             || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, 1))
181             || !TEST_true(EVP_CipherUpdate(ctx, ct, &ctlen, msg, len))
182             || !TEST_true(EVP_CipherFinal_ex(ctx, ct, &ctlen))
183             || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, 0))
184             || !TEST_true(EVP_CipherUpdate(ctx, pt, &ptlen, ct, ctlen))
185             || !TEST_true(EVP_CipherFinal_ex(ctx, pt, &ptlen))
186             || !TEST_mem_eq(pt, ptlen, msg, len))
187         goto err;
188
189     ret = 1;
190 err:
191     EVP_CIPHER_CTX_free(ctx);
192     return ret;
193 }
194
195 /*
196  * Test EVP_CIPHER_fetch()
197  */
198 static int test_EVP_CIPHER_fetch(void)
199 {
200     OPENSSL_CTX *ctx = NULL;
201     EVP_CIPHER *cipher = NULL;
202     OSSL_PROVIDER *prov[2] = {NULL, NULL};
203     int ret = 0;
204     const unsigned char testmsg[] = "Hello world";
205
206     if (use_default_ctx == 0 && !load_providers(&ctx, prov))
207         goto err;
208
209     /* Implicit fetching of the cipher should produce the expected result */
210     if (!TEST_true(encrypt_decrypt(EVP_aes_128_cbc(), testmsg, sizeof(testmsg))))
211         goto err;
212
213     /* Fetch the cipher from a provider using properties. */
214     cipher = EVP_CIPHER_fetch(ctx, "AES-128-CBC", fetch_property);
215     if (expected_fetch_result != 0) {
216         if (!TEST_ptr(cipher)
217             || !TEST_true(encrypt_decrypt(cipher, testmsg, sizeof(testmsg)))) {
218             if (!TEST_true(EVP_CIPHER_up_ref(cipher)))
219                 goto err;
220             /* Ref count should now be 2. Release first one here */
221             EVP_CIPHER_meth_free(cipher);
222         }
223     } else {
224         if (!TEST_ptr_null(cipher))
225             goto err;
226     }
227     ret = 1;
228 err:
229     EVP_CIPHER_meth_free(cipher);
230     OSSL_PROVIDER_unload(prov[0]);
231     OSSL_PROVIDER_unload(prov[1]);
232     OPENSSL_CTX_free(ctx);
233     return ret;
234 }
235
236 int setup_tests(void)
237 {
238     OPTION_CHOICE o;
239
240     while ((o = opt_next()) != OPT_EOF) {
241         switch (o) {
242         case OPT_CONFIG_FILE:
243             config_file = opt_arg();
244             break;
245         case OPT_ALG_FETCH_TYPE:
246             alg = opt_arg();
247             break;
248         case OPT_FETCH_PROPERTY:
249             fetch_property = opt_arg();
250             break;
251         case OPT_FETCH_FAILURE:
252             expected_fetch_result = 0;
253             break;
254         case OPT_USE_DEFAULTCTX:
255             use_default_ctx = 1;
256             break;
257         case OPT_TEST_CASES:
258            break;
259         default:
260         case OPT_ERR:
261             return 0;
262         }
263     }
264     if (strcmp(alg, "digest") == 0)
265         ADD_TEST(test_EVP_MD_fetch);
266     else
267         ADD_TEST(test_EVP_CIPHER_fetch);
268     return 1;
269 }