Path: blob/main/crypto/openssl/apps/lib/app_provider.c
34878 views
/*1* Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include "apps.h"10#include <ctype.h>11#include <string.h>12#include <openssl/err.h>13#include <openssl/provider.h>14#include <openssl/safestack.h>1516/* Non-zero if any of the provider options have been seen */17static int provider_option_given = 0;1819DEFINE_STACK_OF(OSSL_PROVIDER)2021/*22* See comments in opt_verify for explanation of this.23*/24enum prov_range { OPT_PROV_ENUM };2526static STACK_OF(OSSL_PROVIDER) *app_providers = NULL;2728static void provider_free(OSSL_PROVIDER *prov)29{30OSSL_PROVIDER_unload(prov);31}3233int app_provider_load(OSSL_LIB_CTX *libctx, const char *provider_name)34{35OSSL_PROVIDER *prov;3637prov = OSSL_PROVIDER_load(libctx, provider_name);38if (prov == NULL) {39opt_printf_stderr("%s: unable to load provider %s\n"40"Hint: use -provider-path option or OPENSSL_MODULES environment variable.\n",41opt_getprog(), provider_name);42ERR_print_errors(bio_err);43return 0;44}45if (app_providers == NULL)46app_providers = sk_OSSL_PROVIDER_new_null();47if (app_providers == NULL48|| !sk_OSSL_PROVIDER_push(app_providers, prov)) {49app_providers_cleanup();50return 0;51}52return 1;53}5455void app_providers_cleanup(void)56{57sk_OSSL_PROVIDER_pop_free(app_providers, provider_free);58app_providers = NULL;59}6061static int opt_provider_path(const char *path)62{63if (path != NULL && *path == '\0')64path = NULL;65return OSSL_PROVIDER_set_default_search_path(app_get0_libctx(), path);66}6768struct prov_param_st {69char *name;70char *key;71char *val;72int found;73};7475static int set_prov_param(OSSL_PROVIDER *prov, void *vp)76{77struct prov_param_st *p = (struct prov_param_st *)vp;7879if (p->name != NULL && strcmp(OSSL_PROVIDER_get0_name(prov), p->name) != 0)80return 1;81p->found = 1;82return OSSL_PROVIDER_add_conf_parameter(prov, p->key, p->val);83}8485static int opt_provider_param(const char *arg)86{87struct prov_param_st p;88char *copy, *tmp;89int ret = 0;9091if ((copy = OPENSSL_strdup(arg)) == NULL92|| (p.val = strchr(copy, '=')) == NULL) {93opt_printf_stderr("%s: malformed '-provparam' option value: '%s'\n",94opt_getprog(), arg);95goto end;96}9798/* Drop whitespace on both sides of the '=' sign */99*(tmp = p.val++) = '\0';100while (tmp > copy && isspace(_UC(*--tmp)))101*tmp = '\0';102while (isspace(_UC(*p.val)))103++p.val;104105/*106* Split the key on ':', to get the optional provider, empty or missing107* means all.108*/109if ((p.key = strchr(copy, ':')) != NULL) {110*p.key++ = '\0';111p.name = *copy != '\0' ? copy : NULL;112} else {113p.name = NULL;114p.key = copy;115}116117/* The key must not be empty */118if (*p.key == '\0') {119opt_printf_stderr("%s: malformed '-provparam' option value: '%s'\n",120opt_getprog(), arg);121goto end;122}123124p.found = 0;125ret = OSSL_PROVIDER_do_all(app_get0_libctx(), set_prov_param, (void *)&p);126if (ret == 0) {127opt_printf_stderr("%s: Error setting provider '%s' parameter '%s'\n",128opt_getprog(), p.name, p.key);129} else if (p.found == 0) {130opt_printf_stderr("%s: No provider named '%s' is loaded\n",131opt_getprog(), p.name);132ret = 0;133}134135end:136OPENSSL_free(copy);137return ret;138}139140int opt_provider(int opt)141{142const int given = provider_option_given;143144provider_option_given = 1;145switch ((enum prov_range)opt) {146case OPT_PROV__FIRST:147case OPT_PROV__LAST:148return 1;149case OPT_PROV_PROVIDER:150return app_provider_load(app_get0_libctx(), opt_arg());151case OPT_PROV_PROVIDER_PATH:152return opt_provider_path(opt_arg());153case OPT_PROV_PARAM:154return opt_provider_param(opt_arg());155case OPT_PROV_PROPQUERY:156return app_set_propq(opt_arg());157}158/* Should never get here but if we do, undo what we did earlier */159provider_option_given = given;160return 0;161}162163int opt_provider_option_given(void)164{165return provider_option_given;166}167168169