summaryrefslogtreecommitdiffstats
path: root/crypto/kdf
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2019-06-04 18:00:04 +0200
committerRichard Levitte <levitte@openssl.org>2019-08-15 22:12:25 +0200
commit776796e81895fc66994a90bb62da4c7f50d34368 (patch)
tree9f55862e592aa77676f81730432f21fb070fb989 /crypto/kdf
parentd747fb2ec5ee964e8367e7baec8d499d4832def6 (diff)
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 <matt@openssl.org> Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/8877)
Diffstat (limited to 'crypto/kdf')
-rw-r--r--crypto/kdf/sskdf.c106
-rw-r--r--crypto/kdf/tls1_prf.c32
2 files changed, 93 insertions, 45 deletions
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 <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;
@@ -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 <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"
@@ -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_<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;
@@ -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;
}