Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2019-2024 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 #include <stddef.h>
     11 #include <openssl/provider.h>
     12 #include "testutil.h"
     13 
     14 extern OSSL_provider_init_fn PROVIDER_INIT_FUNCTION_NAME;
     15 
     16 static char buf[256];
     17 static OSSL_PARAM greeting_request[] = {
     18     { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf) },
     19     { NULL, 0, NULL, 0, 0 }
     20 };
     21 
     22 static unsigned int digestsuccess = 0;
     23 static OSSL_PARAM digest_check[] = {
     24     { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, &digestsuccess,
     25       sizeof(digestsuccess) },
     26     { NULL, 0, NULL, 0, 0 }
     27 };
     28 
     29 static unsigned int stopsuccess = 0;
     30 static OSSL_PARAM stop_property_mirror[] = {
     31     { "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess,
     32       sizeof(stopsuccess) },
     33     { NULL, 0, NULL, 0, 0 }
     34 };
     35 
     36 static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
     37                          OSSL_PROVIDER *legacy)
     38 {
     39     OSSL_PROVIDER *prov = NULL;
     40     const char *greeting = NULL;
     41     char expected_greeting[256];
     42     int ok = 0;
     43     long err;
     44     int dolegacycheck = (legacy != NULL);
     45     OSSL_PROVIDER *deflt = NULL, *base = NULL;
     46 
     47     BIO_snprintf(expected_greeting, sizeof(expected_greeting),
     48                  "Hello OpenSSL %.20s, greetings from %s!",
     49                  OPENSSL_VERSION_STR, name);
     50 
     51 
     52     /*
     53      * We set properties that we know the providers we are using don't have.
     54      * This should mean that the p_test provider will fail any fetches - which
     55      * is something we test inside the provider.
     56      */
     57     EVP_set_default_properties(*libctx, "fips=yes");
     58     /*
     59      * Check that it is possible to have a built-in provider mirrored in
     60      * a child lib ctx.
     61      */
     62     if (!TEST_ptr(base = OSSL_PROVIDER_load(*libctx, "base")))
     63         goto err;
     64     if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name)))
     65         goto err;
     66 
     67     /*
     68      * Once the provider is loaded we clear the default properties and fetches
     69      * should start working again.
     70      */
     71     EVP_set_default_properties(*libctx, "");
     72     if (dolegacycheck) {
     73         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
     74                 || !TEST_true(digestsuccess))
     75             goto err;
     76 
     77         /*
     78          * Check that a provider can prevent property mirroring if it sets its
     79          * own properties explicitly
     80          */
     81         if (!TEST_true(OSSL_PROVIDER_get_params(prov, stop_property_mirror))
     82                 || !TEST_true(stopsuccess))
     83             goto err;
     84         EVP_set_default_properties(*libctx, "fips=yes");
     85         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
     86                 || !TEST_true(digestsuccess))
     87             goto err;
     88         EVP_set_default_properties(*libctx, "");
     89     }
     90     if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
     91             || !TEST_ptr(greeting = greeting_request[0].data)
     92             || !TEST_size_t_gt(greeting_request[0].data_size, 0)
     93             || !TEST_str_eq(greeting, expected_greeting))
     94         goto err;
     95 
     96     /* Make sure we got the error we were expecting */
     97     err = ERR_peek_last_error();
     98     if (!TEST_int_gt(err, 0)
     99             || !TEST_int_eq(ERR_GET_REASON(err), 1))
    100         goto err;
    101 
    102     OSSL_PROVIDER_unload(legacy);
    103     legacy = NULL;
    104 
    105     if (dolegacycheck) {
    106         /* Legacy provider should also be unloaded from child libctx */
    107         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
    108                 || !TEST_false(digestsuccess))
    109             goto err;
    110         /*
    111          * Loading the legacy provider again should make it available again in
    112          * the child libctx. Loading and unloading the default provider should
    113          * have no impact on the child because the child loads it explicitly
    114          * before this point.
    115          */
    116         legacy = OSSL_PROVIDER_load(*libctx, "legacy");
    117         deflt = OSSL_PROVIDER_load(*libctx, "default");
    118         if (!TEST_ptr(deflt)
    119                 || !TEST_true(OSSL_PROVIDER_available(*libctx, "default")))
    120             goto err;
    121         OSSL_PROVIDER_unload(deflt);
    122         deflt = NULL;
    123         if (!TEST_ptr(legacy)
    124                 || !TEST_false(OSSL_PROVIDER_available(*libctx, "default"))
    125                 || !TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
    126                 || !TEST_true(digestsuccess))
    127         goto err;
    128         OSSL_PROVIDER_unload(legacy);
    129         legacy = NULL;
    130     }
    131 
    132     if (!TEST_true(OSSL_PROVIDER_unload(base)))
    133         goto err;
    134     base = NULL;
    135     if (!TEST_true(OSSL_PROVIDER_unload(prov)))
    136         goto err;
    137     prov = NULL;
    138 
    139     /*
    140      * We must free the libctx to force the provider to really be unloaded from
    141      * memory
    142      */
    143     OSSL_LIB_CTX_free(*libctx);
    144     *libctx = NULL;
    145 
    146     /* We print out all the data to make sure it can still be accessed */
    147     ERR_print_errors_fp(stderr);
    148     ok = 1;
    149  err:
    150     OSSL_PROVIDER_unload(base);
    151     OSSL_PROVIDER_unload(deflt);
    152     OSSL_PROVIDER_unload(legacy);
    153     legacy = NULL;
    154     OSSL_PROVIDER_unload(prov);
    155     OSSL_LIB_CTX_free(*libctx);
    156     *libctx = NULL;
    157     return ok;
    158 }
    159 
    160 static int test_builtin_provider(void)
    161 {
    162     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
    163     const char *name = "p_test_builtin";
    164     int ok;
    165 
    166     ok =
    167         TEST_ptr(libctx)
    168         && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
    169                                                PROVIDER_INIT_FUNCTION_NAME))
    170         && test_provider(&libctx, name, NULL);
    171 
    172     OSSL_LIB_CTX_free(libctx);
    173 
    174     return ok;
    175 }
    176 
    177 /* Test relies on fetching the MD4 digest from the legacy provider */
    178 #ifndef OPENSSL_NO_MD4
    179 static int test_builtin_provider_with_child(void)
    180 {
    181     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
    182     const char *name = "p_test";
    183     OSSL_PROVIDER *legacy;
    184 
    185     if (!TEST_ptr(libctx))
    186         return 0;
    187 
    188     legacy = OSSL_PROVIDER_load(libctx, "legacy");
    189     if (legacy == NULL) {
    190         /*
    191          * In this case we assume we've been built with "no-legacy" and skip
    192          * this test (there is no OPENSSL_NO_LEGACY)
    193          */
    194         OSSL_LIB_CTX_free(libctx);
    195         return 1;
    196     }
    197 
    198     if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
    199                                              PROVIDER_INIT_FUNCTION_NAME))) {
    200         OSSL_PROVIDER_unload(legacy);
    201         OSSL_LIB_CTX_free(libctx);
    202         return 0;
    203     }
    204 
    205     /* test_provider will free libctx and unload legacy as part of the test */
    206     return test_provider(&libctx, name, legacy);
    207 }
    208 #endif
    209 
    210 #ifndef NO_PROVIDER_MODULE
    211 static int test_loaded_provider(void)
    212 {
    213     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
    214     const char *name = "p_test";
    215 
    216     if (!TEST_ptr(libctx))
    217         return 0;
    218 
    219     /* test_provider will free libctx as part of the test */
    220     return test_provider(&libctx, name, NULL);
    221 }
    222 #endif
    223 
    224 typedef enum OPTION_choice {
    225     OPT_ERR = -1,
    226     OPT_EOF = 0,
    227     OPT_LOADED,
    228     OPT_TEST_ENUM
    229 } OPTION_CHOICE;
    230 
    231 const OPTIONS *test_get_options(void)
    232 {
    233     static const OPTIONS test_options[] = {
    234         OPT_TEST_OPTIONS_DEFAULT_USAGE,
    235         { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" },
    236         { NULL }
    237     };
    238     return test_options;
    239 }
    240 
    241 int setup_tests(void)
    242 {
    243     OPTION_CHOICE o;
    244     int loaded = 0;
    245 
    246     while ((o = opt_next()) != OPT_EOF) {
    247         switch (o) {
    248         case OPT_TEST_CASES:
    249             break;
    250         case OPT_LOADED:
    251             loaded = 1;
    252             break;
    253         default:
    254             return 0;
    255         }
    256     }
    257 
    258     if (!loaded) {
    259         ADD_TEST(test_builtin_provider);
    260 #ifndef OPENSSL_NO_MD4
    261         ADD_TEST(test_builtin_provider_with_child);
    262 #endif
    263     }
    264 #ifndef NO_PROVIDER_MODULE
    265     else {
    266         ADD_TEST(test_loaded_provider);
    267     }
    268 #endif
    269     return 1;
    270 }
    271 
    272