Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2019-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 /*
     11  * SHA256 low level APIs are deprecated for public use, but still ok for
     12  * internal use.  Note, that due to symbols not being exported, only the
     13  * #defines can be accessed.  In this case SHA256_CBLOCK.
     14  */
     15 #include "internal/deprecated.h"
     16 
     17 #include <string.h>
     18 #include <openssl/sha.h>
     19 #include <openssl/evp.h>
     20 #include <openssl/provider.h>
     21 #include "internal/sizes.h"
     22 #include "testutil.h"
     23 
     24 static char *config_file = NULL;
     25 static char *alg = "digest";
     26 static int use_default_ctx = 0;
     27 static char *fetch_property = NULL;
     28 static int expected_fetch_result = 1;
     29 
     30 typedef enum OPTION_choice {
     31     OPT_ERR = -1,
     32     OPT_EOF = 0,
     33     OPT_ALG_FETCH_TYPE,
     34     OPT_FETCH_PROPERTY,
     35     OPT_FETCH_FAILURE,
     36     OPT_USE_DEFAULTCTX,
     37     OPT_CONFIG_FILE,
     38     OPT_TEST_ENUM
     39 } OPTION_CHOICE;
     40 
     41 const OPTIONS *test_get_options(void)
     42 {
     43     static const OPTIONS test_options[] = {
     44         OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("[provname...]\n"),
     45         { "config", OPT_CONFIG_FILE, '<', "The configuration file to use for the libctx" },
     46         { "type", OPT_ALG_FETCH_TYPE, 's', "The fetch type to test" },
     47         { "property", OPT_FETCH_PROPERTY, 's', "The fetch property e.g. provider=fips" },
     48         { "fetchfail", OPT_FETCH_FAILURE, '-', "fetch is expected to fail" },
     49         { "defaultctx", OPT_USE_DEFAULTCTX, '-',
     50             "Use the default context if this is set" },
     51         { OPT_HELP_STR, 1, '-', "file\tProvider names to explicitly load\n" },
     52         { NULL }
     53     };
     54     return test_options;
     55 }
     56 
     57 static int calculate_digest(const EVP_MD *md, const char *msg, size_t len,
     58     const unsigned char *exptd)
     59 {
     60     unsigned char out[SHA256_DIGEST_LENGTH];
     61     EVP_MD_CTX *ctx;
     62     int ret = 0;
     63 
     64     if (!TEST_ptr(ctx = EVP_MD_CTX_new())
     65         || !TEST_true(EVP_DigestInit_ex(ctx, md, NULL))
     66         || !TEST_true(EVP_DigestUpdate(ctx, msg, len))
     67         || !TEST_true(EVP_DigestFinal_ex(ctx, out, NULL))
     68         || !TEST_mem_eq(out, SHA256_DIGEST_LENGTH, exptd,
     69             SHA256_DIGEST_LENGTH)
     70         || !TEST_true(md == EVP_MD_CTX_get0_md(ctx)))
     71         goto err;
     72 
     73     ret = 1;
     74 err:
     75     EVP_MD_CTX_free(ctx);
     76     return ret;
     77 }
     78 
     79 static int load_providers(OSSL_LIB_CTX **libctx, OSSL_PROVIDER *prov[])
     80 {
     81     OSSL_LIB_CTX *ctx = NULL;
     82     int ret = 0;
     83     size_t i;
     84 
     85     ctx = OSSL_LIB_CTX_new();
     86     if (!TEST_ptr(ctx))
     87         goto err;
     88 
     89     if (!TEST_true(OSSL_LIB_CTX_load_config(ctx, config_file)))
     90         goto err;
     91     if (test_get_argument_count() > 2)
     92         goto err;
     93 
     94     for (i = 0; i < test_get_argument_count(); ++i) {
     95         char *provname = test_get_argument(i);
     96         prov[i] = OSSL_PROVIDER_load(ctx, provname);
     97         if (!TEST_ptr(prov[i]))
     98             goto err;
     99     }
    100 
    101     ret = 1;
    102     *libctx = ctx;
    103 err:
    104     if (ret == 0)
    105         OSSL_LIB_CTX_free(ctx);
    106     return ret;
    107 }
    108 
    109 static void unload_providers(OSSL_LIB_CTX **libctx, OSSL_PROVIDER *prov[])
    110 {
    111     if (prov[0] != NULL)
    112         OSSL_PROVIDER_unload(prov[0]);
    113     if (prov[1] != NULL)
    114         OSSL_PROVIDER_unload(prov[1]);
    115     /* Not normally needed, but we would like to test that
    116      * OPENSSL_thread_stop_ex() behaves as expected.
    117      */
    118     if (libctx != NULL && *libctx != NULL) {
    119         OPENSSL_thread_stop_ex(*libctx);
    120         OSSL_LIB_CTX_free(*libctx);
    121     }
    122 }
    123 
    124 static int test_legacy_provider_unloaded(void)
    125 {
    126     OSSL_LIB_CTX *ctx = NULL;
    127     int rc = 0;
    128 
    129     ctx = OSSL_LIB_CTX_new();
    130     if (!TEST_ptr(ctx))
    131         goto err;
    132 
    133     if (!TEST_true(OSSL_LIB_CTX_load_config(ctx, config_file)))
    134         goto err;
    135 
    136     if (!TEST_int_eq(OSSL_PROVIDER_available(ctx, "legacy"), 0))
    137         goto err;
    138 
    139     rc = 1;
    140 err:
    141     OSSL_LIB_CTX_free(ctx);
    142     return rc;
    143 }
    144 
    145 static X509_ALGOR *make_algor(int nid)
    146 {
    147     X509_ALGOR *algor;
    148 
    149     if (!TEST_ptr(algor = X509_ALGOR_new())
    150         || !TEST_true(X509_ALGOR_set0(algor, OBJ_nid2obj(nid),
    151             V_ASN1_UNDEF, NULL))) {
    152         X509_ALGOR_free(algor);
    153         return NULL;
    154     }
    155     return algor;
    156 }
    157 
    158 /*
    159  * Test EVP_MD_fetch()
    160  */
    161 static int test_md(const EVP_MD *md)
    162 {
    163     const char testmsg[] = "Hello world";
    164     const unsigned char exptd[] = {
    165         0x27, 0x51, 0x8b, 0xa9, 0x68, 0x30, 0x11, 0xf6, 0xb3, 0x96, 0x07, 0x2c,
    166         0x05, 0xf6, 0x65, 0x6d, 0x04, 0xf5, 0xfb, 0xc3, 0x78, 0x7c, 0xf9, 0x24,
    167         0x90, 0xec, 0x60, 0x6e, 0x50, 0x92, 0xe3, 0x26
    168     };
    169 
    170     return TEST_ptr(md)
    171         && TEST_true(EVP_MD_is_a(md, "SHA256"))
    172         && TEST_true(calculate_digest(md, testmsg, sizeof(testmsg), exptd))
    173         && TEST_int_eq(EVP_MD_get_size(md), SHA256_DIGEST_LENGTH)
    174         && TEST_int_eq(EVP_MD_get_block_size(md), SHA256_CBLOCK);
    175 }
    176 
    177 static int test_implicit_EVP_MD_fetch(void)
    178 {
    179     OSSL_LIB_CTX *ctx = NULL;
    180     OSSL_PROVIDER *prov[2] = { NULL, NULL };
    181     int ret = 0;
    182 
    183     ret = (use_default_ctx == 0 || load_providers(&ctx, prov))
    184         && test_md(EVP_sha256());
    185 
    186     unload_providers(&ctx, prov);
    187     return ret;
    188 }
    189 
    190 static int test_explicit_EVP_MD_fetch(const char *id)
    191 {
    192     OSSL_LIB_CTX *ctx = NULL;
    193     EVP_MD *md = NULL;
    194     OSSL_PROVIDER *prov[2] = { NULL, NULL };
    195     int ret = 0;
    196 
    197     if (use_default_ctx == 0 && !load_providers(&ctx, prov))
    198         goto err;
    199 
    200     md = EVP_MD_fetch(ctx, id, fetch_property);
    201     if (expected_fetch_result != 0) {
    202         if (!test_md(md))
    203             goto err;
    204 
    205         /* Also test EVP_MD_up_ref() while we're doing this */
    206         if (!TEST_true(EVP_MD_up_ref(md)))
    207             goto err;
    208         /* Ref count should now be 2. Release first one here */
    209         EVP_MD_free(md);
    210     } else {
    211         if (!TEST_ptr_null(md))
    212             goto err;
    213     }
    214     ret = 1;
    215 
    216 err:
    217     EVP_MD_free(md);
    218     unload_providers(&ctx, prov);
    219     return ret;
    220 }
    221 
    222 static int test_explicit_EVP_MD_fetch_by_name(void)
    223 {
    224     return test_explicit_EVP_MD_fetch("SHA256");
    225 }
    226 
    227 /*
    228  * idx 0: Allow names from OBJ_obj2txt()
    229  * idx 1: Force an OID in text form from OBJ_obj2txt()
    230  */
    231 static int test_explicit_EVP_MD_fetch_by_X509_ALGOR(int idx)
    232 {
    233     int ret = 0;
    234     X509_ALGOR *algor = make_algor(NID_sha256);
    235     const ASN1_OBJECT *obj;
    236     char id[OSSL_MAX_NAME_SIZE] = { 0 };
    237 
    238     if (algor == NULL)
    239         return 0;
    240 
    241     X509_ALGOR_get0(&obj, NULL, NULL, algor);
    242     switch (idx) {
    243     case 0:
    244         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 0), 0))
    245             goto end;
    246         break;
    247     case 1:
    248         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 1), 0))
    249             goto end;
    250         break;
    251     }
    252 
    253     ret = test_explicit_EVP_MD_fetch(id);
    254 end:
    255     X509_ALGOR_free(algor);
    256     return ret;
    257 }
    258 
    259 /*
    260  * Test EVP_CIPHER_fetch()
    261  */
    262 static int encrypt_decrypt(const EVP_CIPHER *cipher, const unsigned char *msg,
    263     size_t len)
    264 {
    265     int ret = 0, ctlen, ptlen;
    266     EVP_CIPHER_CTX *ctx = NULL;
    267     unsigned char key[128 / 8];
    268     unsigned char ct[64], pt[64];
    269 
    270     memset(key, 0, sizeof(key));
    271     if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
    272         || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, 1))
    273         || !TEST_true(EVP_CipherUpdate(ctx, ct, &ctlen, msg, len))
    274         || !TEST_true(EVP_CipherFinal_ex(ctx, ct, &ctlen))
    275         || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, 0))
    276         || !TEST_true(EVP_CipherUpdate(ctx, pt, &ptlen, ct, ctlen))
    277         || !TEST_true(EVP_CipherFinal_ex(ctx, pt, &ptlen))
    278         || !TEST_mem_eq(pt, ptlen, msg, len))
    279         goto err;
    280 
    281     ret = 1;
    282 err:
    283     EVP_CIPHER_CTX_free(ctx);
    284     return ret;
    285 }
    286 
    287 static int test_cipher(const EVP_CIPHER *cipher)
    288 {
    289     const unsigned char testmsg[] = "Hello world";
    290 
    291     return TEST_ptr(cipher)
    292         && TEST_true(encrypt_decrypt(cipher, testmsg, sizeof(testmsg)));
    293 }
    294 
    295 static int test_implicit_EVP_CIPHER_fetch(void)
    296 {
    297     OSSL_LIB_CTX *ctx = NULL;
    298     OSSL_PROVIDER *prov[2] = { NULL, NULL };
    299     int ret = 0;
    300 
    301     ret = (use_default_ctx == 0 || load_providers(&ctx, prov))
    302         && test_cipher(EVP_aes_128_cbc());
    303 
    304     unload_providers(&ctx, prov);
    305     return ret;
    306 }
    307 
    308 static int test_explicit_EVP_CIPHER_fetch(const char *id)
    309 {
    310     OSSL_LIB_CTX *ctx = NULL;
    311     EVP_CIPHER *cipher = NULL;
    312     OSSL_PROVIDER *prov[2] = { NULL, NULL };
    313     int ret = 0;
    314 
    315     if (use_default_ctx == 0 && !load_providers(&ctx, prov))
    316         goto err;
    317 
    318     cipher = EVP_CIPHER_fetch(ctx, id, fetch_property);
    319     if (expected_fetch_result != 0) {
    320         if (!test_cipher(cipher))
    321             goto err;
    322 
    323         if (!TEST_true(EVP_CIPHER_up_ref(cipher)))
    324             goto err;
    325         /* Ref count should now be 2. Release first one here */
    326         EVP_CIPHER_free(cipher);
    327     } else {
    328         if (!TEST_ptr_null(cipher))
    329             goto err;
    330     }
    331     ret = 1;
    332 err:
    333     EVP_CIPHER_free(cipher);
    334     unload_providers(&ctx, prov);
    335     return ret;
    336 }
    337 
    338 static int test_explicit_EVP_CIPHER_fetch_by_name(void)
    339 {
    340     return test_explicit_EVP_CIPHER_fetch("AES-128-CBC");
    341 }
    342 
    343 /*
    344  * idx 0: Allow names from OBJ_obj2txt()
    345  * idx 1: Force an OID in text form from OBJ_obj2txt()
    346  */
    347 static int test_explicit_EVP_CIPHER_fetch_by_X509_ALGOR(int idx)
    348 {
    349     int ret = 0;
    350     X509_ALGOR *algor = make_algor(NID_aes_128_cbc);
    351     const ASN1_OBJECT *obj;
    352     char id[OSSL_MAX_NAME_SIZE] = { 0 };
    353 
    354     if (algor == NULL)
    355         return 0;
    356 
    357     X509_ALGOR_get0(&obj, NULL, NULL, algor);
    358     switch (idx) {
    359     case 0:
    360         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 0), 0))
    361             goto end;
    362         break;
    363     case 1:
    364         if (!TEST_int_gt(OBJ_obj2txt(id, sizeof(id), obj, 1), 0))
    365             goto end;
    366         break;
    367     }
    368 
    369     ret = test_explicit_EVP_CIPHER_fetch(id);
    370 end:
    371     X509_ALGOR_free(algor);
    372     return ret;
    373 }
    374 
    375 int setup_tests(void)
    376 {
    377     OPTION_CHOICE o;
    378 
    379     while ((o = opt_next()) != OPT_EOF) {
    380         switch (o) {
    381         case OPT_CONFIG_FILE:
    382             config_file = opt_arg();
    383             break;
    384         case OPT_ALG_FETCH_TYPE:
    385             alg = opt_arg();
    386             break;
    387         case OPT_FETCH_PROPERTY:
    388             fetch_property = opt_arg();
    389             break;
    390         case OPT_FETCH_FAILURE:
    391             expected_fetch_result = 0;
    392             break;
    393         case OPT_USE_DEFAULTCTX:
    394             use_default_ctx = 1;
    395             break;
    396         case OPT_TEST_CASES:
    397             break;
    398         default:
    399         case OPT_ERR:
    400             return 0;
    401         }
    402     }
    403     ADD_TEST(test_legacy_provider_unloaded);
    404     if (strcmp(alg, "digest") == 0) {
    405         ADD_TEST(test_implicit_EVP_MD_fetch);
    406         ADD_TEST(test_explicit_EVP_MD_fetch_by_name);
    407         ADD_ALL_TESTS_NOSUBTEST(test_explicit_EVP_MD_fetch_by_X509_ALGOR, 2);
    408     } else {
    409         ADD_TEST(test_implicit_EVP_CIPHER_fetch);
    410         ADD_TEST(test_explicit_EVP_CIPHER_fetch_by_name);
    411         ADD_ALL_TESTS_NOSUBTEST(test_explicit_EVP_CIPHER_fetch_by_X509_ALGOR, 2);
    412     }
    413     return 1;
    414 }
    415