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