Merge pull request #2004 from embhorn/prf_move

Moving PRF to wolfcrypt
This commit is contained in:
toddouska
2019-01-18 08:53:13 -08:00
committed by GitHub
9 changed files with 408 additions and 332 deletions

View File

@ -6738,7 +6738,7 @@ WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short);
of the p_hash function. of the p_hash function.
\param len an unsigned integer that represents the length of \param len an unsigned integer that represents the length of
the msk variable. the msk variable.
\param label a constant char pointer that is copied from in PRF(). \param label a constant char pointer that is copied from in wc_PRF().
_Example_ _Example_
\code \code
@ -6750,9 +6750,7 @@ WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short);
return wolfSSL_make_eap_keys(ssl, msk, len, label); return wolfSSL_make_eap_keys(ssl, msk, len, label);
\endcode \endcode
\sa PRF \sa wc_PRF
\sa doPRF
\sa p_hash
\sa wc_HmacFinal \sa wc_HmacFinal
\sa wc_HmacUpdate \sa wc_HmacUpdate
*/ */
@ -11085,7 +11083,7 @@ WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active,
\ingroup TLS \ingroup TLS
\brief This function copies the values of cr and sr then passes through to \brief This function copies the values of cr and sr then passes through to
PRF (pseudo random function) and returns that value. wc_PRF (pseudo random function) and returns that value.
\return 0 on success \return 0 on success
\return BUFFER_E returned if there will be an error \return BUFFER_E returned if there will be an error
@ -11121,9 +11119,7 @@ WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active,
} }
\endcode \endcode
\sa PRF \sa wc_PRF
\sadoPRF
\sa p_hash
\sa MakeTlsMasterSecret \sa MakeTlsMasterSecret
*/ */
WOLFSSL_API WOLFSSL_API
@ -11143,7 +11139,7 @@ int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, unsigned int msLen,
\return MEMORY_E returned if the allocation of memory failed. \return MEMORY_E returned if the allocation of memory failed.
\param key_data a byte pointer that is allocateded in DeriveTlsKeys \param key_data a byte pointer that is allocateded in DeriveTlsKeys
and passed through to PRF to hold the final hash. and passed through to wc_PRF to hold the final hash.
\param keyLen a word32 type that is derived in DeriveTlsKeys \param keyLen a word32 type that is derived in DeriveTlsKeys
from the WOLFSSL structures specs member. from the WOLFSSL structures specs member.
\param ms a constant pointer type holding the master secret \param ms a constant pointer type holding the master secret
@ -11169,8 +11165,7 @@ int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, unsigned int msLen,
} }
\endcode \endcode
\sa PRF \sa wc_PRF
\sa doPRF
\sa DeriveTlsKeys \sa DeriveTlsKeys
\sa IsAtLeastTLSv1_2 \sa IsAtLeastTLSv1_2
*/ */

View File

@ -15775,6 +15775,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case UNSUPPORTED_EXTENSION: case UNSUPPORTED_EXTENSION:
return "TLS Extension not requested by the client"; return "TLS Extension not requested by the client";
case PRF_MISSING:
return "Pseudo-random function is not enabled";
case KEY_SHARE_ERROR: case KEY_SHARE_ERROR:
return "Key share extension did not contain a valid named group"; return "Key share extension did not contain a valid named group";

369
src/tls.c
View File

