Path: blob/main/crypto/openssl/providers/common/provider_util.c
48266 views
/*1* Copyright 2019-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/* We need to use some engine deprecated APIs */10#define OPENSSL_SUPPRESS_DEPRECATED1112#include <openssl/evp.h>13#include <openssl/core_names.h>14#include <openssl/err.h>15#include <openssl/proverr.h>16#ifndef FIPS_MODULE17# include <openssl/engine.h>18# include "crypto/evp.h"19#endif20#include "prov/providercommon.h"21#include "prov/provider_util.h"2223void ossl_prov_cipher_reset(PROV_CIPHER *pc)24{25EVP_CIPHER_free(pc->alloc_cipher);26pc->alloc_cipher = NULL;27pc->cipher = NULL;28#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)29ENGINE_finish(pc->engine);30#endif31pc->engine = NULL;32}3334int ossl_prov_cipher_copy(PROV_CIPHER *dst, const PROV_CIPHER *src)35{36if (src->alloc_cipher != NULL && !EVP_CIPHER_up_ref(src->alloc_cipher))37return 0;38#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)39if (src->engine != NULL && !ENGINE_init(src->engine)) {40EVP_CIPHER_free(src->alloc_cipher);41return 0;42}43#endif44dst->engine = src->engine;45dst->cipher = src->cipher;46dst->alloc_cipher = src->alloc_cipher;47return 1;48}4950static int load_common(const OSSL_PARAM params[], const char **propquery,51ENGINE **engine)52{53const OSSL_PARAM *p;5455*propquery = NULL;56p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES);57if (p != NULL) {58if (p->data_type != OSSL_PARAM_UTF8_STRING)59return 0;60*propquery = p->data;61}6263#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)64ENGINE_finish(*engine);65#endif66*engine = NULL;67/* Inside the FIPS module, we don't support legacy ciphers */68#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)69p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE);70if (p != NULL) {71if (p->data_type != OSSL_PARAM_UTF8_STRING)72return 0;73/* Get a structural reference */74*engine = ENGINE_by_id(p->data);75if (*engine == NULL)76return 0;77/* Get a functional reference */78if (!ENGINE_init(*engine)) {79ENGINE_free(*engine);80*engine = NULL;81return 0;82}83/* Free the structural reference */84ENGINE_free(*engine);85}86#endif87return 1;88}8990int ossl_prov_cipher_load_from_params(PROV_CIPHER *pc,91const OSSL_PARAM params[],92OSSL_LIB_CTX *ctx)93{94const OSSL_PARAM *p;95const char *propquery;9697if (ossl_param_is_empty(params))98return 1;99100if (!load_common(params, &propquery, &pc->engine))101return 0;102103p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_CIPHER);104if (p == NULL)105return 1;106if (p->data_type != OSSL_PARAM_UTF8_STRING)107return 0;108109EVP_CIPHER_free(pc->alloc_cipher);110ERR_set_mark();111pc->cipher = pc->alloc_cipher = EVP_CIPHER_fetch(ctx, p->data, propquery);112#ifndef FIPS_MODULE /* Inside the FIPS module, we don't support legacy ciphers */113if (pc->cipher == NULL) {114const EVP_CIPHER *cipher;115116cipher = EVP_get_cipherbyname(p->data);117/* Do not use global EVP_CIPHERs */118if (cipher != NULL && cipher->origin != EVP_ORIG_GLOBAL)119pc->cipher = cipher;120}121#endif122if (pc->cipher != NULL)123ERR_pop_to_mark();124else125ERR_clear_last_mark();126return pc->cipher != NULL;127}128129const EVP_CIPHER *ossl_prov_cipher_cipher(const PROV_CIPHER *pc)130{131return pc->cipher;132}133134ENGINE *ossl_prov_cipher_engine(const PROV_CIPHER *pc)135{136return pc->engine;137}138139void ossl_prov_digest_reset(PROV_DIGEST *pd)140{141EVP_MD_free(pd->alloc_md);142pd->alloc_md = NULL;143pd->md = NULL;144#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)145ENGINE_finish(pd->engine);146#endif147pd->engine = NULL;148}149150int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src)151{152if (src->alloc_md != NULL && !EVP_MD_up_ref(src->alloc_md))153return 0;154#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)155if (src->engine != NULL && !ENGINE_init(src->engine)) {156EVP_MD_free(src->alloc_md);157return 0;158}159#endif160dst->engine = src->engine;161dst->md = src->md;162dst->alloc_md = src->alloc_md;163return 1;164}165166const EVP_MD *ossl_prov_digest_fetch(PROV_DIGEST *pd, OSSL_LIB_CTX *libctx,167const char *mdname, const char *propquery)168{169EVP_MD_free(pd->alloc_md);170pd->md = pd->alloc_md = EVP_MD_fetch(libctx, mdname, propquery);171172return pd->md;173}174175int ossl_prov_digest_load_from_params(PROV_DIGEST *pd,176const OSSL_PARAM params[],177OSSL_LIB_CTX *ctx)178{179const OSSL_PARAM *p;180const char *propquery;181182if (ossl_param_is_empty(params))183return 1;184185if (!load_common(params, &propquery, &pd->engine))186return 0;187188p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST);189if (p == NULL)190return 1;191if (p->data_type != OSSL_PARAM_UTF8_STRING)192return 0;193194ERR_set_mark();195ossl_prov_digest_fetch(pd, ctx, p->data, propquery);196#ifndef FIPS_MODULE /* Inside the FIPS module, we don't support legacy digests */197if (pd->md == NULL) {198const EVP_MD *md;199200md = EVP_get_digestbyname(p->data);201/* Do not use global EVP_MDs */202if (md != NULL && md->origin != EVP_ORIG_GLOBAL)203pd->md = md;204}205#endif206if (pd->md != NULL)207ERR_pop_to_mark();208else209ERR_clear_last_mark();210return pd->md != NULL;211}212213void ossl_prov_digest_set_md(PROV_DIGEST *pd, EVP_MD *md)214{215ossl_prov_digest_reset(pd);216pd->md = pd->alloc_md = md;217}218219const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd)220{221return pd->md;222}223224ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd)225{226return pd->engine;227}228229int ossl_prov_set_macctx(EVP_MAC_CTX *macctx,230const OSSL_PARAM params[],231const char *ciphername,232const char *mdname,233const char *engine,234const char *properties,235const unsigned char *key,236size_t keylen)237{238const OSSL_PARAM *p;239OSSL_PARAM mac_params[6], *mp = mac_params;240241if (params != NULL) {242if (mdname == NULL) {243if ((p = OSSL_PARAM_locate_const(params,244OSSL_ALG_PARAM_DIGEST)) != NULL) {245if (p->data_type != OSSL_PARAM_UTF8_STRING)246return 0;247mdname = p->data;248}249}250if (ciphername == NULL) {251if ((p = OSSL_PARAM_locate_const(params,252OSSL_ALG_PARAM_CIPHER)) != NULL) {253if (p->data_type != OSSL_PARAM_UTF8_STRING)254return 0;255ciphername = p->data;256}257}258if (engine == NULL) {259if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE))260!= NULL) {261if (p->data_type != OSSL_PARAM_UTF8_STRING)262return 0;263engine = p->data;264}265}266}267268if (mdname != NULL)269*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,270(char *)mdname, 0);271if (ciphername != NULL)272*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,273(char *)ciphername, 0);274if (properties != NULL)275*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,276(char *)properties, 0);277278#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)279if (engine != NULL)280*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_ENGINE,281(char *) engine, 0);282#endif283284if (key != NULL)285*mp++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,286(unsigned char *)key,287keylen);288289*mp = OSSL_PARAM_construct_end();290291return EVP_MAC_CTX_set_params(macctx, mac_params);292293}294295int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,296const OSSL_PARAM params[],297const char *macname,298const char *ciphername,299const char *mdname,300OSSL_LIB_CTX *libctx)301{302const OSSL_PARAM *p;303const char *properties = NULL;304305if (macname == NULL306&& (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) {307if (p->data_type != OSSL_PARAM_UTF8_STRING)308return 0;309macname = p->data;310}311if ((p = OSSL_PARAM_locate_const(params,312OSSL_ALG_PARAM_PROPERTIES)) != NULL) {313if (p->data_type != OSSL_PARAM_UTF8_STRING)314return 0;315properties = p->data;316}317318/* If we got a new mac name, we make a new EVP_MAC_CTX */319if (macname != NULL) {320EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties);321322EVP_MAC_CTX_free(*macctx);323*macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac);324/* The context holds on to the MAC */325EVP_MAC_free(mac);326if (*macctx == NULL)327return 0;328}329330/*331* If there is no MAC yet (and therefore, no MAC context), we ignore332* all other parameters.333*/334if (*macctx == NULL)335return 1;336337if (ossl_prov_set_macctx(*macctx, params, ciphername, mdname, NULL,338properties, NULL, 0))339return 1;340341EVP_MAC_CTX_free(*macctx);342*macctx = NULL;343return 0;344}345346void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in,347OSSL_ALGORITHM *out)348{349int i, j;350351if (out[0].algorithm_names == NULL) {352for (i = j = 0; in[i].alg.algorithm_names != NULL; ++i) {353if (in[i].capable == NULL || in[i].capable())354out[j++] = in[i].alg;355}356out[j++] = in[i].alg;357}358}359360/* Duplicate a lump of memory safely */361int ossl_prov_memdup(const void *src, size_t src_len,362unsigned char **dest, size_t *dest_len)363{364if (src != NULL) {365if ((*dest = OPENSSL_memdup(src, src_len)) == NULL)366return 0;367*dest_len = src_len;368} else {369*dest = NULL;370*dest_len = 0;371}372return 1;373}374375376