Home | History | Annotate | Line # | Download | only in test
      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 
     24 static 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 
     44 static 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 */
    185 static EVP_PKEY_METHOD *test_rsa = NULL;
    186 
    187 static int called_encrypt = 0;
    188 
    189 /* Test function to check operation has been redirected */
    190 static 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 
    197 static 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 
    217 static 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 
    245 static 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 
    353 int 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 
    362 int 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