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 <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/8877)
*/
+#include <string.h>
+
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/crmf.h>
#include <openssl/err.h>
#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
/*-
* creates and initializes OSSL_CRMF_PBMPARAMETER (section 4.4)
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];
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;
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;
/* 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;
}
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;
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
#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;
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 */
|| 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;
/*
* 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,
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
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,
&& 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;
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));
}
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:
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);
}
}
-/* 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)
{
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);
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);
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;
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
#include "internal/evp_int.h"
#include "kdf_local.h"
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;
for (;;) {
/* calc: A(i) = HMAC_<hash>(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;
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;
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;
}
#include <stdlib.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
#include "internal/modes_int.h"
#include "internal/siv_int.h"
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;
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;
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);
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;
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;