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 <openssl/param_build.h>
     13 #include "testutil.h"
     14 
     15 extern OSSL_provider_init_fn PROVIDER_INIT_FUNCTION_NAME;
     16 
     17 static char buf[256];
     18 static OSSL_PARAM greeting_request[] = {
     19     { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf) },
     20     { NULL, 0, NULL, 0, 0 }
     21 };
     22 
     23 static unsigned int digestsuccess = 0;
     24 static OSSL_PARAM digest_check[] = {
     25     { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, &digestsuccess,
     26         sizeof(digestsuccess) },
     27     { NULL, 0, NULL, 0, 0 }
     28 };
     29 
     30 static unsigned int stopsuccess = 0;
     31 static OSSL_PARAM stop_property_mirror[] = {
     32     { "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess,
     33         sizeof(stopsuccess) },
     34     { NULL, 0, NULL, 0, 0 }
     35 };
     36 
     37 static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
     38     OSSL_PROVIDER *legacy)
     39 {
     40     OSSL_PROVIDER *prov = NULL;
     41     const char *greeting = NULL;
     42     char expected_greeting[256];
     43     int ok = 0;
     44     long err;
     45     int dolegacycheck = (legacy != NULL);
     46     OSSL_PROVIDER *deflt = NULL, *base = NULL;
     47 
     48     BIO_snprintf(expected_greeting, sizeof(expected_greeting),
     49         "Hello OpenSSL %.20s, greetings from %s!",
     50         OPENSSL_VERSION_STR, name);
     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 #ifndef NO_PROVIDER_MODULE
    161 static int test_provider_ex(OSSL_LIB_CTX **libctx, const char *name)
    162 {
    163     OSSL_PROVIDER *prov = NULL;
    164     const char *greeting = NULL;
    165     int ok = 0;
    166     long err;
    167     const char custom_buf[] = "Custom greeting";
    168     OSSL_PARAM_BLD *bld = NULL;
    169     OSSL_PARAM *params = NULL;
    170 
    171     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
    172         || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(bld, "greeting", custom_buf,
    173             strlen(custom_buf)))
    174         || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) {
    175         goto err;
    176     }
    177 
    178     if (!TEST_ptr(prov = OSSL_PROVIDER_load_ex(*libctx, name, params)))
    179         goto err;
    180 
    181     if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
    182         || !TEST_ptr(greeting = greeting_request[0].data)
    183         || !TEST_size_t_gt(greeting_request[0].data_size, 0)
    184         || !TEST_str_eq(greeting, custom_buf))
    185         goto err;
    186 
    187     /* Make sure we got the error we were expecting */
    188     err = ERR_peek_last_error();
    189     if (!TEST_int_gt(err, 0)
    190         || !TEST_int_eq(ERR_GET_REASON(err), 1))
    191         goto err;
    192 
    193     if (!TEST_true(OSSL_PROVIDER_unload(prov)))
    194         goto err;
    195     prov = NULL;
    196 
    197     /*
    198      * We must free the libctx to force the provider to really be unloaded from
    199      * memory
    200      */
    201     OSSL_LIB_CTX_free(*libctx);
    202     *libctx = NULL;
    203 
    204     /* We print out all the data to make sure it can still be accessed */
    205     ERR_print_errors_fp(stderr);
    206     ok = 1;
    207 err:
    208     OSSL_PARAM_BLD_free(bld);
    209     OSSL_PARAM_free(params);
    210     OSSL_PROVIDER_unload(prov);
    211     OSSL_LIB_CTX_free(*libctx);
    212     *libctx = NULL;
    213     return ok;
    214 }
    215 #endif
    216 
    217 static int test_builtin_provider(void)
    218 {
    219     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
    220     const char *name = "p_test_builtin";
    221     int ok;
    222 
    223     ok = TEST_ptr(libctx)
    224         && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
    225             PROVIDER_INIT_FUNCTION_NAME))
    226         && test_provider(&libctx, name, NULL);
    227 
    228     OSSL_LIB_CTX_free(libctx);
    229 
    230     return ok;
    231 }
    232 
    233 /* Test relies on fetching the MD4 digest from the legacy provider */
    234 #ifndef OPENSSL_NO_MD4
    235 static int test_builtin_provider_with_child(void)
    236 {
    237     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
    238     const char *name = "p_test";
    239     OSSL_PROVIDER *legacy;
    240 
    241     if (!TEST_ptr(libctx))
    242         return 0;
    243 
    244     legacy = OSSL_PROVIDER_load(libctx, "legacy");
    245     if (legacy == NULL) {
    246         /*
    247          * In this case we assume we've been built with "no-legacy" and skip
    248          * this test (there is no OPENSSL_NO_LEGACY)
    249          */
    250         OSSL_LIB_CTX_free(libctx);
    251         return 1;
    252     }
    253 
    254     if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
    255             PROVIDER_INIT_FUNCTION_NAME))) {
    256         OSSL_PROVIDER_unload(legacy);
    257         OSSL_LIB_CTX_free(libctx);
    258         return 0;
    259     }
    260 
    261     /* test_provider will free libctx and unload legacy as part of the test */
    262     return test_provider(&libctx, name, legacy);
    263 }
    264 #endif
    265 
    266 #ifndef NO_PROVIDER_MODULE
    267 static int test_loaded_provider(void)
    268 {
    269     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
    270     const char *name = "p_test";
    271     int res = 0;
    272 
    273     if (!TEST_ptr(libctx))
    274         return 0;
    275 
    276     /* test_provider will free libctx as part of the test */
    277     res = test_provider(&libctx, name, NULL);
    278 
    279     libctx = OSSL_LIB_CTX_new();
    280     if (!TEST_ptr(libctx))
    281         return 0;
    282 
    283     /* test_provider_ex will free libctx as part of the test */
    284     res = res && test_provider_ex(&libctx, name);
    285 
    286     return res;
    287 }
    288 #endif
    289 
    290 typedef enum OPTION_choice {
    291     OPT_ERR = -1,
    292     OPT_EOF = 0,
    293     OPT_LOADED,
    294     OPT_TEST_ENUM
    295 } OPTION_CHOICE;
    296 
    297 const OPTIONS *test_get_options(void)
    298 {
    299     static const OPTIONS test_options[] = {
    300         OPT_TEST_OPTIONS_DEFAULT_USAGE,
    301         { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" },
    302         { NULL }
    303     };
    304     return test_options;
    305 }
    306 
    307 int setup_tests(void)
    308 {
    309     OPTION_CHOICE o;
    310     int loaded = 0;
    311 
    312     while ((o = opt_next()) != OPT_EOF) {
    313         switch (o) {
    314         case OPT_TEST_CASES:
    315             break;
    316         case OPT_LOADED:
    317             loaded = 1;
    318             break;
    319         default:
    320             return 0;
    321         }
    322     }
    323 
    324     if (!loaded) {
    325         ADD_TEST(test_builtin_provider);
    326 #ifndef OPENSSL_NO_MD4
    327         ADD_TEST(test_builtin_provider_with_child);
    328 #endif
    329     }
    330 #ifndef NO_PROVIDER_MODULE
    331     else {
    332         ADD_TEST(test_loaded_provider);
    333     }
    334 #endif
    335     return 1;
    336 }
    337