Move the TLSv1.3 KDF into wolfCrypt with the other KDFs.

This commit is contained in:
John Safranek
2021-01-20 16:48:12 -08:00
parent 77e6849786
commit 8ab396cb45
4 changed files with 219 additions and 28 deletions

View File

@ -134,6 +134,18 @@
*/
#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
#if (defined(HAVE_FIPS) && \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 4))) || \
defined(HAVE_SELFTEST)
enum {
/*
MAX_HKDF_LABEL_SZ = OPAQUE16_LEN +
OPAQUE8_LEN + PROTOCOL_LABEL_SZ + MAX_LABEL_SZ +
OPAQUE8_LEN + WC_MAX_DIGEST_SIZE
*/
MAX_TLS13_HKDF_LABEL_SZ = 47 + WC_MAX_DIGEST_SIZE
};
/* Extract data using HMAC, salt and input.
* RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
@ -143,37 +155,35 @@
* saltLen The length of the salt.
* ikm The input keying material.
* ikmLen The length of the input keying material.
* mac The type of digest to use.
* digest The type of digest to use.
* returns 0 on success, otherwise failure.
*/
static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
byte* ikm, int ikmLen, int mac)
static int wc_Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
byte* ikm, int ikmLen, int digest)
{
int ret;
int hash = 0;
int len = 0;
switch (mac) {
switch (digest) {
#ifndef NO_SHA256
case sha256_mac:
hash = WC_SHA256;
case WC_SHA256:
len = WC_SHA256_DIGEST_SIZE;
break;
#endif
#ifdef WOLFSSL_SHA384
case sha384_mac:
hash = WC_SHA384;
case WC_SHA384:
len = WC_SHA384_DIGEST_SIZE;
break;
#endif
#ifdef WOLFSSL_TLS13_SHA512
case sha512_mac:
hash = WC_SHA512;
case WC_SHA512:
len = WC_SHA512_DIGEST_SIZE;
break;
#endif
default:
return BAD_FUNC_ARG;
}
/* When length is 0 then use zeroed data of digest length. */
@ -189,7 +199,7 @@ static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
WOLFSSL_BUFFER(ikm, ikmLen);
#endif
ret = wc_HKDF_Extract(hash, salt, saltLen, ikm, ikmLen, prk);
ret = wc_HKDF_Extract(digest, salt, saltLen, ikm, ikmLen, prk);
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG(" PRK");
@ -199,6 +209,7 @@ static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
return ret;
}
/* Expand data using HMAC, salt and label and info.
* TLS v1.3 defines this function.
*
@ -213,7 +224,7 @@ static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
* digest The type of digest to use.
* returns 0 on success, otherwise failure.
*/
static int HKDF_Expand_Label(byte* okm, word32 okmLen,
static int wc_Tls13_HKDF_Expand_Label(byte* okm, word32 okmLen,
const byte* prk, word32 prkLen,
const byte* protocol, word32 protocolLen,
const byte* label, word32 labelLen,
@ -222,7 +233,7 @@ static int HKDF_Expand_Label(byte* okm, word32 okmLen,
{
int ret = 0;
int idx = 0;
byte data[MAX_HKDF_LABEL_SZ];
byte data[MAX_TLS13_HKDF_LABEL_SZ];
/* Output length. */
data[idx++] = (byte)(okmLen >> 8);
@ -262,6 +273,8 @@ static int HKDF_Expand_Label(byte* okm, word32 okmLen,
return ret;
}
#endif /* HAVE_FIPS */
/* Size of the TLS v1.3 label use when deriving keys. */
#define TLS13_PROTOCOL_LABEL_SZ 6
/* The protocol label for TLS v1.3. */
@ -355,7 +368,7 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen,
if (outputLen == -1)
outputLen = hashSz;
return HKDF_Expand_Label(output, outputLen, secret, hashSz,
return wc_Tls13_HKDF_Expand_Label(output, outputLen, secret, hashSz,
protocol, protocolLen, label, labelLen,
hash, hashSz, digestAlg);
}
@ -424,11 +437,41 @@ static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen,
if (includeMsgs)
hashOutSz = hashSz;
return HKDF_Expand_Label(output, outputLen, secret, hashSz,
return wc_Tls13_HKDF_Expand_Label(output, outputLen, secret, hashSz,
protocol, protocolLen, label, labelLen,
hash, hashOutSz, digestAlg);
}
/* Convert TLS mac ID to a hash algorithm ID
*
* mac Mac ID to convert
* returns hash ID on success, or the NONE type.
*/
static WC_INLINE int mac2hash(int mac)
{
int hash = WC_HASH_TYPE_NONE;
switch (mac) {
#ifndef NO_SHA256
case sha256_mac:
hash = WC_SHA256;
break;
#endif
#ifdef WOLFSSL_SHA384
case sha384_mac:
hash = WC_SHA384;
break;
#endif
#ifdef WOLFSSL_TLS13_SHA512
case sha512_mac:
hash = WC_SHA512;
break;
#endif
}
return hash;
}
#ifndef NO_PSK
/* The length of the binder key label. */
#define BINDER_KEY_LABEL_SZ 10
@ -904,12 +947,12 @@ int DeriveEarlySecret(WOLFSSL* ssl)
return BAD_FUNC_ARG;
}
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
return wc_Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
ssl->arrays->psk_key, ssl->arrays->psk_keySz,
ssl->specs.mac_algorithm);
mac2hash(ssl->specs.mac_algorithm));
#else
return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
return wc_Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0,
ssl->arrays->masterSecret, 0, mac2hash(ssl->specs.mac_algorithm));
#endif
}
@ -937,10 +980,10 @@ int DeriveHandshakeSecret(WOLFSSL* ssl)
if (ret != 0)
return ret;
return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret,
return wc_Tls13_HKDF_Extract(ssl->arrays->preMasterSecret,
key, ssl->specs.hash_size,
ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
ssl->specs.mac_algorithm);
mac2hash(ssl->specs.mac_algorithm));
}
/* Derive the master secret using HKDF Extract.
@ -961,9 +1004,9 @@ int DeriveMasterSecret(WOLFSSL* ssl)
if (ret != 0)
return ret;
ret = Tls13_HKDF_Extract(ssl->arrays->masterSecret,
ret = wc_Tls13_HKDF_Extract(ssl->arrays->masterSecret,
key, ssl->specs.hash_size,
ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm);
ssl->arrays->masterSecret, 0, mac2hash(ssl->specs.mac_algorithm));
#ifdef HAVE_KEYING_MATERIAL
if (ret != 0)
@ -1021,7 +1064,7 @@ int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret)
return BAD_FUNC_ARG;
}
return HKDF_Expand_Label(secret, ssl->specs.hash_size,
return wc_Tls13_HKDF_Expand_Label(secret, ssl->specs.hash_size,
ssl->session.masterSecret, ssl->specs.hash_size,
protocol, protocolLen, resumptionLabel,
RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg);

View File

@ -1597,6 +1597,133 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
return wc_HKDF_Expand(type, prk, hashSz, info, infoSz, out, outSz);
}
#if !defined(HAVE_FIPS) || \
defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 4)
/* Extract data using HMAC, salt and input.
* RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
*
* prk The generated pseudorandom key.
* salt The salt.
* saltLen The length of the salt.
* ikm The input keying material.
* ikmLen The length of the input keying material.
* digest The type of digest to use.
* returns 0 on success, otherwise failure.
*/
int wc_Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
byte* ikm, int ikmLen, int digest)
{
int ret;
int len = 0;
switch (digest) {
#ifndef NO_SHA256
case WC_SHA256:
len = WC_SHA256_DIGEST_SIZE;
break;
#endif
#ifdef WOLFSSL_SHA384
case WC_SHA384:
len = WC_SHA384_DIGEST_SIZE;
break;
#endif
#ifdef WOLFSSL_TLS13_SHA512
case WC_SHA512:
len = WC_SHA512_DIGEST_SIZE;
break;
#endif
default:
return BAD_FUNC_ARG;
}
/* When length is 0 then use zeroed data of digest length. */
if (ikmLen == 0) {
ikmLen = len;
XMEMSET(ikm, 0, len);
}
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG(" Salt");
WOLFSSL_BUFFER(salt, saltLen);
WOLFSSL_MSG(" IKM");
WOLFSSL_BUFFER(ikm, ikmLen);
#endif
ret = wc_HKDF_Extract(digest, salt, saltLen, ikm, ikmLen, prk);
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG(" PRK");
WOLFSSL_BUFFER(prk, len);
#endif
return ret;
}
/* Expand data using HMAC, salt and label and info.
* TLS v1.3 defines this function.
*
* okm The generated pseudorandom key - output key material.
* okmLen The length of generated pseudorandom key -
* output key material.
* prk The salt - pseudo-random key.
* prkLen The length of the salt - pseudo-random key.
* protocol The TLS protocol label.
* protocolLen The length of the TLS protocol label.
* info The information to expand.
* infoLen The length of the information.
* digest The type of digest to use.
* returns 0 on success, otherwise failure.
*/
int wc_Tls13_HKDF_Expand_Label(byte* okm, word32 okmLen,
const byte* prk, word32 prkLen,
const byte* protocol, word32 protocolLen,
const byte* label, word32 labelLen,
const byte* info, word32 infoLen,
int digest)
{
int ret = 0;
int idx = 0;
byte data[MAX_TLS13_HKDF_LABEL_SZ];
/* Output length. */
data[idx++] = (byte)(okmLen >> 8);
data[idx++] = (byte)okmLen;
/* Length of protocol | label. */
data[idx++] = (byte)(protocolLen + labelLen);
/* Protocol */
XMEMCPY(&data[idx], protocol, protocolLen);
idx += protocolLen;
/* Label */
XMEMCPY(&data[idx], label, labelLen);
idx += labelLen;
/* Length of hash of messages */
data[idx++] = (byte)infoLen;
/* Hash of messages */
XMEMCPY(&data[idx], info, infoLen);
idx += infoLen;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG(" PRK");
WOLFSSL_BUFFER(prk, prkLen);
WOLFSSL_MSG(" Info");
WOLFSSL_BUFFER(data, idx);
#endif
ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG(" OKM");
WOLFSSL_BUFFER(okm, okmLen);
#endif
ForceZero(data, idx);
return ret;
}
#endif /* newer HAVE_FIPS */
#endif /* HAVE_HKDF */

