Path: blob/main/crypto/openssl/providers/common/provider_util.c
105687 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))245!= NULL) {246if (p->data_type != OSSL_PARAM_UTF8_STRING)247return 0;248mdname = p->data;249}250}251if (ciphername == NULL) {252if ((p = OSSL_PARAM_locate_const(params,253OSSL_ALG_PARAM_CIPHER))254!= NULL) {255if (p->data_type != OSSL_PARAM_UTF8_STRING)256return 0;257ciphername = p->data;258}259}260if (engine == NULL) {261if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE))262!= NULL) {263if (p->data_type != OSSL_PARAM_UTF8_STRING)264return 0;265engine = p->data;266}267}268}269270if (mdname != NULL)271*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,272(char *)mdname, 0);273if (ciphername != NULL)274*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,275(char *)ciphername, 0);276if (properties != NULL)277*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,278(char *)properties, 0);279280#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)281if (engine != NULL)282*mp++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_ENGINE,283(char *)engine, 0);284#endif285286if (key != NULL)287*mp++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,288(unsigned char *)key,289keylen);290291*mp = OSSL_PARAM_construct_end();292293return EVP_MAC_CTX_set_params(macctx, mac_params);294}295296int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,297const OSSL_PARAM params[],298const char *macname,299const char *ciphername,300const char *mdname,301OSSL_LIB_CTX *libctx)302{303const OSSL_PARAM *p;304const char *properties = NULL;305306if (macname == NULL307&& (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) {308if (p->data_type != OSSL_PARAM_UTF8_STRING)309return 0;310macname = p->data;311}312if ((p = OSSL_PARAM_locate_const(params,313OSSL_ALG_PARAM_PROPERTIES))314!= NULL) {315if (p->data_type != OSSL_PARAM_UTF8_STRING)316return 0;317properties = p->data;318}319320/* If we got a new mac name, we make a new EVP_MAC_CTX */321if (macname != NULL) {322EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties);323324EVP_MAC_CTX_free(*macctx);325*macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac);326/* The context holds on to the MAC */327EVP_MAC_free(mac);328if (*macctx == NULL)329return 0;330}331332/*333* If there is no MAC yet (and therefore, no MAC context), we ignore334* all other parameters.335*/336if (*macctx == NULL)337return 1;338339if (ossl_prov_set_macctx(*macctx, params, ciphername, mdname, NULL,340properties, NULL, 0))341return 1;342343EVP_MAC_CTX_free(*macctx);344*macctx = NULL;345return 0;346}347348void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in,349OSSL_ALGORITHM *out)350{351int i, j;352353if (out[0].algorithm_names == NULL) {354for (i = j = 0; in[i].alg.algorithm_names != NULL; ++i) {355if (in[i].capable == NULL || in[i].capable())356out[j++] = in[i].alg;357}358out[j++] = in[i].alg;359}360}361362/* Duplicate a lump of memory safely */363int ossl_prov_memdup(const void *src, size_t src_len,364unsigned char **dest, size_t *dest_len)365{366if (src != NULL) {367if ((*dest = OPENSSL_memdup(src, src_len)) == NULL)368return 0;369*dest_len = src_len;370} else {371*dest = NULL;372*dest_len = 0;373}374return 1;375}376377378