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