enginetest.c revision 1.3
1/* 2 * Copyright 2000-2017 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 * Depending on whether there's any hardware support compiled in, this 124 * remove may be destined to fail. 125 */ 126 if ((ptr = ENGINE_get_first()) != NULL) { 127 if (!ENGINE_remove(ptr)) 128 TEST_info("Remove failed - probably no hardware support present"); 129 } 130 ENGINE_free(ptr); 131 TEST_info("Engines:"); 132 display_engine_list(); 133 134 if (!TEST_true(ENGINE_add(new_h1)) 135 || !TEST_true(ENGINE_remove(new_h1))) 136 goto end; 137 138 TEST_info("About to beef up the engine-type list"); 139 for (loop = 0; loop < NUMTOADD; loop++) { 140 sprintf(buf, "id%d", loop); 141 id = OPENSSL_strdup(buf); 142 sprintf(buf, "Fake engine type %d", loop); 143 name = OPENSSL_strdup(buf); 144 if (!TEST_ptr(block[loop] = ENGINE_new()) 145 || !TEST_true(ENGINE_set_id(block[loop], id)) 146 || !TEST_true(ENGINE_set_name(block[loop], name))) 147 goto end; 148 } 149 for (loop = 0; loop < NUMTOADD; loop++) { 150 if (!TEST_true(ENGINE_add(block[loop]))) { 151 test_note("Adding stopped at %d, (%s,%s)", 152 loop, ENGINE_get_id(block[loop]), 153 ENGINE_get_name(block[loop])); 154 goto cleanup_loop; 155 } 156 } 157 cleanup_loop: 158 TEST_info("About to empty the engine-type list"); 159 while ((ptr = ENGINE_get_first()) != NULL) { 160 if (!TEST_true(ENGINE_remove(ptr))) 161 goto end; 162 ENGINE_free(ptr); 163 } 164 for (loop = 0; loop < NUMTOADD; loop++) { 165 OPENSSL_free((void *)(intptr_t)ENGINE_get_id(block[loop])); 166 OPENSSL_free((void *)(intptr_t)ENGINE_get_name(block[loop])); 167 } 168 to_return = 1; 169 170 end: 171 ENGINE_free(new_h1); 172 ENGINE_free(new_h2); 173 ENGINE_free(new_h3); 174 ENGINE_free(new_h4); 175 for (loop = 0; loop < NUMTOADD; loop++) 176 ENGINE_free(block[loop]); 177 return to_return; 178} 179 180/* Test EVP_PKEY method */ 181static EVP_PKEY_METHOD *test_rsa = NULL; 182 183static int called_encrypt = 0; 184 185/* Test function to check operation has been redirected */ 186static int test_encrypt(EVP_PKEY_CTX *ctx, unsigned char *sig, 187 size_t *siglen, const unsigned char *tbs, size_t tbslen) 188{ 189 called_encrypt = 1; 190 return 1; 191} 192 193static int test_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, 194 const int **pnids, int nid) 195{ 196 static const int rnid = EVP_PKEY_RSA; 197 if (pmeth == NULL) { 198 *pnids = &rnid; 199 return 1; 200 } 201 202 if (nid == EVP_PKEY_RSA) { 203 *pmeth = test_rsa; 204 return 1; 205 } 206 207 *pmeth = NULL; 208 return 0; 209} 210 211/* Return a test EVP_PKEY value */ 212 213static EVP_PKEY *get_test_pkey(void) 214{ 215 static unsigned char n[] = 216 "\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F" 217 "\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5" 218 "\xAD\xB3\x00\xA0\x28\x5E\x53\x01\x93\x0E\x0C\x70\xFB\x68\x76\x93" 219 "\x9C\xE6\x16\xCE\x62\x4A\x11\xE0\x08\x6D\x34\x1E\xBC\xAC\xA0\xA1" 220 "\xF5"; 221 static unsigned char e[] = "\x11"; 222 223 RSA *rsa = RSA_new(); 224 EVP_PKEY *pk = EVP_PKEY_new(); 225 226 if (rsa == NULL || pk == NULL || !EVP_PKEY_assign_RSA(pk, rsa)) { 227 RSA_free(rsa); 228 EVP_PKEY_free(pk); 229 return NULL; 230 } 231 232 if (!RSA_set0_key(rsa, BN_bin2bn(n, sizeof(n)-1, NULL), 233 BN_bin2bn(e, sizeof(e)-1, NULL), NULL)) { 234 EVP_PKEY_free(pk); 235 return NULL; 236 } 237 238 return pk; 239} 240 241static int test_redirect(void) 242{ 243 const unsigned char pt[] = "Hello World\n"; 244 unsigned char *tmp = NULL; 245 size_t len; 246 EVP_PKEY_CTX *ctx = NULL; 247 ENGINE *e = NULL; 248 EVP_PKEY *pkey = NULL; 249 250 int to_return = 0; 251 252 if (!TEST_ptr(pkey = get_test_pkey())) 253 goto err; 254 255 len = EVP_PKEY_size(pkey); 256 if (!TEST_ptr(tmp = OPENSSL_malloc(len))) 257 goto err; 258 259 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL))) 260 goto err; 261 TEST_info("EVP_PKEY_encrypt test: no redirection"); 262 /* Encrypt some data: should succeed but not be redirected */ 263 if (!TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0) 264 || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0) 265 || !TEST_false(called_encrypt)) 266 goto err; 267 EVP_PKEY_CTX_free(ctx); 268 ctx = NULL; 269 270 /* Create a test ENGINE */ 271 if (!TEST_ptr(e = ENGINE_new()) 272 || !TEST_true(ENGINE_set_id(e, "Test redirect engine")) 273 || !TEST_true(ENGINE_set_name(e, "Test redirect engine"))) 274 goto err; 275 276 /* 277 * Try to create a context for this engine and test key. 278 * Try setting test key engine. Both should fail because the 279 * engine has no public key methods. 280 */ 281 if (!TEST_ptr_null(EVP_PKEY_CTX_new(pkey, e)) 282 || !TEST_int_le(EVP_PKEY_set1_engine(pkey, e), 0)) 283 goto err; 284 285 /* Setup an empty test EVP_PKEY_METHOD and set callback to return it */ 286 if (!TEST_ptr(test_rsa = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0))) 287 goto err; 288 ENGINE_set_pkey_meths(e, test_pkey_meths); 289 290 /* Getting a context for test ENGINE should now succeed */ 291 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, e))) 292 goto err; 293 /* Encrypt should fail because operation is not supported */ 294 if (!TEST_int_le(EVP_PKEY_encrypt_init(ctx), 0)) 295 goto err; 296 EVP_PKEY_CTX_free(ctx); 297 ctx = NULL; 298 299 /* Add test encrypt operation to method */ 300 EVP_PKEY_meth_set_encrypt(test_rsa, 0, test_encrypt); 301 302 TEST_info("EVP_PKEY_encrypt test: redirection via EVP_PKEY_CTX_new()"); 303 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, e))) 304 goto err; 305 /* Encrypt some data: should succeed and be redirected */ 306 if (!TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0) 307 || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0) 308 || !TEST_true(called_encrypt)) 309 goto err; 310 311 EVP_PKEY_CTX_free(ctx); 312 ctx = NULL; 313 called_encrypt = 0; 314 315 /* Create context with default engine: should not be redirected */ 316 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL)) 317 || !TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0) 318 || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0) 319 || !TEST_false(called_encrypt)) 320 goto err; 321 322 EVP_PKEY_CTX_free(ctx); 323 ctx = NULL; 324 325 /* Set engine explicitly for test key */ 326 if (!TEST_true(EVP_PKEY_set1_engine(pkey, e))) 327 goto err; 328 329 TEST_info("EVP_PKEY_encrypt test: redirection via EVP_PKEY_set1_engine()"); 330 331 /* Create context with default engine: should be redirected now */ 332 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL)) 333 || !TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0) 334 || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0) 335 || !TEST_true(called_encrypt)) 336 goto err; 337 338 to_return = 1; 339 340 err: 341 EVP_PKEY_CTX_free(ctx); 342 EVP_PKEY_free(pkey); 343 ENGINE_free(e); 344 OPENSSL_free(tmp); 345 return to_return; 346} 347#endif 348 349int setup_tests(void) 350{ 351#ifdef OPENSSL_NO_ENGINE 352 TEST_note("No ENGINE support"); 353#else 354 ADD_TEST(test_engines); 355 ADD_TEST(test_redirect); 356#endif 357 return 1; 358} 359