Home | History | Annotate | Line # | Download | only in test
provider_test.c revision 1.1.1.1
      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     /*
     54      * We set properties that we know the providers we are using don't have.
     55      * This should mean that the p_test provider will fail any fetches - which
     56      * is something we test inside the provider.
     57      */
     58     EVP_set_default_properties(*libctx, "fips=yes");
     59     /*
     60      * Check that it is possible to have a built-in provider mirrored in
     61      * a child lib ctx.
     62      */
     63     if (!TEST_ptr(base = OSSL_PROVIDER_load(*libctx, "base")))
     64         goto err;
     65     if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name)))
     66         goto err;
     67 
     68     /*
     69      * Once the provider is loaded we clear the default properties and fetches
     70      * should start working again.
     71      */
     72     EVP_set_default_properties(*libctx, "");
     73     if (dolegacycheck) {
     74         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
     75                 || !TEST_true(digestsuccess))
     76             goto err;
     77 
     78         /*
     79          * Check that a provider can prevent property mirroring if it sets its
     80          * own properties explicitly
     81          */
     82         if (!TEST_true(OSSL_PROVIDER_get_params(prov, stop_property_mirror))
     83                 || !TEST_true(stopsuccess))
     84             goto err;
     85         EVP_set_default_properties(*libctx, "fips=yes");
     86         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
     87                 || !TEST_true(digestsuccess))
     88             goto err;
     89         EVP_set_default_properties(*libctx, "");
     90     }
     91     if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
     92             || !TEST_ptr(greeting = greeting_request[0].data)
     93             || !TEST_size_t_gt(greeting_request[0].data_size, 0)
     94             || !TEST_str_eq(greeting, expected_greeting))
     95         goto err;
     96 
     97     /* Make sure we got the error we were expecting */
     98     err = ERR_peek_last_error();
     99     if (!TEST_int_gt(err, 0)
    100             || !TEST_int_eq(ERR_GET_REASON(err), 1))
    101         goto err;
    102 
    103     OSSL_PROVIDER_unload(legacy);
    104     legacy = NULL;
    105 
    106     if (dolegacycheck) {
    107         /* Legacy provider should also be unloaded from child libctx */
    108         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
    109                 || !TEST_false(digestsuccess))
    110             goto err;
    111         /*
    112          * Loading the legacy provider again should make it available again in
    113          * the child libctx. Loading and unloading the default provider should
    114          * have no impact on the child because the child loads it explicitly
    115          * before this point.
    116          */
    117         legacy = OSSL_PROVIDER_load(*libctx, "legacy");
    118         deflt = OSSL_PROVIDER_load(*libctx, "default");
    119         if (!TEST_ptr(deflt)
    120                 || !TEST_true(OSSL_PROVIDER_available(*libctx, "default")))
    121             goto err;
    122         OSSL_PROVIDER_unload(deflt);
    123         deflt = NULL;
    124         if (!TEST_ptr(legacy)
    125                 || !TEST_false(OSSL_PROVIDER_available(*libctx, "default"))
    126                 || !TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
    127                 || !TEST_true(digestsuccess))
    128         goto err;
    129         OSSL_PROVIDER_unload(legacy);
    130         legacy = NULL;
    131     }
    132 
    133     if (!TEST_true(OSSL_PROVIDER_unload(base)))
    134         goto err;
    135     base = NULL;
    136     if (!TEST_true(OSSL_PROVIDER_unload(prov)))
    137         goto err;
    138     prov = NULL;
    139 
    140     /*
    141      * We must free the libctx to force the provider to really be unloaded from
    142      * memory
    143      */
    144     OSSL_LIB_CTX_free(*libctx);
    145     *libctx = NULL;
    146 
    147     /* We print out all the data to make sure it can still be accessed */
    148     ERR_print_errors_fp(stderr);
    149     ok = 1;
    150  err:
    151     OSSL_PROVIDER_unload(base);
    152     OSSL_PROVIDER_unload(deflt);
    153     OSSL_PROVIDER_unload(legacy);
    154     legacy = NULL;
    155     OSSL_PROVIDER_unload(prov);
    156     OSSL_LIB_CTX_free(*libctx);
    157     *libctx = NULL;
    158     return ok;
    159 }
    160 
    161 #ifndef NO_PROVIDER_MODULE
    162 static int test_provider_ex(OSSL_LIB_CTX **libctx, const char *name)
    163 {
    164     OSSL_PROVIDER *prov = NULL;
    165     const char *greeting = NULL;
    166     int ok = 0;
    167     long err;
    168     const char custom_buf[] = "Custom greeting";
    169     OSSL_PARAM_BLD *bld = NULL;
    170     OSSL_PARAM *params = NULL;
    171 
    172     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
    173         || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(bld, "greeting", custom_buf,
    174                                                       strlen(custom_buf)))
    175         || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) {
    176         goto err;
    177     }
    178 
    179     if (!TEST_ptr(prov = OSSL_PROVIDER_load_ex(*libctx, name, params)))
    180         goto err;
    181 
    182     if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
    183             || !TEST_ptr(greeting = greeting_request[0].data)
    184             || !TEST_size_t_gt(greeting_request[0].data_size, 0)
    185             || !TEST_str_eq(greeting, custom_buf))
    186         goto err;
    187 
    188     /* Make sure we got the error we were expecting */
    189     err = ERR_peek_last_error();
    190     if (!TEST_int_gt(err, 0)
    191             || !TEST_int_eq(ERR_GET_REASON(err), 1))
    192         goto err;
    193 
    194     if (!TEST_true(OSSL_PROVIDER_unload(prov)))
    195         goto err;
    196     prov = NULL;
    197 
    198     /*
    199      * We must free the libctx to force the provider to really be unloaded from
    200      * memory
    201      */
    202     OSSL_LIB_CTX_free(*libctx);
    203     *libctx = NULL;
    204 
    205     /* We print out all the data to make sure it can still be accessed */
    206     ERR_print_errors_fp(stderr);
    207     ok = 1;
    208  err:
    209     OSSL_PARAM_BLD_free(bld);
    210     OSSL_PARAM_free(params);
    211     OSSL_PROVIDER_unload(prov);
    212     OSSL_LIB_CTX_free(*libctx);
    213     *libctx = NULL;
    214     return ok;
    215 }
    216 #endif
    217 
    218 static int test_builtin_provider(void)
    219 {
    220     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
    221     const char *name = "p_test_builtin";
    222     int ok;
    223 
    224     ok =
    225         TEST_ptr(libctx)
    226         && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
    227                                                PROVIDER_INIT_FUNCTION_NAME))
    228         && test_provider(&libctx, name, NULL);
    229 
    230     OSSL_LIB_CTX_free(libctx);
    231 
    232     return ok;
    233 }
    234 
    235 /* Test relies on fetching the MD4 digest from the legacy provider */
    236 #ifndef OPENSSL_NO_MD4
    237 static int test_builtin_provider_with_child(void)
    238 {
    239     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
    240     const char *name = "p_test";
    241     OSSL_PROVIDER *legacy;
    242 
    243     if (!TEST_ptr(libctx))
    244         return 0;
    245 
    246     legacy = OSSL_PROVIDER_load(libctx, "legacy");
    247     if (legacy == NULL) {
    248         /*
    249          * In this case we assume we've been built with "no-legacy" and skip
    250          * this test (there is no OPENSSL_NO_LEGACY)
    251          */
    252         OSSL_LIB_CTX_free(libctx);
    253         return 1;
    254     }
    255 
    256     if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
    257                                              PROVIDER_INIT_FUNCTION_NAME))) {
    258         OSSL_PROVIDER_unload(legacy);
    259         OSSL_LIB_CTX_free(libctx);
    260         return 0;
    261     }
    262 
    263     /* test_provider will free libctx and unload legacy as part of the test */
    264     return test_provider(&libctx, name, legacy);
    265 }
    266 #endif
    267 
    268 #ifndef NO_PROVIDER_MODULE
    269 static int test_loaded_provider(void)
    270 {
    271     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
    272     const char *name = "p_test";
    273     int res = 0;
    274 
    275     if (!TEST_ptr(libctx))
    276         return 0;
    277 
    278     /* test_provider will free libctx as part of the test */
    279     res = test_provider(&libctx, name, NULL);
    280 
    281     libctx = OSSL_LIB_CTX_new();
    282     if (!TEST_ptr(libctx))
    283         return 0;
    284 
    285     /* test_provider_ex will free libctx as part of the test */
    286     res = res && test_provider_ex(&libctx, name);
    287 
    288     return res;
    289 }
    290 #endif
    291 
    292 typedef enum OPTION_choice {
    293     OPT_ERR = -1,
    294     OPT_EOF = 0,
    295     OPT_LOADED,
    296     OPT_TEST_ENUM
    297 } OPTION_CHOICE;
    298 
    299 const OPTIONS *test_get_options(void)
    300 {
    301     static const OPTIONS test_options[] = {
    302         OPT_TEST_OPTIONS_DEFAULT_USAGE,
    303         { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" },
    304         { NULL }
    305     };
    306     return test_options;
    307 }
    308 
    309 int setup_tests(void)
    310 {
    311     OPTION_CHOICE o;
    312     int loaded = 0;
    313 
    314     while ((o = opt_next()) != OPT_EOF) {
    315         switch (o) {
    316         case OPT_TEST_CASES:
    317             break;
    318         case OPT_LOADED:
    319             loaded = 1;
    320             break;
    321         default:
    322             return 0;
    323         }
    324     }
    325 
    326     if (!loaded) {
    327         ADD_TEST(test_builtin_provider);
    328 #ifndef OPENSSL_NO_MD4
    329         ADD_TEST(test_builtin_provider_with_child);
    330 #endif
    331     }
    332 #ifndef NO_PROVIDER_MODULE
    333     else {
    334         ADD_TEST(test_loaded_provider);
    335     }
    336 #endif
    337     return 1;
    338 }
    339 
    340