@ -108,291 +108,6 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions);
#ifndef WOLFSSL_NO_TLS12 #ifndef WOLFSSL_NO_TLS12
#ifdef WOLFSSL_SHA384
#define P_HASH_MAX_SIZE WC_SHA384_DIGEST_SIZE
#else
#define P_HASH_MAX_SIZE WC_SHA256_DIGEST_SIZE
#endif
/* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */
static int p_hash(byte* result, word32 resLen, const byte* secret,
word32 secLen, const byte* seed, word32 seedLen, int hash,
void* heap, int devId)
{
word32 len = P_HASH_MAX_SIZE;
word32 times;
word32 lastLen;
word32 lastTime;
word32 i;
word32 idx = 0;
int ret = 0;
#ifdef WOLFSSL_SMALL_STACK
byte* previous;
byte* current;
Hmac* hmac;
#else
byte previous[P_HASH_MAX_SIZE]; /* max size */
byte current[P_HASH_MAX_SIZE]; /* max size */
Hmac hmac[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST);
current = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST);
hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
if (previous == NULL || current == NULL || hmac == NULL) {
if (previous) XFREE(previous, heap, DYNAMIC_TYPE_DIGEST);
if (current) XFREE(current, heap, DYNAMIC_TYPE_DIGEST);
if (hmac) XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
return MEMORY_E;
}
#endif
switch (hash) {
#ifndef NO_MD5
case md5_mac:
hash = WC_MD5;
len = WC_MD5_DIGEST_SIZE;
break;
#endif
#ifndef NO_SHA256
case sha256_mac:
hash = WC_SHA256;
len = WC_SHA256_DIGEST_SIZE;
break;
#endif
#ifdef WOLFSSL_SHA384
case sha384_mac:
hash = WC_SHA384;
len = WC_SHA384_DIGEST_SIZE;
break;
#endif
#ifndef NO_SHA
case sha_mac:
default:
hash = WC_SHA;
len = WC_SHA_DIGEST_SIZE;
break;
#endif
}
times = resLen / len;
lastLen = resLen % len;
if (lastLen)
times += 1;
lastTime = times - 1;
ret = wc_HmacInit(hmac, heap, devId);
if (ret == 0) {
ret = wc_HmacSetKey(hmac, hash, secret, secLen);
if (ret == 0)
ret = wc_HmacUpdate(hmac, seed, seedLen); /* A0 = seed */
if (ret == 0)
ret = wc_HmacFinal(hmac, previous); /* A1 */
if (ret == 0) {
for (i = 0; i < times; i++) {
ret = wc_HmacUpdate(hmac, previous, len);
if (ret != 0)
break;
ret = wc_HmacUpdate(hmac, seed, seedLen);
if (ret != 0)
break;
ret = wc_HmacFinal(hmac, current);
if (ret != 0)
break;
if ((i == lastTime) && lastLen)
XMEMCPY(&result[idx], current,
min(lastLen, P_HASH_MAX_SIZE));
else {
XMEMCPY(&result[idx], current, len);
idx += len;
ret = wc_HmacUpdate(hmac, previous, len);
if (ret != 0)
break;
ret = wc_HmacFinal(hmac, previous);
if (ret != 0)
break;
}
}
}
wc_HmacFree(hmac);
}
ForceZero(previous, P_HASH_MAX_SIZE);
ForceZero(current, P_HASH_MAX_SIZE);
ForceZero(hmac, sizeof(Hmac));
#ifdef WOLFSSL_SMALL_STACK
XFREE(previous, heap, DYNAMIC_TYPE_DIGEST);
XFREE(current, heap, DYNAMIC_TYPE_DIGEST);
XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
#endif
return ret;
}
#undef P_HASH_MAX_SIZE
#endif /* !WOLFSSL_NO_TLS12 */
#ifndef NO_OLD_TLS
/* calculate XOR for TLSv1 PRF */
static WC_INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha)
{
word32 i;
for (i = 0; i < digLen; i++)
digest[i] = md5[i] ^ sha[i];
}
/* compute TLSv1 PRF (pseudo random function using HMAC) */
static int doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen,
const byte* label, word32 labLen, const byte* seed,
word32 seedLen, void* heap, int devId)
{
int ret = 0;
word32 half = (secLen + 1) / 2;
#ifdef WOLFSSL_SMALL_STACK
byte* md5_half;
byte* sha_half;
byte* md5_result;
byte* sha_result;
#else
byte md5_half[MAX_PRF_HALF]; /* half is real size */
byte sha_half[MAX_PRF_HALF]; /* half is real size */
byte md5_result[MAX_PRF_DIG]; /* digLen is real size */
byte sha_result[MAX_PRF_DIG]; /* digLen is real size */
#endif
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap);
if (labelSeed == NULL)
return MEMORY_E;
#else
byte labelSeed[MAX_PRF_LABSEED];
#endif
if (half > MAX_PRF_HALF ||
labLen + seedLen > MAX_PRF_LABSEED ||
digLen > MAX_PRF_DIG)
{
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(labelSeed, heap);
#endif
return BUFFER_E;
}
#ifdef WOLFSSL_SMALL_STACK
md5_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST);
sha_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST);
md5_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST);
sha_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST);
if (md5_half == NULL || sha_half == NULL || md5_result == NULL ||
sha_result == NULL) {
if (md5_half) XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST);
if (sha_half) XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST);
if (md5_result) XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST);
if (sha_result) XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST);
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(labelSeed, heap);
#endif
return MEMORY_E;
}
#endif
XMEMSET(md5_result, 0, digLen);
XMEMSET(sha_result, 0, digLen);
XMEMCPY(md5_half, secret, half);
XMEMCPY(sha_half, secret + half - secLen % 2, half);
XMEMCPY(labelSeed, label, labLen);
XMEMCPY(labelSeed + labLen, seed, seedLen);
if ((ret = p_hash(md5_result, digLen, md5_half, half, labelSeed,
labLen + seedLen, md5_mac, heap, devId)) == 0) {
if ((ret = p_hash(sha_result, digLen, sha_half, half, labelSeed,
labLen + seedLen, sha_mac, heap, devId)) == 0) {
get_xor(digest, digLen, md5_result, sha_result);
}
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST);
XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST);
XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST);
XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST);
#endif
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(labelSeed, heap);
#endif
return ret;
}
#endif
#ifndef WOLFSSL_NO_TLS12
/* Wrapper to call straight thru to p_hash in TSL 1.2 cases to remove stack
use */
static int PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
const byte* label, word32 labLen, const byte* seed, word32 seedLen,
int useAtLeastSha256, int hash_type, void* heap, int devId)
{
int ret = 0;
if (useAtLeastSha256) {
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap);
if (labelSeed == NULL)
return MEMORY_E;
#else
byte labelSeed[MAX_PRF_LABSEED];
#endif
if (labLen + seedLen > MAX_PRF_LABSEED)
return BUFFER_E;
XMEMCPY(labelSeed, label, labLen);
XMEMCPY(labelSeed + labLen, seed, seedLen);
/* If a cipher suite wants an algorithm better than sha256, it
* should use better. */
if (hash_type < sha256_mac || hash_type == blake2b_mac)
hash_type = sha256_mac;
ret = p_hash(digest, digLen, secret, secLen, labelSeed,
labLen + seedLen, hash_type, heap, devId);
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(labelSeed, heap);
#endif
}
#ifndef NO_OLD_TLS
else {
ret = doPRF(digest, digLen, secret, secLen, label, labLen, seed,
seedLen, heap, devId);
}
#endif
return ret;
}
#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SHA384
#define HSHASH_SZ WC_SHA384_DIGEST_SIZE #define HSHASH_SZ WC_SHA384_DIGEST_SIZE
#else #else
@ -459,10 +174,19 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
else else
side = tls_server; side = tls_server;
ret = PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, #ifdef WOLFSSL_HAVE_PRF
ret = wc_PRF_TLS((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret,
SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz,
IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
ssl->heap, ssl->devId); ssl->heap, ssl->devId);
#else
/* Pseudo random function must be enabled in the configuration. */
ret = PRF_MISSING;
WOLFSSL_MSG("Pseudo-random function is not enabled");
(void)side;
(void)hashes;
#endif
} }
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
@ -555,8 +279,28 @@ static int _DeriveTlsKeys(byte* key_dig, word32 key_dig_len,
XMEMCPY(seed, sr, RAN_LEN); XMEMCPY(seed, sr, RAN_LEN);
XMEMCPY(seed + RAN_LEN, cr, RAN_LEN); XMEMCPY(seed + RAN_LEN, cr, RAN_LEN);
ret = PRF(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ, #ifdef WOLFSSL_HAVE_PRF
ret = wc_PRF_TLS(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ,
seed, SEED_LEN, tls1_2, hash_type, heap, devId); seed, SEED_LEN, tls1_2, hash_type, heap, devId);
#else
/* Pseudo random function must be enabled in the configuration. */
ret = PRF_MISSING;
WOLFSSL_MSG("Pseudo-random function is not enabled");
(void)key_dig;
(void)key_dig_len;
(void)ms;
(void)msLen;
(void)tls1_2;
(void)hash_type;
(void)heap;
(void)devId;
(void)key_label;
(void)master_label;
#ifdef HAVE_EXTENDED_MASTER
(void)ext_master_label;
#endif
#endif
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(seed, heap); FREE_VAR(seed, heap);
@ -628,8 +372,23 @@ static int _MakeTlsMasterSecret(byte* ms, word32 msLen,
XMEMCPY(seed, cr, RAN_LEN); XMEMCPY(seed, cr, RAN_LEN);
XMEMCPY(seed + RAN_LEN, sr, RAN_LEN); XMEMCPY(seed + RAN_LEN, sr, RAN_LEN);
ret = PRF(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ, #ifdef WOLFSSL_HAVE_PRF
ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ,
seed, SEED_LEN, tls1_2, hash_type, heap, devId); seed, SEED_LEN, tls1_2, hash_type, heap, devId);
#else
/* Pseudo random function must be enabled in the configuration. */
ret = PRF_MISSING;
WOLFSSL_MSG("Pseudo-random function is not enabled");
(void)ms;
(void)msLen;
(void)pms;
(void)pmsLen;
(void)tls1_2;
(void)hash_type;
(void)heap;
(void)devId;
#endif
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(seed, heap); FREE_VAR(seed, heap);
@ -657,8 +416,28 @@ static int _MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
int tls1_2, int hash_type, int tls1_2, int hash_type,
void* heap, int devId) void* heap, int devId)
{ {
return PRF(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ, int ret;
#ifdef WOLFSSL_HAVE_PRF
ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ,
sHash, sHashLen, tls1_2, hash_type, heap, devId); sHash, sHashLen, tls1_2, hash_type, heap, devId);
#else
/* Pseudo random function must be enabled in the configuration. */
ret = PRF_MISSING;
WOLFSSL_MSG("Pseudo-random function is not enabled");
(void)ms;
(void)msLen;
(void)pms;
(void)pmsLen;
(void)sHash;
(void)sHashLen;
(void)tls1_2;
(void)hash_type;
(void)heap;
(void)devId;
#endif
return ret;
} }
/* External facing wrapper so user can call as well, 0 on success */ /* External facing wrapper so user can call as well, 0 on success */
@ -786,10 +565,20 @@ int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len,
XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN);
XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN);
ret = PRF((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN, #ifdef WOLFSSL_HAVE_PRF
ret = wc_PRF_TLS((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN,
(const byte *)label, (word32)XSTRLEN(label), seed, SEED_LEN, (const byte *)label, (word32)XSTRLEN(label), seed, SEED_LEN,
IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
ssl->heap, ssl->devId); ssl->heap, ssl->devId);
#else
/* Pseudo random function must be enabled in the configuration. */
ret = PRF_MISSING;
WOLFSSL_MSG("Pseudo-random function is not enabled");
(void)msk;
(void)len;
(void)label;
#endif
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
XFREE(seed, ssl->heap, DYNAMIC_TYPE_SEED); XFREE(seed, ssl->heap, DYNAMIC_TYPE_SEED);

View File

@ -32,7 +32,14 @@
#endif #endif
#include <wolfssl/wolfcrypt/hash.h> #include <wolfssl/wolfcrypt/hash.h>
#include <wolfssl/wolfcrypt/hmac.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) #if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC)
@ -48,18 +55,6 @@ enum Hash_Sum {
}; };
#endif /* !NO_ASN */ #endif /* !NO_ASN */
#ifdef HAVE_SELFTEST
enum {
/* CAVP selftest includes these in hmac.h instead of sha3.h,
copied here for that build */
WC_SHA3_224_BLOCK_SIZE = 144,
WC_SHA3_256_BLOCK_SIZE = 136,
WC_SHA3_384_BLOCK_SIZE = 104,
WC_SHA3_512_BLOCK_SIZE = 72,
};
#endif
/* function converts int hash type to enum */ /* function converts int hash type to enum */
enum wc_HashType wc_HashTypeConvert(int hashType) enum wc_HashType wc_HashTypeConvert(int hashType)
{ {
@ -928,3 +923,275 @@ int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type)
return ret; return ret;
} }
#endif /* WOLFSSL_SHA384 */ #endif /* WOLFSSL_SHA384 */
#ifdef WOLFSSL_HAVE_PRF
#ifdef WOLFSSL_SHA384
#define P_HASH_MAX_SIZE WC_SHA384_DIGEST_SIZE
#else
#define P_HASH_MAX_SIZE WC_SHA256_DIGEST_SIZE
#endif
/* Pseudo Random Function for MD5, SHA-1, SHA-256, or SHA-384 */
int wc_PRF(byte* result, word32 resLen, const byte* secret,
word32 secLen, const byte* seed, word32 seedLen, int hash,
void* heap, int devId)
{
word32 len = P_HASH_MAX_SIZE;
word32 times;
word32 lastLen;
word32 lastTime;
word32 i;
word32 idx = 0;
int ret = 0;
#ifdef WOLFSSL_SMALL_STACK
byte* previous;
byte* current;
Hmac* hmac;
#else
byte previous[P_HASH_MAX_SIZE]; /* max size */
byte current[P_HASH_MAX_SIZE]; /* max size */
Hmac hmac[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST);
current = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST);
hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
if (previous == NULL || current == NULL || hmac == NULL) {
if (previous) XFREE(previous, heap, DYNAMIC_TYPE_DIGEST);
if (current) XFREE(current, heap, DYNAMIC_TYPE_DIGEST);
if (hmac) XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
return MEMORY_E;
}
#endif
switch (hash) {
#ifndef NO_MD5
case md5_mac:
hash = WC_MD5;
len = WC_MD5_DIGEST_SIZE;
break;
#endif
#ifndef NO_SHA256
case sha256_mac:
hash = WC_SHA256;
len = WC_SHA256_DIGEST_SIZE;
break;
#endif
#ifdef WOLFSSL_SHA384
case sha384_mac:
hash = WC_SHA384;
len = WC_SHA384_DIGEST_SIZE;
break;
#endif
#ifndef NO_SHA
case sha_mac:
default:
hash = WC_SHA;
len = WC_SHA_DIGEST_SIZE;
break;
#endif
}
times = resLen / len;
lastLen = resLen % len;
if (lastLen)
times += 1;
lastTime = times - 1;
ret = wc_HmacInit(hmac, heap, devId);
if (ret == 0) {
ret = wc_HmacSetKey(hmac, hash, secret, secLen);
if (ret == 0)
ret = wc_HmacUpdate(hmac, seed, seedLen); /* A0 = seed */
if (ret == 0)
ret = wc_HmacFinal(hmac, previous); /* A1 */
if (ret == 0) {
for (i = 0; i < times; i++) {
ret = wc_HmacUpdate(hmac, previous, len);
if (ret != 0)
break;
ret = wc_HmacUpdate(hmac, seed, seedLen);
if (ret != 0)
break;
ret = wc_HmacFinal(hmac, current);
if (ret != 0)
break;
if ((i == lastTime) && lastLen)
XMEMCPY(&result[idx], current,
min(lastLen, P_HASH_MAX_SIZE));
else {
XMEMCPY(&result[idx], current, len);
idx += len;
ret = wc_HmacUpdate(hmac, previous, len);
if (ret != 0)
break;
ret = wc_HmacFinal(hmac, previous);
if (ret != 0)
break;
}
}
}
wc_HmacFree(hmac);
}
ForceZero(previous, P_HASH_MAX_SIZE);
ForceZero(current, P_HASH_MAX_SIZE);
ForceZero(hmac, sizeof(Hmac));
#ifdef WOLFSSL_SMALL_STACK
XFREE(previous, heap, DYNAMIC_TYPE_DIGEST);
XFREE(current, heap, DYNAMIC_TYPE_DIGEST);
XFREE(hmac, heap, DYNAMIC_TYPE_HMAC);
#endif
return ret;
}
#undef P_HASH_MAX_SIZE
/* compute PRF (pseudo random function) using SHA1 and MD5 for TLSv1 */
int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret,
word32 secLen, const byte* label, word32 labLen,
const byte* seed, word32 seedLen, void* heap, int devId)
{
int ret = 0;
word32 half = (secLen + 1) / 2;
#ifdef WOLFSSL_SMALL_STACK
byte* md5_half;
byte* sha_half;
byte* md5_result;
byte* sha_result;
#else
byte md5_half[MAX_PRF_HALF]; /* half is real size */
byte sha_half[MAX_PRF_HALF]; /* half is real size */
byte md5_result[MAX_PRF_DIG]; /* digLen is real size */
byte sha_result[MAX_PRF_DIG]; /* digLen is real size */
#endif
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap);
if (labelSeed == NULL)
return MEMORY_E;
#else
byte labelSeed[MAX_PRF_LABSEED];
#endif
if (half > MAX_PRF_HALF ||
labLen + seedLen > MAX_PRF_LABSEED ||
digLen > MAX_PRF_DIG)
{
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(labelSeed, heap);
#endif
return BUFFER_E;
}
#ifdef WOLFSSL_SMALL_STACK
md5_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST);
sha_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST);
md5_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST);
sha_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST);
if (md5_half == NULL || sha_half == NULL || md5_result == NULL ||
sha_result == NULL) {
if (md5_half) XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST);
if (sha_half) XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST);
if (md5_result) XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST);
if (sha_result) XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST);
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(labelSeed, heap);
#endif
return MEMORY_E;
}
#endif
XMEMSET(md5_result, 0, digLen);
XMEMSET(sha_result, 0, digLen);
XMEMCPY(md5_half, secret, half);
XMEMCPY(sha_half, secret + half - secLen % 2, half);
XMEMCPY(labelSeed, label, labLen);
XMEMCPY(labelSeed + labLen, seed, seedLen);
if ((ret = wc_PRF(md5_result, digLen, md5_half, half, labelSeed,
labLen + seedLen, md5_mac, heap, devId)) == 0) {
if ((ret = wc_PRF(sha_result, digLen, sha_half, half, labelSeed,
labLen + seedLen, sha_mac, heap, devId)) == 0) {
/* calculate XOR for TLSv1 PRF */
XMEMCPY(digest, md5_result, digLen);
xorbuf(digest, sha_result, digLen);
}
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST);
XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST);
XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST);
XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST);
#endif
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(labelSeed, heap);
#endif
return ret;
}
/* Wrapper for TLS 1.2 and TLSv1 cases to calculate PRF */
/* In TLS 1.2 case call straight thru to wc_PRF */
int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
const byte* label, word32 labLen, const byte* seed, word32 seedLen,
int useAtLeastSha256, int hash_type, void* heap, int devId)
{
int ret = 0;
if (useAtLeastSha256) {
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap);
if (labelSeed == NULL)
return MEMORY_E;
#else
byte labelSeed[MAX_PRF_LABSEED];
#endif
if (labLen + seedLen > MAX_PRF_LABSEED)
return BUFFER_E;
XMEMCPY(labelSeed, label, labLen);
XMEMCPY(labelSeed + labLen, seed, seedLen);
/* If a cipher suite wants an algorithm better than sha256, it
* should use better. */
if (hash_type < sha256_mac || hash_type == blake2b_mac)
hash_type = sha256_mac;
/* compute PRF for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1.2 PRF */
ret = wc_PRF(digest, digLen, secret, secLen, labelSeed,
labLen + seedLen, hash_type, heap, devId);
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
FREE_VAR(labelSeed, heap);
#endif
}
#ifndef NO_OLD_TLS
else {
/* compute TLSv1 PRF (pseudo random function using HMAC) */
ret = wc_PRF_TLSv1(digest, digLen, secret, secLen, label, labLen, seed,
seedLen, heap, devId);
}
#endif
return ret;
}
#endif /* WOLFSSL_HAVE_PRF */