View File

@ -1362,9 +1362,6 @@ enum Misc {
KEY_LABEL_SZ = 13, /* TLS key block expansion sz */
PROTOCOL_LABEL_SZ = 9, /* Length of the protocol label */
MAX_LABEL_SZ = 34, /* Maximum length of a label */
MAX_HKDF_LABEL_SZ = OPAQUE16_LEN +
OPAQUE8_LEN + PROTOCOL_LABEL_SZ + MAX_LABEL_SZ +
OPAQUE8_LEN + WC_MAX_DIGEST_SIZE,
MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */
SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */
TLS_MAX_PAD_SZ = 255, /* Max padding in TLS */

View File

@ -234,6 +234,30 @@ WOLFSSL_API int wc_HKDF(int type, const byte* inKey, word32 inKeySz,
const byte* info, word32 infoSz,
byte* out, word32 outSz);
#if (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 4))) && \
!defined(HAVE_SELFTEST)
enum {
/*
MAX_HKDF_LABEL_SZ = OPAQUE16_LEN +
OPAQUE8_LEN + PROTOCOL_LABEL_SZ + MAX_LABEL_SZ +
OPAQUE8_LEN + WC_MAX_DIGEST_SIZE
*/
MAX_TLS13_HKDF_LABEL_SZ = 47 + WC_MAX_DIGEST_SIZE
};
WOLFSSL_API int wc_Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen,
byte* ikm, int ikmLen, int digest);
WOLFSSL_API int wc_Tls13_HKDF_Expand_Label(byte* okm, word32 okmLen,
const byte* prk, word32 prkLen,
const byte* protocol, word32 protocolLen,
const byte* label, word32 labelLen,
const byte* info, word32 infoLen,
int digest);
#endif /* HAVE_FIPS */
#endif /* HAVE_HKDF */
#ifdef WOLFSSL_WOLFSSH