forked from wolfSSL/wolfssl
@ -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 structure’s 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
|
||||
*/
|
||||
|
@ -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
369
src/tls.c
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user