From 4e8b8e47c85a45d1bda3241d7b2852d82db2a255 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Thu, 19 Sep 2019 11:47:46 +0200 Subject: [PATCH] Refactor TLS-PRF's kdf_tls1_prf_mkmacctx() to a provider utility ossl_prov_macctx_load_from_params() creates a EVP_MAC_CTX *, or sets new common parameters for an existing one. Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/9946) --- include/openssl/core_names.h | 5 +- .../common/include/internal/provider_util.h | 24 +++++ providers/common/kdfs/tls1_prf.c | 62 +++---------- providers/common/provider_util.c | 88 +++++++++++++++++++ 4 files changed, 127 insertions(+), 52 deletions(-) diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index e1bc43d8db..ad4cf50bb5 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -47,6 +47,7 @@ extern "C" { */ #define OSSL_ALG_PARAM_DIGEST "digest" /* utf8_string */ #define OSSL_ALG_PARAM_CIPHER "cipher" /* utf8_string */ +#define OSSL_ALG_PARAM_MAC "mac" /* utf8_string */ #define OSSL_ALG_PARAM_ENGINE "engine" /* utf8_string */ #define OSSL_ALG_PARAM_PROPERTIES "properties"/* utf8_string */ @@ -108,8 +109,8 @@ extern "C" { #define OSSL_KDF_PARAM_KEY "key" /* octet string */ #define OSSL_KDF_PARAM_SALT "salt" /* octet string */ #define OSSL_KDF_PARAM_PASSWORD "pass" /* octet string */ -#define OSSL_KDF_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST /* utf8 string */ -#define OSSL_KDF_PARAM_MAC "mac" /* utf8 string */ +#define OSSL_KDF_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST /* utf8 string */ +#define OSSL_KDF_PARAM_MAC OSSL_ALG_PARAM_MAC /* utf8 string */ #define OSSL_KDF_PARAM_MAC_SIZE "maclen" /* size_t */ #define OSSL_KDF_PARAM_ENGINE OSSL_ALG_PARAM_ENGINE /* utf8 string */ #define OSSL_KDF_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES /* utf8 string */ diff --git a/providers/common/include/internal/provider_util.h b/providers/common/include/internal/provider_util.h index 9fe21c5ef6..ad7e72293b 100644 --- a/providers/common/include/internal/provider_util.h +++ b/providers/common/include/internal/provider_util.h @@ -85,3 +85,27 @@ int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src); const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd); ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd); const char *ossl_prov_digest_name(const PROV_DIGEST *pd); + +/* MAC functions */ +/* + * Load an EVP_MAC_CTX* from the specified parameters with the specified + * library context. + * The params "mac" and "properties" are used to determine the implementation + * used, and the parameters "digest", "cipher", "engine" and "properties" are + * passed to the MAC via the created MAC context if they are given. + * If there is already a created MAC context, it will be replaced if the "mac" + * parameter is found, otherwise it will simply be used as is, and passed the + * parameters to pilfer as it sees fit. + * + * As an option, a MAC name may be explicitly given, and if it is, the "mac" + * parameter will be ignored. + * Similarly, as an option, a cipher name or a digest name may be explicitly + * given, and if any of them is, the "digest" and "cipher" parameters are + * ignored. + */ +int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx, + const OSSL_PARAM params[], + const char *macname, + const char *ciphername, + const char *mdname, + OPENSSL_CTX *ctx); diff --git a/providers/common/kdfs/tls1_prf.c b/providers/common/kdfs/tls1_prf.c index 0acdcdf3b8..3053b756dc 100644 --- a/providers/common/kdfs/tls1_prf.c +++ b/providers/common/kdfs/tls1_prf.c @@ -145,51 +145,6 @@ static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, key, keylen); } -static EVP_MAC_CTX *kdf_tls1_prf_mkmacctx(OPENSSL_CTX *libctx, - const char *mdname, - const OSSL_PARAM params[]) -{ - const OSSL_PARAM *p; - OSSL_PARAM mac_params[5], *mp = mac_params; - const char *properties = NULL; - /* TODO(3.0) rethink "flags", also see hmac.c in providers */ - int mac_flags = EVP_MD_CTX_FLAG_NON_FIPS_ALLOW; - EVP_MAC_CTX *macctx = NULL; - - *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, - (char *)mdname, 0); -#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ENGINE)) != NULL) - *mp++ = *p; -#endif - if ((p = OSSL_PARAM_locate_const(params, - OSSL_KDF_PARAM_PROPERTIES)) != NULL) { - properties = p->data; - *mp++ = *p; - } - *mp++ = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_FLAGS, &mac_flags); - *mp = OSSL_PARAM_construct_end(); - - /* Implicit fetch */ - { - EVP_MAC *mac = EVP_MAC_fetch(libctx, OSSL_MAC_NAME_HMAC, properties); - - macctx = EVP_MAC_CTX_new(mac); - /* The context holds on to the MAC */ - EVP_MAC_free(mac); - if (macctx == NULL) - goto err; - } - - if (EVP_MAC_CTX_set_params(macctx, mac_params)) - goto done; - err: - EVP_MAC_CTX_free(macctx); - macctx = NULL; - done: - return macctx; -} - static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { const OSSL_PARAM *p; @@ -197,13 +152,20 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) { - EVP_MAC_CTX_free(ctx->P_hash); - EVP_MAC_CTX_free(ctx->P_sha1); if (strcasecmp(p->data, SN_md5_sha1) == 0) { - ctx->P_hash = kdf_tls1_prf_mkmacctx(libctx, SN_md5, params); - ctx->P_sha1 = kdf_tls1_prf_mkmacctx(libctx, SN_sha1, params); + if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params, + OSSL_MAC_NAME_HMAC, + NULL, SN_md5, libctx) + || !ossl_prov_macctx_load_from_params(&ctx->P_sha1, params, + OSSL_MAC_NAME_HMAC, + NULL, SN_sha1, libctx)) + return 0; } else { - ctx->P_hash = kdf_tls1_prf_mkmacctx(libctx, p->data, params); + EVP_MAC_CTX_free(ctx->P_sha1); + if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params, + OSSL_MAC_NAME_HMAC, + NULL, NULL, libctx)) + return 0; } } diff --git a/providers/common/provider_util.c b/providers/common/provider_util.c index 199544730a..4056878498 100644 --- a/providers/common/provider_util.c +++ b/providers/common/provider_util.c @@ -165,3 +165,91 @@ const char *ossl_prov_digest_name(const PROV_DIGEST *pd) { return pd->name; } + +int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx, + const OSSL_PARAM params[], + const char *macname, + const char *ciphername, + const char *mdname, + OPENSSL_CTX *libctx) +{ + const OSSL_PARAM *p; + OSSL_PARAM mac_params[5], *mp = mac_params; + const char *properties = NULL; + + if (macname == NULL + && (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + macname = p->data; + } + if ((p = OSSL_PARAM_locate_const(params, + OSSL_ALG_PARAM_PROPERTIES)) != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + properties = p->data; + } + + /* If we got a new mac name, we make a new EVP_MAC_CTX */ + if (macname != NULL) { + EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties); + + EVP_MAC_CTX_free(*macctx); + *macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac); + /* The context holds on to the MAC */ + EVP_MAC_free(mac); + if (*macctx == NULL) + return 0; + } + + /* + * If there is no MAC yet (and therefore, no MAC context), we ignore + * all other parameters. + */ + if (*macctx == NULL) + return 1; + + if (mdname == NULL) { + if ((p = OSSL_PARAM_locate_const(params, + OSSL_ALG_PARAM_DIGEST)) != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + mdname = p->data; + } + } + if (ciphername == NULL) { + if ((p = OSSL_PARAM_locate_const(params, + OSSL_ALG_PARAM_CIPHER)) != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + ciphername = p->data; + } + } + + if (mdname != NULL) + *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, + (char *)mdname, 0); + if (ciphername != NULL) + *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, + (char *)ciphername, 0); + if (properties != NULL) + *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES, + (char *)properties, 0); + +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) + if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE)) != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE, + p->data, p->data_size); + } +#endif + *mp = OSSL_PARAM_construct_end(); + + if (EVP_MAC_CTX_set_params(*macctx, mac_params)) + return 1; + + EVP_MAC_CTX_free(*macctx); + *macctx = NULL; + return 0; +} -- 2.34.1