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
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
make_algor(int nid)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 */
test_md(const EVP_MD * md)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
test_implicit_EVP_MD_fetch(void)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
test_explicit_EVP_MD_fetch(const char * id)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
test_explicit_EVP_MD_fetch_by_name(void)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 */
test_explicit_EVP_MD_fetch_by_X509_ALGOR(int idx)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 */
encrypt_decrypt(const EVP_CIPHER * cipher,const unsigned char * msg,size_t len)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
test_cipher(const EVP_CIPHER * cipher)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
test_implicit_EVP_CIPHER_fetch(void)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
test_explicit_EVP_CIPHER_fetch(const char * id)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
test_explicit_EVP_CIPHER_fetch_by_name(void)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 */
test_explicit_EVP_CIPHER_fetch_by_X509_ALGOR(int idx)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
setup_tests(void)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