From 776796e81895fc66994a90bb62da4c7f50d34368 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Tue, 4 Jun 2019 18:00:04 +0200 Subject: [PATCH] Adapt diverse code to provider based MACs. CRMF, SSKDF, TLS1_PRF and SIV are affected by this. This also forces the need to check MAC names, which leads to storing the names in the created methods, which affects all EVP APIs, not just EVP_MAC. We will want that kind of information anyway (for example for 'openssl list')... Consequently, EVP_MAC_name() is re-implemented. Reviewed-by: Matt Caswell Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/8877) --- crypto/crmf/crmf_pbm.c | 30 +++++--- crypto/include/internal/modes_int.h | 1 + crypto/kdf/sskdf.c | 106 ++++++++++++++++++---------- crypto/kdf/tls1_prf.c | 32 ++++++--- crypto/modes/siv128.c | 32 ++++++--- 5 files changed, 140 insertions(+), 61 deletions(-) diff --git a/crypto/crmf/crmf_pbm.c b/crypto/crmf/crmf_pbm.c index 7b29166610..40c12dd32a 100644 --- a/crypto/crmf/crmf_pbm.c +++ b/crypto/crmf/crmf_pbm.c @@ -12,6 +12,8 @@ */ +#include + #include #include @@ -22,6 +24,8 @@ #include #include #include +#include +#include /*- * creates and initializes OSSL_CRMF_PBMPARAMETER (section 4.4) @@ -120,9 +124,10 @@ OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(size_t slen, int owfnid, int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp, const unsigned char *msg, size_t msglen, const unsigned char *sec, size_t seclen, - unsigned char **mac, size_t *maclen) + unsigned char **out, size_t *outlen) { int mac_nid, hmac_md_nid = NID_undef; + const char *mdname = NULL; const EVP_MD *m = NULL; EVP_MD_CTX *ctx = NULL; unsigned char basekey[EVP_MAX_MD_SIZE]; @@ -130,9 +135,12 @@ int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp, int64_t iterations; unsigned char *mac_res = 0; int ok = 0; + EVP_MAC *mac = NULL; EVP_MAC_CTX *mctx = NULL; + OSSL_PARAM macparams[3] = + { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; - if (mac == NULL || pbmp == NULL || pbmp->mac == NULL + if (out == NULL || pbmp == NULL || pbmp->mac == NULL || pbmp->mac->algorithm == NULL || msg == NULL || sec == NULL) { CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_NULL_ARGUMENT); goto err; @@ -193,17 +201,22 @@ int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp, mac_nid = OBJ_obj2nid(pbmp->mac->algorithm); if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, mac_nid, NULL, &hmac_md_nid, NULL) - || ((m = EVP_get_digestbynid(hmac_md_nid)) == NULL)) { + || ((mdname = OBJ_nid2sn(hmac_md_nid)) == NULL)) { CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_UNSUPPORTED_ALGORITHM); goto err; } - if ((mctx = EVP_MAC_CTX_new(EVP_get_macbyname("HMAC"))) == NULL - || EVP_MAC_ctrl(mctx, EVP_MAC_CTRL_SET_MD, m) <= 0 - || EVP_MAC_ctrl(mctx, EVP_MAC_CTRL_SET_KEY, basekey, bklen) <= 0 + macparams[0] = + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM, + (char *)mdname, strlen(mdname) + 1); + macparams[1] = + OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, basekey, bklen); + if ((mac = EVP_MAC_fetch(NULL, "HMAC", NULL)) == NULL + || (mctx = EVP_MAC_CTX_new(mac)) == NULL + || !EVP_MAC_CTX_set_params(mctx, macparams) || !EVP_MAC_init(mctx) || !EVP_MAC_update(mctx, msg, msglen) - || !EVP_MAC_final(mctx, mac_res, maclen)) + || !EVP_MAC_final(mctx, mac_res, outlen, EVP_MAX_MD_SIZE)) goto err; ok = 1; @@ -212,10 +225,11 @@ int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp, /* cleanup */ OPENSSL_cleanse(basekey, bklen); EVP_MAC_CTX_free(mctx); + EVP_MAC_free(mac); EVP_MD_CTX_free(ctx); if (ok == 1) { - *mac = mac_res; + *out = mac_res; return 1; } diff --git a/crypto/include/internal/modes_int.h b/crypto/include/internal/modes_int.h index 5230f08966..08e4ffae74 100644 --- a/crypto/include/internal/modes_int.h +++ b/crypto/include/internal/modes_int.h @@ -211,6 +211,7 @@ struct siv128_context { SIV_BLOCK d; SIV_BLOCK tag; EVP_CIPHER_CTX *cipher_ctx; + EVP_MAC *mac; EVP_MAC_CTX *mac_ctx_init; int final_ret; int crypto_ok; diff --git a/crypto/kdf/sskdf.c b/crypto/kdf/sskdf.c index 62372a50ed..7e5a68be5e 100644 --- a/crypto/kdf/sskdf.c +++ b/crypto/kdf/sskdf.c @@ -40,12 +40,14 @@ #include #include #include +#include +#include #include "internal/cryptlib.h" #include "internal/evp_int.h" #include "kdf_local.h" struct evp_kdf_impl_st { - const EVP_MAC *mac; /* H(x) = HMAC_hash OR H(x) = KMAC */ + EVP_MAC *mac; /* H(x) = HMAC_hash OR H(x) = KMAC */ const EVP_MD *md; /* H(x) = hash OR when H(x) = HMAC_hash */ unsigned char *secret; size_t secret_len; @@ -141,11 +143,17 @@ static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom, size_t custom_len, size_t kmac_out_len, size_t derived_key_len, unsigned char **out) { + OSSL_PARAM params[2]; + /* Only KMAC has custom data - so return if not KMAC */ if (custom == NULL) return 1; - if (EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_CUSTOM, custom, custom_len) <= 0) + params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM, + (void *)custom, custom_len); + params[1] = OSSL_PARAM_construct_end(); + + if (!EVP_MAC_CTX_set_params(ctx, params)) return 0; /* By default only do one iteration if kmac_out_len is not specified */ @@ -160,7 +168,10 @@ static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom, || kmac_out_len == 64)) return 0; - if (EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_SIZE, kmac_out_len) <= 0) + params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_OUTLEN, + &kmac_out_len); + + if (EVP_MAC_CTX_set_params(ctx, params) <= 0) return 0; /* @@ -181,7 +192,7 @@ static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom, * H(x) = HMAC-hash(salt, x) OR * H(x) = KMAC#(salt, x, outbits, CustomString='KDF') */ -static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md, +static int SSKDF_mac_kdm(EVP_MAC *kdf_mac, const EVP_MD *hmac_md, const unsigned char *kmac_custom, size_t kmac_custom_len, size_t kmac_out_len, const unsigned char *salt, size_t salt_len, @@ -196,6 +207,8 @@ static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md, unsigned char *out = derived_key; EVP_MAC_CTX *ctx = NULL, *ctx_init = NULL; unsigned char *mac = mac_buf, *kmac_buffer = NULL; + OSSL_PARAM params[3]; + size_t params_n = 0; if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN || derived_key_len > SSKDF_MAX_INLEN @@ -205,11 +218,20 @@ static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md, ctx_init = EVP_MAC_CTX_new(kdf_mac); if (ctx_init == NULL) goto end; - if (hmac_md != NULL && - EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_MD, hmac_md) <= 0) - goto end; - if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_KEY, salt, salt_len) <= 0) + if (hmac_md != NULL) { + const char *mdname = EVP_MD_name(hmac_md); + params[params_n++] = + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM, + (char *)mdname, + strlen(mdname) + 1); + } + params[params_n++] = + OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, (void *)salt, + salt_len); + params[params_n] = OSSL_PARAM_construct_end(); + + if (!EVP_MAC_CTX_set_params(ctx_init, params)) goto end; if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len, @@ -239,14 +261,14 @@ static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md, && EVP_MAC_update(ctx, info, info_len))) goto end; if (len >= out_len) { - if (!EVP_MAC_final(ctx, out, NULL)) + if (!EVP_MAC_final(ctx, out, NULL, len)) goto end; out += out_len; len -= out_len; if (len == 0) break; } else { - if (!EVP_MAC_final(ctx, mac, NULL)) + if (!EVP_MAC_final(ctx, mac, NULL, len)) goto end; memcpy(out, mac, len); break; @@ -280,6 +302,10 @@ static void sskdf_reset(EVP_KDF_IMPL *impl) OPENSSL_clear_free(impl->secret, impl->secret_len); OPENSSL_clear_free(impl->info, impl->info_len); OPENSSL_clear_free(impl->salt, impl->salt_len); + EVP_MAC_free(impl->mac); +#if 0 /* TODO(3.0) When we switch to fetched MDs */ + EVP_MD_meth_free(impl->md); +#endif memset(impl, 0, sizeof(*impl)); } @@ -311,7 +337,6 @@ static int sskdf_set_buffer(va_list args, unsigned char **out, size_t *out_len) static int sskdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args) { const EVP_MD *md; - const EVP_MAC *mac; switch (cmd) { case EVP_KDF_CTRL_SET_KEY: @@ -325,17 +350,34 @@ static int sskdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args) if (md == NULL) return 0; +#if 0 /* TODO(3.0) When we switch to fetched MDs */ + EVP_MD_meth_free(impl->md); +#endif impl->md = md; return 1; case EVP_KDF_CTRL_SET_MAC: - mac = va_arg(args, const EVP_MAC *); - if (mac == NULL) - return 0; + { + const char *name; + EVP_MAC *mac; - impl->mac = mac; - return 1; + name = va_arg(args, const char *); + if (name == NULL) + return 0; + + EVP_MAC_free(impl->mac); + impl->mac = NULL; + /* + * TODO(3.0) add support for OPENSSL_CTX and properties in KDFs + */ + mac = EVP_MAC_fetch(NULL, name, NULL); + if (mac == NULL) + return 0; + + impl->mac = mac; + return 1; + } case EVP_KDF_CTRL_SET_SALT: return sskdf_set_buffer(args, &impl->salt, &impl->salt_len); @@ -348,20 +390,6 @@ static int sskdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args) } } -/* Pass a mac to a ctrl */ -static int sskdf_mac2ctrl(EVP_KDF_IMPL *impl, - int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args), - int cmd, const char *mac_name) -{ - const EVP_MAC *mac; - - if (mac_name == NULL || (mac = EVP_get_macbyname(mac_name)) == NULL) { - KDFerr(KDF_F_SSKDF_MAC2CTRL, KDF_R_INVALID_MAC_TYPE); - return 0; - } - return call_ctrl(ctrl, impl, cmd, mac); -} - static int sskdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type, const char *value) { @@ -385,7 +413,7 @@ static int sskdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type, return kdf_md2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MD, value); if (strcmp(type, "mac") == 0) - return sskdf_mac2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MAC, value); + return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MAC, value); if (strcmp(type, "salt") == 0) return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SALT, value); @@ -430,11 +458,16 @@ static int sskdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen) int ret; const unsigned char *custom = NULL; size_t custom_len = 0; - int nid; + const char *macname; int default_salt_len; - nid = EVP_MAC_nid(impl->mac); - if (nid == EVP_MAC_HMAC) { + /* + * TODO(3.0) investigate the necessity to have all these controls. + * Why does KMAC require a salt length that's shorter than the MD + * block size? + */ + macname = EVP_MAC_name(impl->mac); + if (strcmp(macname, "HMAC") == 0) { /* H(x) = HMAC(x, salt, hash) */ if (impl->md == NULL) { KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST); @@ -443,11 +476,12 @@ static int sskdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen) default_salt_len = EVP_MD_block_size(impl->md); if (default_salt_len <= 0) return 0; - } else if (nid == EVP_MAC_KMAC128 || nid == EVP_MAC_KMAC256) { + } else if (strcmp(macname, "KMAC128") == 0 + || strcmp(macname, "KMAC256") == 0) { /* H(x) = KMACzzz(x, salt, custom) */ custom = kmac_custom_str; custom_len = sizeof(kmac_custom_str); - if (nid == EVP_MAC_KMAC128) + if (strcmp(macname, "KMAC128") == 0) default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE; else default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE; diff --git a/crypto/kdf/tls1_prf.c b/crypto/kdf/tls1_prf.c index b14ae6fee1..1df201dd3f 100644 --- a/crypto/kdf/tls1_prf.c +++ b/crypto/kdf/tls1_prf.c @@ -51,6 +51,8 @@ #include "internal/cryptlib.h" #include #include +#include +#include #include "internal/evp_int.h" #include "kdf_local.h" @@ -232,19 +234,30 @@ static int tls1_prf_P_hash(const EVP_MD *md, unsigned char *out, size_t olen) { size_t chunk; + EVP_MAC *mac = NULL; EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL, *ctx_init = NULL; unsigned char Ai[EVP_MAX_MD_SIZE]; size_t Ai_len; int ret = 0; + OSSL_PARAM params[4]; + int mac_flags; + const char *mdname = EVP_MD_name(md); - ctx_init = EVP_MAC_CTX_new_id(EVP_MAC_HMAC); + mac = EVP_MAC_fetch(NULL, "HMAC", NULL); /* Implicit fetch */ + ctx_init = EVP_MAC_CTX_new(mac); if (ctx_init == NULL) goto err; - if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_FLAGS, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW) != 1) - goto err; - if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_MD, md) != 1) - goto err; - if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_KEY, sec, sec_len) != 1) + + /* TODO(3.0) rethink "flags", also see hmac.c in providers */ + mac_flags = EVP_MD_CTX_FLAG_NON_FIPS_ALLOW; + params[0] = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_FLAGS, &mac_flags); + params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM, + (char *)mdname, + strlen(mdname) + 1); + params[2] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + (void *)sec, sec_len); + params[3] = OSSL_PARAM_construct_end(); + if (!EVP_MAC_CTX_set_params(ctx_init, params)) goto err; if (!EVP_MAC_init(ctx_init)) goto err; @@ -260,7 +273,7 @@ static int tls1_prf_P_hash(const EVP_MD *md, for (;;) { /* calc: A(i) = HMAC_(secret, A(i-1)) */ - if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len)) + if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai))) goto err; EVP_MAC_CTX_free(ctx_Ai); ctx_Ai = NULL; @@ -281,12 +294,12 @@ static int tls1_prf_P_hash(const EVP_MD *md, goto err; if (olen <= chunk) { /* last chunk - use Ai as temp bounce buffer */ - if (!EVP_MAC_final(ctx, Ai, &Ai_len)) + if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai))) goto err; memcpy(out, Ai, olen); break; } - if (!EVP_MAC_final(ctx, out, NULL)) + if (!EVP_MAC_final(ctx, out, NULL, olen)) goto err; EVP_MAC_CTX_free(ctx); ctx = NULL; @@ -298,6 +311,7 @@ static int tls1_prf_P_hash(const EVP_MD *md, EVP_MAC_CTX_free(ctx); EVP_MAC_CTX_free(ctx_Ai); EVP_MAC_CTX_free(ctx_init); + EVP_MAC_free(mac); OPENSSL_cleanse(Ai, sizeof(Ai)); return ret; } diff --git a/crypto/modes/siv128.c b/crypto/modes/siv128.c index 359252f196..04abea25c1 100644 --- a/crypto/modes/siv128.c +++ b/crypto/modes/siv128.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "internal/modes_int.h" #include "internal/siv_int.h" @@ -117,7 +119,7 @@ __owur static ossl_inline int siv128_do_s2v_p(SIV128_CONTEXT *ctx, SIV_BLOCK *ou if (!EVP_MAC_update(mac_ctx, t.byte, SIV_LEN)) goto err; } - if (!EVP_MAC_final(mac_ctx, out->byte, &out_len) + if (!EVP_MAC_final(mac_ctx, out->byte, &out_len, sizeof(out->byte)) || out_len != SIV_LEN) goto err; @@ -167,6 +169,15 @@ int CRYPTO_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen, static const unsigned char zero[SIV_LEN] = { 0 }; size_t out_len = SIV_LEN; EVP_MAC_CTX *mac_ctx = NULL; + OSSL_PARAM params[3]; + const char *cbc_name = EVP_CIPHER_name(cbc); + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM, + (char *)cbc_name, + strlen(cbc_name) + 1); + params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + (void *)key, klen); + params[2] = OSSL_PARAM_construct_end(); memset(&ctx->d, 0, sizeof(ctx->d)); ctx->cipher_ctx = NULL; @@ -174,16 +185,19 @@ int CRYPTO_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen, if (key == NULL || cbc == NULL || ctr == NULL || (ctx->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL - || (ctx->mac_ctx_init = EVP_MAC_CTX_new_id(EVP_MAC_CMAC)) == NULL - || EVP_MAC_ctrl(ctx->mac_ctx_init, EVP_MAC_CTRL_SET_CIPHER, cbc) <= 0 - || EVP_MAC_ctrl(ctx->mac_ctx_init, EVP_MAC_CTRL_SET_KEY, key, klen) <= 0 + /* TODO(3.0) library context */ + || (ctx->mac = EVP_MAC_fetch(NULL, "CMAC", NULL)) == NULL + || (ctx->mac_ctx_init = EVP_MAC_CTX_new(ctx->mac)) == NULL + || !EVP_MAC_CTX_set_params(ctx->mac_ctx_init, params) || !EVP_EncryptInit_ex(ctx->cipher_ctx, ctr, NULL, key + klen, NULL) || (mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init)) == NULL || !EVP_MAC_update(mac_ctx, zero, sizeof(zero)) - || !EVP_MAC_final(mac_ctx, ctx->d.byte, &out_len)) { + || !EVP_MAC_final(mac_ctx, ctx->d.byte, &out_len, + sizeof(ctx->d.byte))) { EVP_CIPHER_CTX_free(ctx->cipher_ctx); EVP_MAC_CTX_free(ctx->mac_ctx_init); EVP_MAC_CTX_free(mac_ctx); + EVP_MAC_free(ctx->mac); return 0; } EVP_MAC_CTX_free(mac_ctx); @@ -223,10 +237,10 @@ int CRYPTO_siv128_aad(SIV128_CONTEXT *ctx, const unsigned char *aad, siv128_dbl(&ctx->d); - mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init); - if (mac_ctx == NULL + if ((mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init)) == NULL || !EVP_MAC_update(mac_ctx, aad, len) - || !EVP_MAC_final(mac_ctx, mac_out.byte, &out_len) + || !EVP_MAC_final(mac_ctx, mac_out.byte, &out_len, + sizeof(mac_out.byte)) || out_len != SIV_LEN) { EVP_MAC_CTX_free(mac_ctx); return 0; @@ -345,6 +359,8 @@ int CRYPTO_siv128_cleanup(SIV128_CONTEXT *ctx) ctx->cipher_ctx = NULL; EVP_MAC_CTX_free(ctx->mac_ctx_init); ctx->mac_ctx_init = NULL; + EVP_MAC_free(ctx->mac); + ctx->mac = NULL; OPENSSL_cleanse(&ctx->d, sizeof(ctx->d)); OPENSSL_cleanse(&ctx->tag, sizeof(ctx->tag)); ctx->final_ret = -1; -- 2.40.0