1 /* 2 * Copyright 2000-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 /* We need to use some deprecated APIs */ 11 #define OPENSSL_SUPPRESS_DEPRECATED 12 13 #include <stdio.h> 14 #include <string.h> 15 #include <stdlib.h> 16 #include <openssl/e_os2.h> 17 18 #include "testutil.h" 19 20 #ifndef OPENSSL_NO_ENGINE 21 #include <openssl/buffer.h> 22 #include <openssl/crypto.h> 23 #include <openssl/engine.h> 24 #include <openssl/rsa.h> 25 #include <openssl/err.h> 26 #include <openssl/x509.h> 27 #include <openssl/pem.h> 28 29 static void display_engine_list(void) 30 { 31 ENGINE *h; 32 int loop; 33 34 loop = 0; 35 for (h = ENGINE_get_first(); h != NULL; h = ENGINE_get_next(h)) { 36 TEST_info("#%d: id = \"%s\", name = \"%s\"", 37 loop++, ENGINE_get_id(h), ENGINE_get_name(h)); 38 } 39 40 /* 41 * ENGINE_get_first() increases the struct_ref counter, so we must call 42 * ENGINE_free() to decrease it again 43 */ 44 ENGINE_free(h); 45 } 46 47 #define NUMTOADD 512 48 49 static int test_engines(void) 50 { 51 ENGINE *block[NUMTOADD]; 52 char *eid[NUMTOADD]; 53 char *ename[NUMTOADD]; 54 char buf[256]; 55 ENGINE *ptr; 56 int loop; 57 int to_return = 0; 58 ENGINE *new_h1 = NULL; 59 ENGINE *new_h2 = NULL; 60 ENGINE *new_h3 = NULL; 61 ENGINE *new_h4 = NULL; 62 63 memset(block, 0, sizeof(block)); 64 if (!TEST_ptr(new_h1 = ENGINE_new()) 65 || !TEST_true(ENGINE_set_id(new_h1, "test_id0")) 66 || !TEST_true(ENGINE_set_name(new_h1, "First test item")) 67 || !TEST_ptr(new_h2 = ENGINE_new()) 68 || !TEST_true(ENGINE_set_id(new_h2, "test_id1")) 69 || !TEST_true(ENGINE_set_name(new_h2, "Second test item")) 70 || !TEST_ptr(new_h3 = ENGINE_new()) 71 || !TEST_true(ENGINE_set_id(new_h3, "test_id2")) 72 || !TEST_true(ENGINE_set_name(new_h3, "Third test item")) 73 || !TEST_ptr(new_h4 = ENGINE_new()) 74 || !TEST_true(ENGINE_set_id(new_h4, "test_id3")) 75 || !TEST_true(ENGINE_set_name(new_h4, "Fourth test item"))) 76 goto end; 77 TEST_info("Engines:"); 78 display_engine_list(); 79 80 if (!TEST_true(ENGINE_add(new_h1))) 81 goto end; 82 TEST_info("Engines:"); 83 display_engine_list(); 84 85 ptr = ENGINE_get_first(); 86 if (!TEST_true(ENGINE_remove(ptr))) 87 goto end; 88 ENGINE_free(ptr); 89 TEST_info("Engines:"); 90 display_engine_list(); 91 92 if (!TEST_true(ENGINE_add(new_h3)) 93 || !TEST_true(ENGINE_add(new_h2))) 94 goto end; 95 TEST_info("Engines:"); 96 display_engine_list(); 97 98 if (!TEST_true(ENGINE_remove(new_h2))) 99 goto end; 100 TEST_info("Engines:"); 101 display_engine_list(); 102 103 if (!TEST_true(ENGINE_add(new_h4))) 104 goto end; 105 TEST_info("Engines:"); 106 display_engine_list(); 107 108 /* Should fail. */ 109 if (!TEST_false(ENGINE_add(new_h3))) 110 goto end; 111 ERR_clear_error(); 112 113 /* Should fail. */ 114 if (!TEST_false(ENGINE_remove(new_h2))) 115 goto end; 116 ERR_clear_error(); 117 118 if (!TEST_true(ENGINE_remove(new_h3))) 119 goto end; 120 TEST_info("Engines:"); 121 display_engine_list(); 122 123 if (!TEST_true(ENGINE_remove(new_h4))) 124 goto end; 125 TEST_info("Engines:"); 126 display_engine_list(); 127 128 /* 129 * At this point, we should have an empty list, unless some hardware 130 * support engine got added. However, since we don't allow the config 131 * file to be loaded and don't otherwise load any built in engines, 132 * that is unlikely. Still, we check, if for nothing else, then to 133 * notify that something is a little off (and might mean that |new_h1| 134 * wasn't unloaded when it should have) 135 */ 136 if ((ptr = ENGINE_get_first()) != NULL) { 137 if (!ENGINE_remove(ptr)) 138 TEST_info("Remove failed - probably no hardware support present"); 139 } 140 ENGINE_free(ptr); 141 TEST_info("Engines:"); 142 display_engine_list(); 143 144 if (!TEST_true(ENGINE_add(new_h1)) 145 || !TEST_true(ENGINE_remove(new_h1))) 146 goto end; 147 148 TEST_info("About to beef up the engine-type list"); 149 for (loop = 0; loop < NUMTOADD; loop++) { 150 BIO_snprintf(buf, sizeof(buf), "id%d", loop); 151 eid[loop] = OPENSSL_strdup(buf); 152 BIO_snprintf(buf, sizeof(buf), "Fake engine type %d", loop); 153 ename[loop] = OPENSSL_strdup(buf); 154 if (!TEST_ptr(block[loop] = ENGINE_new()) 155 || !TEST_true(ENGINE_set_id(block[loop], eid[loop])) 156 || !TEST_true(ENGINE_set_name(block[loop], ename[loop]))) 157 goto end; 158 } 159 for (loop = 0; loop < NUMTOADD; loop++) { 160 if (!TEST_true(ENGINE_add(block[loop]))) { 161 test_note("Adding stopped at %d, (%s,%s)", 162 loop, ENGINE_get_id(block[loop]), 163 ENGINE_get_name(block[loop])); 164 goto cleanup_loop; 165 } 166 } 167 cleanup_loop: 168 TEST_info("About to empty the engine-type list"); 169 while ((ptr = ENGINE_get_first()) != NULL) { 170 if (!TEST_true(ENGINE_remove(ptr))) 171 goto end; 172 ENGINE_free(ptr); 173 } 174 for (loop = 0; loop < NUMTOADD; loop++) { 175 OPENSSL_free(eid[loop]); 176 OPENSSL_free(ename[loop]); 177 } 178 to_return = 1; 179 180 end: 181 ENGINE_free(new_h1); 182 ENGINE_free(new_h2); 183 ENGINE_free(new_h3); 184 ENGINE_free(new_h4); 185 for (loop = 0; loop < NUMTOADD; loop++) 186 ENGINE_free(block[loop]); 187 return to_return; 188 } 189 190 /* Test EVP_PKEY method */ 191 static EVP_PKEY_METHOD *test_rsa = NULL; 192 193 static int called_encrypt = 0; 194 195 /* Test function to check operation has been redirected */ 196 static int test_encrypt(EVP_PKEY_CTX *ctx, unsigned char *sig, 197 size_t *siglen, const unsigned char *tbs, size_t tbslen) 198 { 199 called_encrypt = 1; 200 return 1; 201 } 202 203 static int test_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, 204 const int **pnids, int nid) 205 { 206 static const int rnid = EVP_PKEY_RSA; 207 if (pmeth == NULL) { 208 *pnids = &rnid; 209 return 1; 210 } 211 212 if (nid == EVP_PKEY_RSA) { 213 *pmeth = test_rsa; 214 return 1; 215 } 216 217 *pmeth = NULL; 218 return 0; 219 } 220 221 /* Return a test EVP_PKEY value */ 222 223 static EVP_PKEY *get_test_pkey(void) 224 { 225 static unsigned char n[] = "\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F" 226 "\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5" 227 "\xAD\xB3\x00\xA0\x28\x5E\x53\x01\x93\x0E\x0C\x70\xFB\x68\x76\x93" 228 "\x9C\xE6\x16\xCE\x62\x4A\x11\xE0\x08\x6D\x34\x1E\xBC\xAC\xA0\xA1" 229 "\xF5"; 230 static unsigned char e[] = "\x11"; 231 232 RSA *rsa = RSA_new(); 233 EVP_PKEY *pk = EVP_PKEY_new(); 234 235 if (rsa == NULL || pk == NULL || !EVP_PKEY_assign_RSA(pk, rsa)) { 236 RSA_free(rsa); 237 EVP_PKEY_free(pk); 238 return NULL; 239 } 240 241 if (!RSA_set0_key(rsa, BN_bin2bn(n, sizeof(n) - 1, NULL), 242 BN_bin2bn(e, sizeof(e) - 1, NULL), NULL)) { 243 EVP_PKEY_free(pk); 244 return NULL; 245 } 246 247 return pk; 248 } 249 250 static int test_redirect(void) 251 { 252 const unsigned char pt[] = "Hello World\n"; 253 unsigned char *tmp = NULL; 254 size_t len; 255 EVP_PKEY_CTX *ctx = NULL; 256 ENGINE *e = NULL; 257 EVP_PKEY *pkey = NULL; 258 259 int to_return = 0; 260 261 if (!TEST_ptr(pkey = get_test_pkey())) 262 goto err; 263 264 len = EVP_PKEY_get_size(pkey); 265 if (!TEST_ptr(tmp = OPENSSL_malloc(len))) 266 goto err; 267 268 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL))) 269 goto err; 270 TEST_info("EVP_PKEY_encrypt test: no redirection"); 271 /* Encrypt some data: should succeed but not be redirected */ 272 if (!TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0) 273 || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0) 274 || !TEST_false(called_encrypt)) 275 goto err; 276 EVP_PKEY_CTX_free(ctx); 277 ctx = NULL; 278 279 /* Create a test ENGINE */ 280 if (!TEST_ptr(e = ENGINE_new()) 281 || !TEST_true(ENGINE_set_id(e, "Test redirect engine")) 282 || !TEST_true(ENGINE_set_name(e, "Test redirect engine"))) 283 goto err; 284 285 /* 286 * Try to create a context for this engine and test key. 287 * Try setting test key engine. Both should fail because the 288 * engine has no public key methods. 289 */ 290 if (!TEST_ptr_null(ctx = EVP_PKEY_CTX_new(pkey, e)) 291 || !TEST_int_le(EVP_PKEY_set1_engine(pkey, e), 0)) 292 goto err; 293 294 /* Setup an empty test EVP_PKEY_METHOD and set callback to return it */ 295 if (!TEST_ptr(test_rsa = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0))) 296 goto err; 297 ENGINE_set_pkey_meths(e, test_pkey_meths); 298 299 /* Getting a context for test ENGINE should now succeed */ 300 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, e))) 301 goto err; 302 /* Encrypt should fail because operation is not supported */ 303 if (!TEST_int_le(EVP_PKEY_encrypt_init(ctx), 0)) 304 goto err; 305 EVP_PKEY_CTX_free(ctx); 306 ctx = NULL; 307 308 /* Add test encrypt operation to method */ 309 EVP_PKEY_meth_set_encrypt(test_rsa, 0, test_encrypt); 310 311 TEST_info("EVP_PKEY_encrypt test: redirection via EVP_PKEY_CTX_new()"); 312 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, e))) 313 goto err; 314 /* Encrypt some data: should succeed and be redirected */ 315 if (!TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0) 316 || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0) 317 || !TEST_true(called_encrypt)) 318 goto err; 319 320 EVP_PKEY_CTX_free(ctx); 321 ctx = NULL; 322 called_encrypt = 0; 323 324 /* Create context with default engine: should not be redirected */ 325 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL)) 326 || !TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0) 327 || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0) 328 || !TEST_false(called_encrypt)) 329 goto err; 330 331 EVP_PKEY_CTX_free(ctx); 332 ctx = NULL; 333 334 /* Set engine explicitly for test key */ 335 if (!TEST_true(EVP_PKEY_set1_engine(pkey, e))) 336 goto err; 337 338 TEST_info("EVP_PKEY_encrypt test: redirection via EVP_PKEY_set1_engine()"); 339 340 /* Create context with default engine: should be redirected now */ 341 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL)) 342 || !TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0) 343 || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0) 344 || !TEST_true(called_encrypt)) 345 goto err; 346 347 to_return = 1; 348 349 err: 350 EVP_PKEY_CTX_free(ctx); 351 EVP_PKEY_free(pkey); 352 ENGINE_free(e); 353 OPENSSL_free(tmp); 354 return to_return; 355 } 356 357 static int test_x509_dup_w_engine(void) 358 { 359 ENGINE *e = NULL; 360 X509 *cert = NULL, *dupcert = NULL; 361 X509_PUBKEY *pubkey, *duppubkey = NULL; 362 int ret = 0; 363 BIO *b = NULL; 364 RSA_METHOD *rsameth = NULL; 365 366 if (!TEST_ptr(b = BIO_new_file(test_get_argument(0), "r")) 367 || !TEST_ptr(cert = PEM_read_bio_X509(b, NULL, NULL, NULL))) 368 goto err; 369 370 /* Dup without an engine */ 371 if (!TEST_ptr(dupcert = X509_dup(cert))) 372 goto err; 373 X509_free(dupcert); 374 dupcert = NULL; 375 376 if (!TEST_ptr(pubkey = X509_get_X509_PUBKEY(cert)) 377 || !TEST_ptr(duppubkey = X509_PUBKEY_dup(pubkey)) 378 || !TEST_ptr_ne(duppubkey, pubkey) 379 || !TEST_ptr_ne(X509_PUBKEY_get0(duppubkey), X509_PUBKEY_get0(pubkey))) 380 goto err; 381 382 X509_PUBKEY_free(duppubkey); 383 duppubkey = NULL; 384 385 X509_free(cert); 386 cert = NULL; 387 388 /* Create a test ENGINE */ 389 if (!TEST_ptr(e = ENGINE_new()) 390 || !TEST_true(ENGINE_set_id(e, "Test dummy engine")) 391 || !TEST_true(ENGINE_set_name(e, "Test dummy engine"))) 392 goto err; 393 394 if (!TEST_ptr(rsameth = RSA_meth_dup(RSA_get_default_method()))) 395 goto err; 396 397 ENGINE_set_RSA(e, rsameth); 398 399 if (!TEST_true(ENGINE_set_default_RSA(e))) 400 goto err; 401 402 if (!TEST_int_ge(BIO_seek(b, 0), 0) 403 || !TEST_ptr(cert = PEM_read_bio_X509(b, NULL, NULL, NULL))) 404 goto err; 405 406 /* Dup with an engine set on the key */ 407 if (!TEST_ptr(dupcert = X509_dup(cert))) 408 goto err; 409 410 if (!TEST_ptr(pubkey = X509_get_X509_PUBKEY(cert)) 411 || !TEST_ptr(duppubkey = X509_PUBKEY_dup(pubkey)) 412 || !TEST_ptr_ne(duppubkey, pubkey) 413 || !TEST_ptr_ne(X509_PUBKEY_get0(duppubkey), X509_PUBKEY_get0(pubkey))) 414 goto err; 415 416 ret = 1; 417 418 err: 419 X509_free(cert); 420 X509_free(dupcert); 421 X509_PUBKEY_free(duppubkey); 422 if (e != NULL) { 423 ENGINE_unregister_RSA(e); 424 ENGINE_free(e); 425 } 426 RSA_meth_free(rsameth); 427 BIO_free(b); 428 return ret; 429 } 430 #endif 431 432 int global_init(void) 433 { 434 /* 435 * If the config file gets loaded, the dynamic engine will be loaded, 436 * and that interferes with our test above. 437 */ 438 return OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL); 439 } 440 441 OPT_TEST_DECLARE_USAGE("certfile\n") 442 443 int setup_tests(void) 444 { 445 #ifdef OPENSSL_NO_ENGINE 446 TEST_note("No ENGINE support"); 447 #else 448 int n; 449 450 if (!test_skip_common_options()) { 451 TEST_error("Error parsing test options\n"); 452 return 0; 453 } 454 455 n = test_get_argument_count(); 456 if (n == 0) 457 return 0; 458 459 ADD_TEST(test_engines); 460 ADD_TEST(test_redirect); 461 ADD_TEST(test_x509_dup_w_engine); 462 #endif 463 return 1; 464 } 465