summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorPauli <pauli@openssl.org>2021-08-02 16:16:35 +1000
committerPauli <pauli@openssl.org>2021-08-05 15:43:59 +1000
commitf7d998a206383b6bab3fad32b28e58d3786fe08a (patch)
tree68dc70d58777158e20d6c9549c54e8e461b87773 /ssl
parent2cdf7c6a3324f0477d34b2906632e863941d8d6b (diff)
tls/prov: move the TLS 1.3 KDF code to providers
This function needs to be power up tested as part of the FIPS validation and thus it needs to be inside the provider boundary. This is realised by introducing a new KDF "TLS13-KDF" which does the required massaging of parameters but is otherwise functionally equivalent to HKDF. Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/16203)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/tls13_enc.c116
1 files changed, 34 insertions, 82 deletions
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index 91c4248117..7f6133f29c 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -18,8 +18,11 @@
#define TLS13_MAX_LABEL_LEN 249
-/* Always filled with zeros */
-static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
+#ifdef CHARSET_EBCDIC
+static const unsigned char label_prefix[] = { 0x74, 0x6C, 0x73, 0x31, 0x33, 0x20, 0x00 };
+#else
+static const unsigned char label_prefix[] = "tls13 ";
+#endif
/*
* Given a |secret|; a |label| of length |labellen|; and |data| of length
@@ -33,29 +36,14 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
const unsigned char *data, size_t datalen,
unsigned char *out, size_t outlen, int fatal)
{
-#ifdef CHARSET_EBCDIC
- static const unsigned char label_prefix[] = { 0x74, 0x6C, 0x73, 0x31, 0x33, 0x20, 0x00 };
-#else
- static const unsigned char label_prefix[] = "tls13 ";
-#endif
- EVP_KDF *kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_HKDF,
+ EVP_KDF *kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_TLS1_3_KDF,
s->ctx->propq);
EVP_KDF_CTX *kctx;
- OSSL_PARAM params[5], *p = params;
+ OSSL_PARAM params[7], *p = params;
int mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
const char *mdname = EVP_MD_get0_name(md);
int ret;
- size_t hkdflabellen;
size_t hashlen;
- /*
- * 2 bytes for length of derived secret + 1 byte for length of combined
- * prefix and label + bytes for the label itself + 1 byte length of hash
- * + bytes for the hash itself
- */
- unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t)
- + (sizeof(label_prefix) - 1) + TLS13_MAX_LABEL_LEN
- + 1 + EVP_MAX_MD_SIZE];
- WPACKET pkt;
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
@@ -76,37 +64,33 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
return 0;
}
- hashlen = EVP_MD_get_size(md);
-
- if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0)
- || !WPACKET_put_bytes_u16(&pkt, outlen)
- || !WPACKET_start_sub_packet_u8(&pkt)
- || !WPACKET_memcpy(&pkt, label_prefix, sizeof(label_prefix) - 1)
- || !WPACKET_memcpy(&pkt, label, labellen)
- || !WPACKET_close(&pkt)
- || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen)
- || !WPACKET_get_total_written(&pkt, &hkdflabellen)
- || !WPACKET_finish(&pkt)) {
+ if ((ret = EVP_MD_get_size(md)) <= 0) {
EVP_KDF_CTX_free(kctx);
- WPACKET_cleanup(&pkt);
if (fatal)
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
else
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
+ hashlen = (size_t)ret;
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)mdname, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
(unsigned char *)secret, hashlen);
- *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
- hkdflabel, hkdflabellen);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PREFIX,
+ (unsigned char *)label_prefix,
+ sizeof(label_prefix) - 1);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_LABEL,
+ (unsigned char *)label, labellen);
+ if (data != NULL)
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_DATA,
+ (unsigned char *)data,
+ datalen);
*p++ = OSSL_PARAM_construct_end();
ret = EVP_KDF_derive(kctx, out, outlen, params) <= 0;
-
EVP_KDF_CTX_free(kctx);
if (ret != 0) {
@@ -178,12 +162,12 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
size_t insecretlen,
unsigned char *outsecret)
{
- size_t mdlen, prevsecretlen;
+ size_t mdlen;
int mdleni;
int ret;
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
- OSSL_PARAM params[5], *p = params;
+ OSSL_PARAM params[7], *p = params;
int mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
const char *mdname = EVP_MD_get0_name(md);
#ifdef CHARSET_EBCDIC
@@ -191,9 +175,8 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
#else
static const char derived_secret_label[] = "derived";
#endif
- unsigned char preextractsec[EVP_MAX_MD_SIZE];
- kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_HKDF, s->ctx->propq);
+ kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_TLS1_3_KDF, s->ctx->propq);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
if (kctx == NULL) {
@@ -210,51 +193,22 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
}
mdlen = (size_t)mdleni;
- if (insecret == NULL) {
- insecret = default_zeros;
- insecretlen = mdlen;
- }
- if (prevsecret == NULL) {
- prevsecret = default_zeros;
- prevsecretlen = 0;
- } else {
- EVP_MD_CTX *mctx = EVP_MD_CTX_new();
- unsigned char hash[EVP_MAX_MD_SIZE];
-
- /* The pre-extract derive step uses a hash of no messages */
- if (mctx == NULL
- || EVP_DigestInit_ex(mctx, md, NULL) <= 0
- || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- EVP_MD_CTX_free(mctx);
- EVP_KDF_CTX_free(kctx);
- return 0;
- }
- EVP_MD_CTX_free(mctx);
-
- /* Generate the pre-extract secret */
- if (!tls13_hkdf_expand(s, md, prevsecret,
- (unsigned char *)derived_secret_label,
- sizeof(derived_secret_label) - 1, hash, mdlen,
- preextractsec, mdlen, 1)) {
- /* SSLfatal() already called */
- EVP_KDF_CTX_free(kctx);
- return 0;
- }
-
- prevsecret = preextractsec;
- prevsecretlen = mdlen;
- }
-
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)mdname, 0);
- *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
- (unsigned char *)insecret,
- insecretlen);
- *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
- (unsigned char *)prevsecret,
- prevsecretlen);
+ if (insecret != NULL)
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ (unsigned char *)insecret,
+ insecretlen);
+ if (prevsecret != NULL)
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ (unsigned char *)prevsecret, mdlen);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PREFIX,
+ (unsigned char *)label_prefix,
+ sizeof(label_prefix) - 1);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_LABEL,
+ (unsigned char *)derived_secret_label,
+ sizeof(derived_secret_label) - 1);
*p++ = OSSL_PARAM_construct_end();
ret = EVP_KDF_derive(kctx, outsecret, mdlen, params) <= 0;
@@ -263,8 +217,6 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
EVP_KDF_CTX_free(kctx);
- if (prevsecret == preextractsec)
- OPENSSL_cleanse(preextractsec, mdlen);
return ret == 0;
}