View File

@ -162,6 +162,7 @@ enum wolfSSL_ErrorCodes {
ALERT_COUNT_E = -427, /* Alert Count exceeded err */ ALERT_COUNT_E = -427, /* Alert Count exceeded err */
EXT_MISSING = -428, /* Required extension not found */ EXT_MISSING = -428, /* Required extension not found */
UNSUPPORTED_EXTENSION = -429, /* TLSX not requested by client */ UNSUPPORTED_EXTENSION = -429, /* TLSX not requested by client */
PRF_MISSING = -430, /* PRF not compiled in */
/* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */
/* begin negotiation parameter errors */ /* begin negotiation parameter errors */

View File

@ -1255,9 +1255,6 @@ enum Misc {
EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */ EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */
MASTER_LABEL_SZ = 13, /* TLS master secret label sz */ MASTER_LABEL_SZ = 13, /* TLS master secret label sz */
KEY_LABEL_SZ = 13, /* TLS key block expansion sz */ KEY_LABEL_SZ = 13, /* TLS key block expansion sz */
MAX_PRF_HALF = 256, /* Maximum half secret len */
MAX_PRF_LABSEED = 128, /* Maximum label + seed len */
MAX_PRF_DIG = 224, /* Maximum digest len */
PROTOCOL_LABEL_SZ = 9, /* Length of the protocol label */ PROTOCOL_LABEL_SZ = 9, /* Length of the protocol label */
MAX_LABEL_SZ = 34, /* Maximum length of a label */ MAX_LABEL_SZ = 34, /* Maximum length of a label */
MAX_HKDF_LABEL_SZ = OPAQUE16_LEN + MAX_HKDF_LABEL_SZ = OPAQUE16_LEN +
@ -2768,20 +2765,6 @@ typedef struct CipherSpecs {
void InitCipherSpecs(CipherSpecs* cs); void InitCipherSpecs(CipherSpecs* cs);
/* Supported Message Authentication Codes from page 43 */
enum MACAlgorithm {
no_mac,
md5_mac,
sha_mac,
sha224_mac,
sha256_mac, /* needs to match external KDF_MacAlgorithm */
sha384_mac,
sha512_mac,
rmd_mac,
blake2b_mac
};
/* Supported Key Exchange Protocols */ /* Supported Key Exchange Protocols */
enum KeyExchangeAlgorithm { enum KeyExchangeAlgorithm {
no_kea, no_kea,

View File

@ -1902,7 +1902,7 @@ enum BulkCipherAlgorithm {
/* for KDF TLS 1.2 mac types */ /* for KDF TLS 1.2 mac types */
enum KDF_MacAlgorithm { enum KDF_MacAlgorithm {
wolfssl_sha256 = 4, /* needs to match internal MACAlgorithm */ wolfssl_sha256 = 4, /* needs to match hash.h wc_MACAlgorithm */
wolfssl_sha384, wolfssl_sha384,
wolfssl_sha512 wolfssl_sha512
}; };

View File

@ -63,6 +63,20 @@
#endif #endif
/* Supported Message Authentication Codes from page 43 */
enum wc_MACAlgorithm {
no_mac,
md5_mac,
sha_mac,
sha224_mac,
sha256_mac, /* needs to match external KDF_MacAlgorithm */
sha384_mac,
sha512_mac,
rmd_mac,
blake2b_mac
};
typedef union { typedef union {
#ifndef NO_MD5 #ifndef NO_MD5
wc_Md5 md5; wc_Md5 md5;
@ -166,6 +180,25 @@ WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*);
WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*); WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*);
#endif /* WOLFSSL_SHA512 */ #endif /* WOLFSSL_SHA512 */
enum max_prf {
MAX_PRF_HALF = 256, /* Maximum half secret len */
MAX_PRF_LABSEED = 128, /* Maximum label + seed len */
MAX_PRF_DIG = 224 /* Maximum digest len */
};
#ifdef WOLFSSL_HAVE_PRF
WOLFSSL_API int wc_PRF(byte* result, word32 resLen, const byte* secret,
word32 secLen, const byte* seed, word32 seedLen, int hash,
void* heap, int devId);
WOLFSSL_API int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret,
word32 secLen, const byte* label, word32 labLen,
const byte* seed, word32 seedLen, void* heap, int devId);
WOLFSSL_API int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret,
word32 secLen, const byte* label, word32 labLen,
const byte* seed, word32 seedLen, int useAtLeastSha256,
int hash_type, void* heap, int devId);
#endif /* WOLFSSL_HAVE_PRF */
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

View File

@ -1831,8 +1831,13 @@ extern void uITRON4_free(void *p) ;
#define WOLFSSL_NO_WORD64_OPS #define WOLFSSL_NO_WORD64_OPS
#endif #endif
#if !defined(WOLFCRYPT_ONLY) && !defined(WOLFSSL_NO_TLS12)
#undef WOLFSSL_HAVE_PRF
#define WOLFSSL_HAVE_PRF
#endif
#if defined(NO_AES) && defined(NO_DES3) && !defined(HAVE_CAMELLIA) && \ #if defined(NO_AES) && defined(NO_DES3) && !defined(HAVE_CAMELLIA) && \
defined(NO_PWDBASED) && !defined(HAVE_IDEA) !defined(WOLFSSL_HAVE_PRF) && defined(NO_PWDBASED) && !defined(HAVE_IDEA)
#undef WOLFSSL_NO_XOR_OPS #undef WOLFSSL_NO_XOR_OPS
#define WOLFSSL_NO_XOR_OPS #define WOLFSSL_NO_XOR_OPS
#endif #endif