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