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 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 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 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 */ 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 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 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 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 */ 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 */ 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 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 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 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 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 */ 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 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