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.
\param len an unsigned integer that represents the length of
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_
\code
@ -6750,9 +6750,7 @@ WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short);
return wolfSSL_make_eap_keys(ssl, msk, len, label);
\endcode
\sa PRF
\sa doPRF
\sa p_hash
\sa wc_PRF
\sa wc_HmacFinal
\sa wc_HmacUpdate
*/
@ -11085,7 +11083,7 @@ WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active,
\ingroup TLS
\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 BUFFER_E returned if there will be an error
@ -11121,9 +11119,7 @@ WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active,
}
\endcode
\sa PRF
\sadoPRF
\sa p_hash
\sa wc_PRF
\sa MakeTlsMasterSecret
*/
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.
\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
from the WOLFSSL structures specs member.
\param ms a constant pointer type holding the master secret
@ -11169,8 +11165,7 @@ int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, unsigned int msLen,
}
\endcode
\sa PRF
\sa doPRF
\sa wc_PRF
\sa DeriveTlsKeys
\sa IsAtLeastTLSv1_2
*/

View File

@ -15775,6 +15775,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
case UNSUPPORTED_EXTENSION:
return "TLS Extension not requested by the client";
case PRF_MISSING:
return "Pseudo-random function is not enabled";
case KEY_SHARE_ERROR:
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
#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
#define HSHASH_SZ WC_SHA384_DIGEST_SIZE
#else
@ -459,10 +174,19 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
else
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,
IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
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)
@ -555,8 +279,28 @@ static int _DeriveTlsKeys(byte* key_dig, word32 key_dig_len,
XMEMCPY(seed, sr, 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);
#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)
FREE_VAR(seed, heap);
@ -628,8 +372,23 @@ static int _MakeTlsMasterSecret(byte* ms, word32 msLen,
XMEMCPY(seed, cr, 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);
#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)
FREE_VAR(seed, heap);
@ -657,8 +416,28 @@ static int _MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
int tls1_2, int hash_type,
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);
#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 */
@ -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 + 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,
IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
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
XFREE(seed, ssl->heap, DYNAMIC_TYPE_SEED);

View File

@ -32,7 +32,14 @@
#endif
#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)
@ -48,18 +55,6 @@ enum Hash_Sum {
};
#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 */
enum wc_HashType wc_HashTypeConvert(int hashType)
{
@ -928,3 +923,275 @@ int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type)
return ret;
}
#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 */
EXT_MISSING = -428, /* Required extension not found */
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 !!!!! */
/* begin negotiation parameter errors */

View File

@ -1255,9 +1255,6 @@ enum Misc {
EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */
MASTER_LABEL_SZ = 13, /* TLS master secret label 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 */
MAX_LABEL_SZ = 34, /* Maximum length of a label */
MAX_HKDF_LABEL_SZ = OPAQUE16_LEN +
@ -2768,20 +2765,6 @@ typedef struct CipherSpecs {
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 */
enum KeyExchangeAlgorithm {
no_kea,

View File

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

View File

@ -63,6 +63,20 @@
#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 {
#ifndef NO_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*);
#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
} /* extern "C" */
#endif

View File

@ -1831,8 +1831,13 @@ extern void uITRON4_free(void *p) ;
#define WOLFSSL_NO_WORD64_OPS
#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) && \
defined(NO_PWDBASED) && !defined(HAVE_IDEA)
!defined(WOLFSSL_HAVE_PRF) && defined(NO_PWDBASED) && !defined(HAVE_IDEA)
#undef WOLFSSL_NO_XOR_OPS
#define WOLFSSL_NO_XOR_OPS
#endif