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 sprintf(buf, "id%d", loop); 151 eid[loop] = OPENSSL_strdup(buf); 152 sprintf(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[] = 226 "\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