forked from wolfSSL/wolfssl
Constant time padding and HMAC verification in TLS
This commit is contained in:
343
src/internal.c
343
src/internal.c
@ -146,7 +146,7 @@ static const byte tls13Downgrade[7] = {
|
|||||||
|
|
||||||
#ifndef NO_OLD_TLS
|
#ifndef NO_OLD_TLS
|
||||||
static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
|
static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
|
||||||
int content, int verify);
|
int padSz, int content, int verify);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -11860,173 +11860,6 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_OLD_TLS
|
|
||||||
|
|
||||||
static INLINE void Md5Rounds(int rounds, const byte* data, int sz)
|
|
||||||
{
|
|
||||||
wc_Md5 md5;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
wc_InitMd5(&md5); /* no error check on purpose, dummy round */
|
|
||||||
|
|
||||||
for (i = 0; i < rounds; i++)
|
|
||||||
wc_Md5Update(&md5, data, sz);
|
|
||||||
wc_Md5Free(&md5); /* in case needed to release resources */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* do a dummy sha round */
|
|
||||||
static INLINE void ShaRounds(int rounds, const byte* data, int sz)
|
|
||||||
{
|
|
||||||
wc_Sha sha;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
wc_InitSha(&sha); /* no error check on purpose, dummy round */
|
|
||||||
|
|
||||||
for (i = 0; i < rounds; i++)
|
|
||||||
wc_ShaUpdate(&sha, data, sz);
|
|
||||||
wc_ShaFree(&sha); /* in case needed to release resources */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WOLFSSL_NO_TLS12
|
|
||||||
|
|
||||||
#ifndef NO_SHA256
|
|
||||||
|
|
||||||
static INLINE void Sha256Rounds(int rounds, const byte* data, int sz)
|
|
||||||
{
|
|
||||||
wc_Sha256 sha256;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
wc_InitSha256(&sha256); /* no error check on purpose, dummy round */
|
|
||||||
|
|
||||||
for (i = 0; i < rounds; i++) {
|
|
||||||
wc_Sha256Update(&sha256, data, sz);
|
|
||||||
/* no error check on purpose, dummy round */
|
|
||||||
}
|
|
||||||
wc_Sha256Free(&sha256); /* in case needed to release resources */
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_SHA384
|
|
||||||
|
|
||||||
static INLINE void Sha384Rounds(int rounds, const byte* data, int sz)
|
|
||||||
{
|
|
||||||
wc_Sha384 sha384;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
wc_InitSha384(&sha384); /* no error check on purpose, dummy round */
|
|
||||||
|
|
||||||
for (i = 0; i < rounds; i++) {
|
|
||||||
wc_Sha384Update(&sha384, data, sz);
|
|
||||||
/* no error check on purpose, dummy round */
|
|
||||||
}
|
|
||||||
wc_Sha384Free(&sha384); /* in case needed to release resources */
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_SHA512
|
|
||||||
|
|
||||||
static INLINE void Sha512Rounds(int rounds, const byte* data, int sz)
|
|
||||||
{
|
|
||||||
wc_Sha512 sha512;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
wc_InitSha512(&sha512); /* no error check on purpose, dummy round */
|
|
||||||
|
|
||||||
for (i = 0; i < rounds; i++) {
|
|
||||||
wc_Sha512Update(&sha512, data, sz);
|
|
||||||
/* no error check on purpose, dummy round */
|
|
||||||
}
|
|
||||||
wc_Sha512Free(&sha512); /* in case needed to release resources */
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_RIPEMD
|
|
||||||
|
|
||||||
static INLINE void RmdRounds(int rounds, const byte* data, int sz)
|
|
||||||
{
|
|
||||||
RipeMd ripemd;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
(void)wc_InitRipeMd(&ripemd);
|
|
||||||
|
|
||||||
for (i = 0; i < rounds; i++)
|
|
||||||
(void)wc_RipeMdUpdate(&ripemd, data, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Do dummy rounds */
|
|
||||||
static INLINE void DoRounds(int type, int rounds, const byte* data, int sz)
|
|
||||||
{
|
|
||||||
(void)rounds;
|
|
||||||
(void)data;
|
|
||||||
(void)sz;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case no_mac :
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifndef NO_OLD_TLS
|
|
||||||
#ifndef NO_MD5
|
|
||||||
case md5_mac :
|
|
||||||
Md5Rounds(rounds, data, sz);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NO_SHA
|
|
||||||
case sha_mac :
|
|
||||||
ShaRounds(rounds, data, sz);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NO_SHA256
|
|
||||||
case sha256_mac :
|
|
||||||
Sha256Rounds(rounds, data, sz);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_SHA384
|
|
||||||
case sha384_mac :
|
|
||||||
Sha384Rounds(rounds, data, sz);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_SHA512
|
|
||||||
case sha512_mac :
|
|
||||||
Sha512Rounds(rounds, data, sz);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_RIPEMD
|
|
||||||
case rmd_mac :
|
|
||||||
RmdRounds(rounds, data, sz);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
WOLFSSL_MSG("Bad round type");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* do number of compression rounds on dummy data */
|
|
||||||
static INLINE void CompressRounds(WOLFSSL* ssl, int rounds, const byte* dummy)
|
|
||||||
{
|
|
||||||
if (rounds)
|
|
||||||
DoRounds(ssl->specs.mac_algorithm, rounds, dummy, COMPRESS_LOWER);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* check all length bytes for the pad value, return 0 on success */
|
/* check all length bytes for the pad value, return 0 on success */
|
||||||
static int PadCheck(const byte* a, byte pad, int length)
|
static int PadCheck(const byte* a, byte pad, int length)
|
||||||
@ -12042,81 +11875,127 @@ static int PadCheck(const byte* a, byte pad, int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* get compression extra rounds */
|
/* Mask the padding bytes with the expected values.
|
||||||
static INLINE int GetRounds(int pLen, int padLen, int t)
|
* Constant time implementation - does maximum pad size possible.
|
||||||
|
*
|
||||||
|
* data Message data.
|
||||||
|
* sz Size of the message including MAC and padding and padding length.
|
||||||
|
* macSz Size of the MAC.
|
||||||
|
* returns 0 on success, otherwise failure.
|
||||||
|
*/
|
||||||
|
static byte MaskPadding(const byte* data, int sz, int macSz)
|
||||||
{
|
{
|
||||||
int roundL1 = 1; /* round up flags */
|
int i;
|
||||||
int roundL2 = 1;
|
int checkSz = sz - 1;
|
||||||
|
byte paddingSz = data[sz - 1];
|
||||||
|
byte mask;
|
||||||
|
byte good = ctMaskGT(paddingSz, sz - 1 - macSz);
|
||||||
|
|
||||||
int L1 = COMPRESS_CONSTANT + pLen - t;
|
if (checkSz > TLS_MAX_PAD_SZ)
|
||||||
int L2 = COMPRESS_CONSTANT + pLen - padLen - 1 - t;
|
checkSz = TLS_MAX_PAD_SZ;
|
||||||
|
|
||||||
L1 -= COMPRESS_UPPER;
|
for (i = 0; i < checkSz; i++) {
|
||||||
L2 -= COMPRESS_UPPER;
|
mask = ctMaskLTE(i, paddingSz);
|
||||||
|
good |= mask & (data[sz - 1 - i] ^ paddingSz);
|
||||||
|
}
|
||||||
|
|
||||||
if ( (L1 % COMPRESS_LOWER) == 0)
|
return good;
|
||||||
roundL1 = 0;
|
|
||||||
if ( (L2 % COMPRESS_LOWER) == 0)
|
|
||||||
roundL2 = 0;
|
|
||||||
|
|
||||||
L1 /= COMPRESS_LOWER;
|
|
||||||
L2 /= COMPRESS_LOWER;
|
|
||||||
|
|
||||||
L1 += roundL1;
|
|
||||||
L2 += roundL2;
|
|
||||||
|
|
||||||
return L1 - L2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mask the MAC in the message with the MAC calculated.
|
||||||
|
* Constant time implementation - starts looking for MAC where maximum padding
|
||||||
|
* size has it.
|
||||||
|
*
|
||||||
|
* data Message data.
|
||||||
|
* sz Size of the message including MAC and padding and padding length.
|
||||||
|
* macSz Size of the MAC data.
|
||||||
|
* expMac Expected MAC value.
|
||||||
|
* returns 0 on success, otherwise failure.
|
||||||
|
*/
|
||||||
|
static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
unsigned char mac[WC_MAX_DIGEST_SIZE];
|
||||||
|
int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz;
|
||||||
|
int macEnd = sz - 1 - data[sz - 1];
|
||||||
|
int macStart = macEnd - macSz;
|
||||||
|
int r = 0;
|
||||||
|
unsigned char started, notEnded;
|
||||||
|
unsigned char good = 0;
|
||||||
|
|
||||||
|
if (scanStart < 0)
|
||||||
|
scanStart = 0;
|
||||||
|
|
||||||
|
/* Div on Intel has different speeds depending on value.
|
||||||
|
* Use a bitwise AND or mod a specific value (converted to mul). */
|
||||||
|
if ((macSz & (macSz - 1)) == 0)
|
||||||
|
r = (macSz - (scanStart - macStart)) & (macSz - 1);
|
||||||
|
#ifndef NO_SHA
|
||||||
|
else if (macSz == WC_SHA_DIGEST_SIZE)
|
||||||
|
r = (macSz - (scanStart - macStart)) % WC_SHA_DIGEST_SIZE;
|
||||||
|
#endif
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
else if (macSz == WC_SHA384_DIGEST_SIZE)
|
||||||
|
r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
XMEMSET(mac, 0, macSz);
|
||||||
|
for (i = scanStart; i < sz; i += macSz) {
|
||||||
|
for (j = 0; j < macSz && j + i < sz; j++) {
|
||||||
|
started = ctMaskGTE(i + j, macStart);
|
||||||
|
notEnded = ctMaskLT(i + j, macEnd);
|
||||||
|
mac[j] |= started & notEnded & data[i + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((macSz & (macSz - 1)) == 0) {
|
||||||
|
for (i = 0; i < macSz; i++)
|
||||||
|
good |= expMac[i] ^ mac[(i + r) & (macSz - 1)];
|
||||||
|
}
|
||||||
|
#ifndef NO_SHA
|
||||||
|
else if (macSz == WC_SHA_DIGEST_SIZE) {
|
||||||
|
for (i = 0; i < macSz; i++)
|
||||||
|
good |= expMac[i] ^ mac[(i + r) % WC_SHA_DIGEST_SIZE];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
else if (macSz == WC_SHA384_DIGEST_SIZE) {
|
||||||
|
for (i = 0; i < macSz; i++)
|
||||||
|
good |= expMac[i] ^ mac[(i + r) % WC_SHA384_DIGEST_SIZE];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return good;
|
||||||
|
}
|
||||||
|
|
||||||
/* timing resistant pad/verify check, return 0 on success */
|
/* timing resistant pad/verify check, return 0 on success */
|
||||||
static int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t,
|
int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz,
|
||||||
int pLen, int content)
|
int pLen, int content)
|
||||||
{
|
{
|
||||||
byte verify[WC_MAX_DIGEST_SIZE];
|
byte verify[WC_MAX_DIGEST_SIZE];
|
||||||
byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0};
|
byte good;
|
||||||
byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
(void)dmy;
|
good = MaskPadding(input, pLen, macSz);
|
||||||
|
ret = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen,
|
||||||
|
content, 1);
|
||||||
|
good |= MaskMac(input, pLen, ssl->specs.hash_size, verify);
|
||||||
|
|
||||||
if ( (t + padLen + 1) > pLen) {
|
/* Non-zero on failure. */
|
||||||
WOLFSSL_MSG("Plain Len not long enough for pad/mac");
|
good = ~good;
|
||||||
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE);
|
good &= good >> 4;
|
||||||
ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */
|
good &= good >> 2;
|
||||||
ConstantCompare(verify, input + pLen - t, t);
|
good &= good >> 1;
|
||||||
|
/* Make ret negative on masking failure. */
|
||||||
|
ret -= 1 - good;
|
||||||
|
|
||||||
return VERIFY_MAC_ERROR;
|
/* Treat any faulure as verify MAC error. */
|
||||||
}
|
|
||||||
|
|
||||||
if (PadCheck(input + pLen - (padLen + 1), (byte)padLen, padLen + 1) != 0) {
|
|
||||||
WOLFSSL_MSG("PadCheck failed");
|
|
||||||
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1);
|
|
||||||
ssl->hmac(ssl, verify, input, pLen - t, content, 1); /* still compare */
|
|
||||||
ConstantCompare(verify, input + pLen - t, t);
|
|
||||||
|
|
||||||
return VERIFY_MAC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
PadCheck(dummy, (byte)padLen, MAX_PAD_SIZE - padLen - 1);
|
|
||||||
ret = ssl->hmac(ssl, verify, input, pLen - padLen - 1 - t, content, 1);
|
|
||||||
|
|
||||||
CompressRounds(ssl, GetRounds(pLen, padLen, t), dummy);
|
|
||||||
|
|
||||||
if (ConstantCompare(verify, input + (pLen - padLen - 1 - t), t) != 0) {
|
|
||||||
WOLFSSL_MSG("Verify MAC compare failed");
|
|
||||||
return VERIFY_MAC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* treat any faulure as verify MAC error */
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
ret = VERIFY_MAC_ERROR;
|
ret = VERIFY_MAC_ERROR;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WOLFSSL_NO_TLS12 */
|
|
||||||
|
|
||||||
|
|
||||||
int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
|
int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx)
|
||||||
{
|
{
|
||||||
@ -12368,8 +12247,8 @@ static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
|
|||||||
badPadLen = 1;
|
badPadLen = 1;
|
||||||
}
|
}
|
||||||
PadCheck(dummy, (byte)pad, MAX_PAD_SIZE); /* timing only */
|
PadCheck(dummy, (byte)pad, MAX_PAD_SIZE); /* timing only */
|
||||||
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1,
|
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, pad,
|
||||||
content, 1);
|
content, 1);
|
||||||
if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
|
if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1,
|
||||||
digestSz) != 0)
|
digestSz) != 0)
|
||||||
return VERIFY_MAC_ERROR;
|
return VERIFY_MAC_ERROR;
|
||||||
@ -12378,7 +12257,7 @@ static INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ssl->specs.cipher_type == stream) {
|
else if (ssl->specs.cipher_type == stream) {
|
||||||
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, content, 1);
|
ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1);
|
||||||
if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){
|
if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){
|
||||||
return VERIFY_MAC_ERROR;
|
return VERIFY_MAC_ERROR;
|
||||||
}
|
}
|
||||||
@ -13118,7 +12997,7 @@ int SendChangeCipher(WOLFSSL* ssl)
|
|||||||
|
|
||||||
#ifndef NO_OLD_TLS
|
#ifndef NO_OLD_TLS
|
||||||
static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
|
static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
|
||||||
int content, int verify)
|
int padLen, int content, int verify)
|
||||||
{
|
{
|
||||||
byte result[WC_MAX_DIGEST_SIZE];
|
byte result[WC_MAX_DIGEST_SIZE];
|
||||||
word32 digestSz = ssl->specs.hash_size; /* actual sizes */
|
word32 digestSz = ssl->specs.hash_size; /* actual sizes */
|
||||||
@ -13133,6 +13012,8 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
|
|||||||
byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */
|
byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */
|
||||||
const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify);
|
const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify);
|
||||||
|
|
||||||
|
(void)padLen;
|
||||||
|
|
||||||
#ifdef HAVE_FUZZER
|
#ifdef HAVE_FUZZER
|
||||||
if (ssl->fuzzerCb)
|
if (ssl->fuzzerCb)
|
||||||
ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
|
ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
|
||||||
@ -13609,8 +13490,8 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
|
|||||||
ERROR_OUT(MEMORY_E, exit_buildmsg);
|
ERROR_OUT(MEMORY_E, exit_buildmsg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ret = ssl->hmac(ssl, hmac, output + args->headerSz + args->ivSz, inSz,
|
ret = ssl->hmac(ssl, hmac, output + args->headerSz + args->ivSz,
|
||||||
type, 0);
|
inSz, -1, type, 0);
|
||||||
XMEMCPY(output + args->idx, hmac, args->digestSz);
|
XMEMCPY(output + args->idx, hmac, args->digestSz);
|
||||||
|
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
@ -13619,8 +13500,8 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
ret = ssl->hmac(ssl, output + args->idx, output + args->headerSz + args->ivSz,
|
ret = ssl->hmac(ssl, output + args->idx, output +
|
||||||
inSz, type, 0);
|
args->headerSz + args->ivSz, inSz, -1, type, 0);
|
||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
if (ssl->options.dtls)
|
if (ssl->options.dtls)
|
||||||
DtlsSEQIncrement(ssl, CUR_ORDER);
|
DtlsSEQIncrement(ssl, CUR_ORDER);
|
||||||
|
484
src/tls.c
484
src/tls.c
@ -852,13 +852,447 @@ int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TLS type HMAC */
|
#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS)
|
||||||
int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
|
|
||||||
int content, int verify)
|
/* Update the hash in the HMAC.
|
||||||
|
*
|
||||||
|
* hmac HMAC object.
|
||||||
|
* data Data to be hashed.
|
||||||
|
* sz Size of data to hash.
|
||||||
|
* returns 0 on success, otherwise failure.
|
||||||
|
*/
|
||||||
|
static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz)
|
||||||
{
|
{
|
||||||
Hmac hmac;
|
int ret = BAD_FUNC_ARG;
|
||||||
int ret = 0;
|
|
||||||
byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
|
switch (hmac->macType) {
|
||||||
|
#ifndef NO_SHA
|
||||||
|
case WC_SHA:
|
||||||
|
ret = wc_ShaUpdate(&hmac->hash.sha, data, sz);
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA */
|
||||||
|
|
||||||
|
#ifndef NO_SHA256
|
||||||
|
case WC_SHA256:
|
||||||
|
ret = wc_Sha256Update(&hmac->hash.sha256, data, sz);
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA256 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
case WC_SHA384:
|
||||||
|
ret = wc_Sha384Update(&hmac->hash.sha384, data, sz);
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA384 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA512
|
||||||
|
case WC_SHA512:
|
||||||
|
ret = wc_Sha512Update(&hmac->hash.sha512, data, sz);
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA512 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finalize the hash but don't put the EOC, padding or length in.
|
||||||
|
*
|
||||||
|
* hmac HMAC object.
|
||||||
|
* hash Hash result.
|
||||||
|
* returns 0 on success, otherwise failure.
|
||||||
|
*/
|
||||||
|
static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash)
|
||||||
|
{
|
||||||
|
int ret = BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
switch (hmac->macType) {
|
||||||
|
#ifndef NO_SHA
|
||||||
|
case WC_SHA:
|
||||||
|
ret = wc_ShaFinalRaw(&hmac->hash.sha, hash);
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA */
|
||||||
|
|
||||||
|
#ifndef NO_SHA256
|
||||||
|
case WC_SHA256:
|
||||||
|
ret = wc_Sha256FinalRaw(&hmac->hash.sha256, hash);
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA256 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
case WC_SHA384:
|
||||||
|
ret = wc_Sha384FinalRaw(&hmac->hash.sha384, hash);
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA384 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA512
|
||||||
|
case WC_SHA512:
|
||||||
|
ret = wc_Sha512FinalRaw(&hmac->hash.sha512, hash);
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA512 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finalize the HMAC by performing outer hash.
|
||||||
|
*
|
||||||
|
* hmac HMAC object.
|
||||||
|
* mac MAC result.
|
||||||
|
* returns 0 on success, otherwise failure.
|
||||||
|
*/
|
||||||
|
static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac)
|
||||||
|
{
|
||||||
|
int ret = BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
switch (hmac->macType) {
|
||||||
|
#ifndef NO_SHA
|
||||||
|
case WC_SHA:
|
||||||
|
ret = wc_InitSha(&hmac->hash.sha);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->opad,
|
||||||
|
WC_SHA_BLOCK_SIZE);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->innerHash,
|
||||||
|
WC_SHA_DIGEST_SIZE);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_ShaFinal(&hmac->hash.sha, mac);
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA */
|
||||||
|
|
||||||
|
#ifndef NO_SHA256
|
||||||
|
case WC_SHA256:
|
||||||
|
ret = wc_InitSha256(&hmac->hash.sha256);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad,
|
||||||
|
WC_SHA256_BLOCK_SIZE);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha256Update(&hmac->hash.sha256,
|
||||||
|
(byte*)hmac->innerHash,
|
||||||
|
WC_SHA256_DIGEST_SIZE);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha256Final(&hmac->hash.sha256, mac);
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA256 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
case WC_SHA384:
|
||||||
|
ret = wc_InitSha384(&hmac->hash.sha384);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->opad,
|
||||||
|
WC_SHA384_BLOCK_SIZE);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha384Update(&hmac->hash.sha384,
|
||||||
|
(byte*)hmac->innerHash,
|
||||||
|
WC_SHA384_DIGEST_SIZE);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha384Final(&hmac->hash.sha384, mac);
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA384 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA512
|
||||||
|
case WC_SHA512:
|
||||||
|
ret = wc_InitSha512(&hmac->hash.sha512);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha512Update(&hmac->hash.sha512,(byte*)hmac->opad,
|
||||||
|
WC_SHA512_BLOCK_SIZE);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha512Update(&hmac->hash.sha512,
|
||||||
|
(byte*)hmac->innerHash,
|
||||||
|
WC_SHA512_DIGEST_SIZE);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha512Final(&hmac->hash.sha512, mac);
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA512 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the HMAC of the header + message data.
|
||||||
|
* Constant time implementation using wc_Sha*FinalRaw().
|
||||||
|
*
|
||||||
|
* hmac HMAC object.
|
||||||
|
* digest MAC result.
|
||||||
|
* in Message data.
|
||||||
|
* sz Size of the message data.
|
||||||
|
* header Constructed record header with length of handshake data.
|
||||||
|
* returns 0 on success, otherwise failure.
|
||||||
|
*/
|
||||||
|
static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in,
|
||||||
|
word32 sz, byte* header)
|
||||||
|
{
|
||||||
|
byte lenBytes[8];
|
||||||
|
int i, j, k;
|
||||||
|
int blockBits, blockMask;
|
||||||
|
int realLen, lastBlockLen, macLen, extraLen, eocIndex;
|
||||||
|
int blocks, safeBlocks, lenBlock, eocBlock;
|
||||||
|
int maxLen;
|
||||||
|
int blockSz, padSz;
|
||||||
|
int ret;
|
||||||
|
byte extraBlock;
|
||||||
|
|
||||||
|
switch (hmac->macType) {
|
||||||
|
#ifndef NO_SHA
|
||||||
|
case WC_SHA:
|
||||||
|
blockSz = WC_SHA_BLOCK_SIZE;
|
||||||
|
blockBits = 6;
|
||||||
|
macLen = WC_SHA_DIGEST_SIZE;
|
||||||
|
padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA */
|
||||||
|
|
||||||
|
#ifndef NO_SHA256
|
||||||
|
case WC_SHA256:
|
||||||
|
blockSz = WC_SHA256_BLOCK_SIZE;
|
||||||
|
blockBits = 6;
|
||||||
|
macLen = WC_SHA256_DIGEST_SIZE;
|
||||||
|
padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA256 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
case WC_SHA384:
|
||||||
|
blockSz = WC_SHA384_BLOCK_SIZE;
|
||||||
|
blockBits = 7;
|
||||||
|
macLen = WC_SHA384_DIGEST_SIZE;
|
||||||
|
padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA384 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA512
|
||||||
|
case WC_SHA512:
|
||||||
|
blockSz = WC_SHA512_BLOCK_SIZE;
|
||||||
|
blockBits = 7;
|
||||||
|
macLen = WC_SHA512_DIGEST_SIZE;
|
||||||
|
padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA512 */
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
blockMask = blockSz - 1;
|
||||||
|
|
||||||
|
/* Size of data to HMAC if padding length byte is zero. */
|
||||||
|
maxLen = WOLFSSL_TLS_HMAC_INNER_SZ + sz - 1 - macLen;
|
||||||
|
/* Complete data (including padding) has block for EOC and/or length. */
|
||||||
|
extraBlock = ctSetLTE((maxLen + padSz) & blockMask, padSz);
|
||||||
|
/* Total number of blocks for data including padding. */
|
||||||
|
blocks = ((maxLen + blockSz - 1) >> blockBits) + extraBlock;
|
||||||
|
/* Up to last 6 blocks can be hashed safely. */
|
||||||
|
safeBlocks = blocks - 6;
|
||||||
|
|
||||||
|
/* Length of message data. */
|
||||||
|
realLen = maxLen - in[sz - 1];
|
||||||
|
/* Number of message bytes in last block. */
|
||||||
|
lastBlockLen = realLen & blockMask;
|
||||||
|
/* Number of padding bytes in last block. */
|
||||||
|
extraLen = ((blockSz * 2 - padSz - lastBlockLen) & blockMask) + 1;
|
||||||
|
/* Number of blocks to create for hash. */
|
||||||
|
lenBlock = (realLen + extraLen) >> blockBits;
|
||||||
|
/* Block containing EOC byte. */
|
||||||
|
eocBlock = realLen >> blockBits;
|
||||||
|
/* Index of EOC byte in block. */
|
||||||
|
eocIndex = realLen & blockMask;
|
||||||
|
|
||||||
|
/* Add length of hmac's ipad to total length. */
|
||||||
|
realLen += blockSz;
|
||||||
|
/* Length as bits - 8 bytes bigendian. */
|
||||||
|
c32toa(realLen >> ((sizeof(word32) * 8) - 3), lenBytes);
|
||||||
|
c32toa(realLen << 3, lenBytes + sizeof(word32));
|
||||||
|
|
||||||
|
ret = Hmac_HashUpdate(hmac, (unsigned char*)hmac->ipad, blockSz);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
XMEMSET(hmac->innerHash, 0, macLen);
|
||||||
|
|
||||||
|
if (safeBlocks > 0) {
|
||||||
|
ret = Hmac_HashUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
ret = Hmac_HashUpdate(hmac, in, safeBlocks * blockSz -
|
||||||
|
WOLFSSL_TLS_HMAC_INNER_SZ);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
safeBlocks = 0;
|
||||||
|
|
||||||
|
XMEMSET(digest, 0, macLen);
|
||||||
|
k = safeBlocks * blockSz;
|
||||||
|
for (i = safeBlocks; i < blocks; i++) {
|
||||||
|
unsigned char hashBlock[WC_MAX_BLOCK_SIZE];
|
||||||
|
unsigned char isEocBlock = ctMaskEq(i, eocBlock);
|
||||||
|
unsigned char isOutBlock = ctMaskEq(i, lenBlock);
|
||||||
|
|
||||||
|
for (j = 0; j < blockSz; j++, k++) {
|
||||||
|
unsigned char atEoc = ctMaskEq(j, eocIndex) & isEocBlock;
|
||||||
|
unsigned char pastEoc = ctMaskGT(j, eocIndex) & isEocBlock;
|
||||||
|
unsigned char b = 0;
|
||||||
|
|
||||||
|
if (k < WOLFSSL_TLS_HMAC_INNER_SZ)
|
||||||
|
b = header[k];
|
||||||
|
else if (k < maxLen)
|
||||||
|
b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ];
|
||||||
|
|
||||||
|
b = ctMaskSel(atEoc, b, 0x80);
|
||||||
|
b &= ~pastEoc;
|
||||||
|
b &= ~isOutBlock | isEocBlock;
|
||||||
|
|
||||||
|
if (j >= blockSz - 8) {
|
||||||
|
b = ctMaskSel(isOutBlock, b, lenBytes[j - (blockSz - 8)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashBlock[j] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = Hmac_HashUpdate(hmac, hashBlock, blockSz);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
ret = Hmac_HashFinalRaw(hmac, hashBlock);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
for (j = 0; j < macLen; j++)
|
||||||
|
((unsigned char*)hmac->innerHash)[j] |= hashBlock[j] & isOutBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = Hmac_OuterHash(hmac, digest);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_NO_HASH_RAW) || defined(HAVE_FIPS) || defined(HAVE_BLAKE2)
|
||||||
|
|
||||||
|
/* Calculate the HMAC of the header + message data.
|
||||||
|
* Constant time implementation using normal hashing operations.
|
||||||
|
* Update-Final need to be constant time.
|
||||||
|
*
|
||||||
|
* hmac HMAC object.
|
||||||
|
* digest MAC result.
|
||||||
|
* in Message data.
|
||||||
|
* sz Size of the message data.
|
||||||
|
* header Constructed record header with length of handshake data.
|
||||||
|
* returns 0 on success, otherwise failure.
|
||||||
|
*/
|
||||||
|
static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in,
|
||||||
|
word32 sz, byte* header)
|
||||||
|
{
|
||||||
|
byte dummy[WC_MAX_BLOCK_SIZE] = {0};
|
||||||
|
int ret;
|
||||||
|
word32 msgSz, blockSz, macSz, padSz, maxSz, realSz;
|
||||||
|
word32 currSz, offset;
|
||||||
|
int msgBlocks, blocks, blockBits;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
switch (hmac->macType) {
|
||||||
|
#ifndef NO_SHA
|
||||||
|
case WC_SHA:
|
||||||
|
blockSz = WC_SHA_BLOCK_SIZE;
|
||||||
|
blockBits = 6;
|
||||||
|
macSz = WC_SHA_DIGEST_SIZE;
|
||||||
|
padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA */
|
||||||
|
|
||||||
|
#ifndef NO_SHA256
|
||||||
|
case WC_SHA256:
|
||||||
|
blockSz = WC_SHA256_BLOCK_SIZE;
|
||||||
|
blockBits = 6;
|
||||||
|
macSz = WC_SHA256_DIGEST_SIZE;
|
||||||
|
padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA256 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
case WC_SHA384:
|
||||||
|
blockSz = WC_SHA384_BLOCK_SIZE;
|
||||||
|
blockBits = 7;
|
||||||
|
macSz = WC_SHA384_DIGEST_SIZE;
|
||||||
|
padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA384 */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA512
|
||||||
|
case WC_SHA512:
|
||||||
|
blockSz = WC_SHA512_BLOCK_SIZE;
|
||||||
|
blockBits = 7;
|
||||||
|
macSz = WC_SHA512_DIGEST_SIZE;
|
||||||
|
padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA512 */
|
||||||
|
|
||||||
|
#ifdef HAVE_BLAKE2
|
||||||
|
case WC_HASH_TYPE_BLAKE2B:
|
||||||
|
blockSz = BLAKE2B_BLOCKBYTES;
|
||||||
|
blockBits = 7;
|
||||||
|
macSz = BLAKE2B_256;
|
||||||
|
padSz = 0;
|
||||||
|
break;
|
||||||
|
#endif /* HAVE_BLAK2 */
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgSz = sz - (1 + in[sz - 1] + macSz);
|
||||||
|
/* Make negative result 0 */
|
||||||
|
msgSz &= ~(0 - (msgSz >> 31));
|
||||||
|
realSz = WOLFSSL_TLS_HMAC_INNER_SZ + msgSz;
|
||||||
|
maxSz = WOLFSSL_TLS_HMAC_INNER_SZ + (sz - 1) - macSz;
|
||||||
|
|
||||||
|
/* Calculate #blocks processed in HMAC for max and real data. */
|
||||||
|
blocks = maxSz >> blockBits;
|
||||||
|
blocks += ((maxSz + padSz) % blockSz) < padSz;
|
||||||
|
msgBlocks = realSz >> blockBits;
|
||||||
|
/* #Extra blocks to process. */
|
||||||
|
blocks -= msgBlocks + (((realSz + padSz) % blockSz) < padSz);
|
||||||
|
/* Calculate whole blocks. */
|
||||||
|
msgBlocks--;
|
||||||
|
|
||||||
|
ret = wc_HmacUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ);
|
||||||
|
if (ret == 0) {
|
||||||
|
/* Fill the rest of the block with any available data. */
|
||||||
|
currSz = ctMaskLT(msgSz, blockSz) & msgSz;
|
||||||
|
currSz |= ctMaskGTE(msgSz, blockSz) & blockSz;
|
||||||
|
currSz -= WOLFSSL_TLS_HMAC_INNER_SZ;
|
||||||
|
currSz &= ~(0 - (currSz >> 31));
|
||||||
|
ret = wc_HmacUpdate(hmac, in, currSz);
|
||||||
|
offset = currSz;
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
/* Do the hash operations on a block basis. */
|
||||||
|
for (i = 0; i < msgBlocks; i++, offset += blockSz) {
|
||||||
|
ret = wc_HmacUpdate(hmac, in + offset, blockSz);
|
||||||
|
if (ret != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HmacUpdate(hmac, in + offset, msgSz - offset);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HmacFinal(hmac, digest);
|
||||||
|
if (ret == 0) {
|
||||||
|
/* Do the dummy hash operations. Do at least one. */
|
||||||
|
for (i = 0; i < blocks + 1; i++) {
|
||||||
|
ret = wc_HmacUpdate(hmac, dummy, blockSz);
|
||||||
|
if (ret != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz,
|
||||||
|
int content, int verify)
|
||||||
|
{
|
||||||
|
Hmac hmac;
|
||||||
|
byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (ssl == NULL)
|
if (ssl == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
@ -875,14 +1309,40 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
|
ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
|
||||||
wolfSSL_GetMacSecret(ssl, verify), ssl->specs.hash_size);
|
wolfSSL_GetMacSecret(ssl, verify),
|
||||||
|
ssl->specs.hash_size);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
|
/* Constant time verification required. */
|
||||||
if (ret == 0)
|
if (verify && padSz >= 0) {
|
||||||
ret = wc_HmacUpdate(&hmac, in, sz); /* content */
|
#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS)
|
||||||
if (ret == 0)
|
#ifdef HAVE_BLAKE2
|
||||||
ret = wc_HmacFinal(&hmac, digest);
|
if (wolfSSL_GetHmacType(ssl) == WC_HASH_TYPE_BLAKE2B) {
|
||||||
|
ret = Hmac_UpdateFinal(&hmac, digest, in, sz +
|
||||||
|
ssl->specs.hash_size + padSz + 1,
|
||||||
|
myInner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
ret = Hmac_UpdateFinal_CT(&hmac, digest, in, sz +
|
||||||
|
ssl->specs.hash_size + padSz + 1,
|
||||||
|
myInner);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ret = Hmac_UpdateFinal(&hmac, digest, in, sz +
|
||||||
|
ssl->specs.hash_size + padSz + 1,
|
||||||
|
myInner);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HmacUpdate(&hmac, in, sz); /* content */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HmacFinal(&hmac, digest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wc_HmacFree(&hmac);
|
wc_HmacFree(&hmac);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -311,6 +311,48 @@ STATIC INLINE word32 btoi(byte b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Constant time - mask set when a > b. */
|
||||||
|
STATIC INLINE byte ctMaskGT(int a, int b)
|
||||||
|
{
|
||||||
|
return (((word32)a - b - 1) >> 31) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constant time - mask set when a >= b. */
|
||||||
|
STATIC INLINE byte ctMaskGTE(int a, int b)
|
||||||
|
{
|
||||||
|
return (((word32)a - b ) >> 31) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constant time - mask set when a < b. */
|
||||||
|
STATIC INLINE byte ctMaskLT(int a, int b)
|
||||||
|
{
|
||||||
|
return (((word32)b - a - 1) >> 31) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constant time - mask set when a <= b. */
|
||||||
|
STATIC INLINE byte ctMaskLTE(int a, int b)
|
||||||
|
{
|
||||||
|
return (((word32)b - a ) >> 31) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constant time - mask set when a == b. */
|
||||||
|
STATIC INLINE byte ctMaskEq(int a, int b)
|
||||||
|
{
|
||||||
|
return 0 - (a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constant time - select b when mask is set and a otherwise. */
|
||||||
|
STATIC INLINE byte ctMaskSel(byte m, byte a, byte b)
|
||||||
|
{
|
||||||
|
return (a & ~m) | (b & m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constant time - bit set when a <= b. */
|
||||||
|
STATIC INLINE byte ctSetLTE(int a, int b)
|
||||||
|
{
|
||||||
|
return ((word32)a - b - 1) >> 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#undef STATIC
|
#undef STATIC
|
||||||
|
|
||||||
|
@ -431,6 +431,20 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wc_ShaFinalRaw(wc_Sha* sha, byte* hash)
|
||||||
|
{
|
||||||
|
if (sha == NULL || hash == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE);
|
||||||
|
#ifdef LITTLE_ENDIAN_ORDER
|
||||||
|
ByteReverseWords((word32*)hash, (word32*)hash, WC_SHA_DIGEST_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int wc_ShaFinal(wc_Sha* sha, byte* hash)
|
int wc_ShaFinal(wc_Sha* sha, byte* hash)
|
||||||
{
|
{
|
||||||
byte* local;
|
byte* local;
|
||||||
|
@ -765,6 +765,20 @@ static int InitSha256(wc_Sha256* sha256)
|
|||||||
return XTRANSFORM(sha256);
|
return XTRANSFORM(sha256);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash)
|
||||||
|
{
|
||||||
|
if (sha256 == NULL || hash == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
|
||||||
|
#if defined(LITTLE_ENDIAN_ORDER)
|
||||||
|
ByteReverseWords((word32*)hash, (word32*)hash, WC_SHA256_DIGEST_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
|
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -695,6 +695,20 @@ static INLINE int Sha512Final(wc_Sha512* sha512)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wc_Sha512FinalRaw(wc_Sha512* sha512, byte* hash)
|
||||||
|
{
|
||||||
|
if (sha512 == NULL || hash == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE);
|
||||||
|
#if defined(LITTLE_ENDIAN_ORDER)
|
||||||
|
ByteReverseWords64((word64*)hash, (word64*)hash, WC_SHA512_DIGEST_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int wc_Sha512Final(wc_Sha512* sha512, byte* hash)
|
int wc_Sha512Final(wc_Sha512* sha512, byte* hash)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -2588,6 +2602,20 @@ int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wc_Sha384FinalRaw(wc_Sha384* sha384, byte* hash)
|
||||||
|
{
|
||||||
|
if (sha384 == NULL || hash == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
|
||||||
|
#if defined(LITTLE_ENDIAN_ORDER)
|
||||||
|
ByteReverseWords64((word64*)hash, (word64*)hash, WC_SHA384_DIGEST_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int wc_Sha384Final(wc_Sha384* sha384, byte* hash)
|
int wc_Sha384Final(wc_Sha384* sha384, byte* hash)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1095,10 +1095,6 @@ enum Misc {
|
|||||||
PAD_MD5 = 48, /* pad length for finished */
|
PAD_MD5 = 48, /* pad length for finished */
|
||||||
PAD_SHA = 40, /* pad length for finished */
|
PAD_SHA = 40, /* pad length for finished */
|
||||||
MAX_PAD_SIZE = 256, /* maximum length of padding */
|
MAX_PAD_SIZE = 256, /* maximum length of padding */
|
||||||
COMPRESS_DUMMY_SIZE = 64, /* compression dummy round size */
|
|
||||||
COMPRESS_CONSTANT = 13, /* compression calc constant */
|
|
||||||
COMPRESS_UPPER = 55, /* compression calc numerator */
|
|
||||||
COMPRESS_LOWER = 64, /* compression calc denominator */
|
|
||||||
|
|
||||||
LENGTH_SZ = 2, /* length field for HMAC, data only */
|
LENGTH_SZ = 2, /* length field for HMAC, data only */
|
||||||
VERSION_SZ = 2, /* length of proctocol version */
|
VERSION_SZ = 2, /* length of proctocol version */
|
||||||
@ -1181,6 +1177,7 @@ enum Misc {
|
|||||||
OPAQUE8_LEN + WC_MAX_DIGEST_SIZE,
|
OPAQUE8_LEN + WC_MAX_DIGEST_SIZE,
|
||||||
MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */
|
MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */
|
||||||
SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */
|
SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */
|
||||||
|
TLS_MAX_PAD_SZ = 255, /* Max padding in TLS */
|
||||||
|
|
||||||
#ifdef HAVE_FIPS
|
#ifdef HAVE_FIPS
|
||||||
MAX_SYM_KEY_SIZE = AES_256_KEY_SIZE,
|
MAX_SYM_KEY_SIZE = AES_256_KEY_SIZE,
|
||||||
@ -1550,6 +1547,8 @@ WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input,
|
|||||||
word32* inOutIdx, word32 helloSz,
|
word32* inOutIdx, word32 helloSz,
|
||||||
byte* extMsgType);
|
byte* extMsgType);
|
||||||
#endif
|
#endif
|
||||||
|
int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t,
|
||||||
|
int pLen, int content);
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -2853,7 +2852,7 @@ WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte);
|
|||||||
WOLFSSL_LOCAL
|
WOLFSSL_LOCAL
|
||||||
int SetSession(WOLFSSL*, WOLFSSL_SESSION*);
|
int SetSession(WOLFSSL*, WOLFSSL_SESSION*);
|
||||||
|
|
||||||
typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int);
|
typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int);
|
||||||
|
|
||||||
#ifndef NO_CLIENT_CACHE
|
#ifndef NO_CLIENT_CACHE
|
||||||
WOLFSSL_SESSION* GetSessionClient(WOLFSSL*, const byte*, int);
|
WOLFSSL_SESSION* GetSessionClient(WOLFSSL*, const byte*, int);
|
||||||
@ -3942,7 +3941,7 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength);
|
|||||||
#ifndef NO_TLS
|
#ifndef NO_TLS
|
||||||
WOLFSSL_LOCAL int MakeTlsMasterSecret(WOLFSSL*);
|
WOLFSSL_LOCAL int MakeTlsMasterSecret(WOLFSSL*);
|
||||||
WOLFSSL_LOCAL int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in,
|
WOLFSSL_LOCAL int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in,
|
||||||
word32 sz, int content, int verify);
|
word32 sz, int padSz, int content, int verify);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NO_WOLFSSL_CLIENT
|
#ifndef NO_WOLFSSL_CLIENT
|
||||||
|
@ -91,6 +91,15 @@ void ato24(const byte* c, word32* u24);
|
|||||||
void ato32(const byte* c, word32* u32);
|
void ato32(const byte* c, word32* u32);
|
||||||
word32 btoi(byte b);
|
word32 btoi(byte b);
|
||||||
|
|
||||||
|
|
||||||
|
WOLFSSL_LOCAL byte ctMaskGT(int a, int b);
|
||||||
|
WOLFSSL_LOCAL byte ctMaskGTE(int a, int b);
|
||||||
|
WOLFSSL_LOCAL byte ctMaskLT(int a, int b);
|
||||||
|
WOLFSSL_LOCAL byte ctMaskLTE(int a, int b);
|
||||||
|
WOLFSSL_LOCAL byte ctMaskEq(int a, int b);
|
||||||
|
WOLFSSL_LOCAL byte ctMaskSel(byte m, byte a, byte b);
|
||||||
|
WOLFSSL_LOCAL byte ctSetLTE(int a, int b);
|
||||||
|
|
||||||
#endif /* NO_INLINE */
|
#endif /* NO_INLINE */
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#include <wolfssl/wolfcrypt/types.h>
|
#include <wolfssl/wolfcrypt/types.h>
|
||||||
|
|
||||||
|
#define WOLFSSL_NO_HASH_RAW
|
||||||
|
|
||||||
#ifndef WC_CAAM_CTXLEN
|
#ifndef WC_CAAM_CTXLEN
|
||||||
/* last 8 bytes of context is for length */
|
/* last 8 bytes of context is for length */
|
||||||
#define WC_CAAM_CTXLEN 8
|
#define WC_CAAM_CTXLEN 8
|
||||||
|
@ -196,6 +196,8 @@ int wc_Pic32DesCrypt(word32 *key, int keyLen, word32 *iv, int ivLen,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WOLFSSL_PIC32MZ_HASH
|
#ifdef WOLFSSL_PIC32MZ_HASH
|
||||||
|
#define WOLFSSL_NO_HASH_RAW
|
||||||
|
|
||||||
int wc_Pic32Hash(const byte* in, int inLen, word32* out, int outLen, int algo);
|
int wc_Pic32Hash(const byte* in, int inLen, word32* out, int outLen, int algo);
|
||||||
int wc_Pic32HashCopy(hashUpdCache* src, hashUpdCache* dst);
|
int wc_Pic32HashCopy(hashUpdCache* src, hashUpdCache* dst);
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#ifdef STM32_HASH
|
#ifdef STM32_HASH
|
||||||
|
|
||||||
|
#define WOLFSSL_NO_HASH_RAW
|
||||||
|
|
||||||
/* Generic STM32 Hashing Function */
|
/* Generic STM32 Hashing Function */
|
||||||
/* Supports CubeMX HAL or Standard Peripheral Library */
|
/* Supports CubeMX HAL or Standard Peripheral Library */
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#define WOLFSSL_MAX_HASH_SIZE 64
|
#define WOLFSSL_MAX_HASH_SIZE 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define WOLFSSL_NO_HASH_RAW
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte *msg;
|
byte *msg;
|
||||||
word32 used;
|
word32 used;
|
||||||
|
@ -122,6 +122,7 @@ typedef struct wc_Sha {
|
|||||||
WOLFSSL_API int wc_InitSha(wc_Sha*);
|
WOLFSSL_API int wc_InitSha(wc_Sha*);
|
||||||
WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId);
|
WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId);
|
||||||
WOLFSSL_API int wc_ShaUpdate(wc_Sha*, const byte*, word32);
|
WOLFSSL_API int wc_ShaUpdate(wc_Sha*, const byte*, word32);
|
||||||
|
WOLFSSL_API int wc_ShaFinalRaw(wc_Sha*, byte*);
|
||||||
WOLFSSL_API int wc_ShaFinal(wc_Sha*, byte*);
|
WOLFSSL_API int wc_ShaFinal(wc_Sha*, byte*);
|
||||||
WOLFSSL_API void wc_ShaFree(wc_Sha*);
|
WOLFSSL_API void wc_ShaFree(wc_Sha*);
|
||||||
|
|
||||||
|
@ -139,6 +139,7 @@ typedef struct wc_Sha256 {
|
|||||||
WOLFSSL_API int wc_InitSha256(wc_Sha256*);
|
WOLFSSL_API int wc_InitSha256(wc_Sha256*);
|
||||||
WOLFSSL_API int wc_InitSha256_ex(wc_Sha256*, void*, int);
|
WOLFSSL_API int wc_InitSha256_ex(wc_Sha256*, void*, int);
|
||||||
WOLFSSL_API int wc_Sha256Update(wc_Sha256*, const byte*, word32);
|
WOLFSSL_API int wc_Sha256Update(wc_Sha256*, const byte*, word32);
|
||||||
|
WOLFSSL_API int wc_Sha256FinalRaw(wc_Sha256*, byte*);
|
||||||
WOLFSSL_API int wc_Sha256Final(wc_Sha256*, byte*);
|
WOLFSSL_API int wc_Sha256Final(wc_Sha256*, byte*);
|
||||||
WOLFSSL_API void wc_Sha256Free(wc_Sha256*);
|
WOLFSSL_API void wc_Sha256Free(wc_Sha256*);
|
||||||
|
|
||||||
|
@ -112,6 +112,7 @@ typedef struct wc_Sha512 {
|
|||||||
WOLFSSL_API int wc_InitSha512(wc_Sha512*);
|
WOLFSSL_API int wc_InitSha512(wc_Sha512*);
|
||||||
WOLFSSL_API int wc_InitSha512_ex(wc_Sha512*, void*, int);
|
WOLFSSL_API int wc_InitSha512_ex(wc_Sha512*, void*, int);
|
||||||
WOLFSSL_API int wc_Sha512Update(wc_Sha512*, const byte*, word32);
|
WOLFSSL_API int wc_Sha512Update(wc_Sha512*, const byte*, word32);
|
||||||
|
WOLFSSL_API int wc_Sha512FinalRaw(wc_Sha512*, byte*);
|
||||||
WOLFSSL_API int wc_Sha512Final(wc_Sha512*, byte*);
|
WOLFSSL_API int wc_Sha512Final(wc_Sha512*, byte*);
|
||||||
WOLFSSL_API void wc_Sha512Free(wc_Sha512*);
|
WOLFSSL_API void wc_Sha512Free(wc_Sha512*);
|
||||||
|
|
||||||
@ -144,6 +145,7 @@ typedef wc_Sha512 wc_Sha384;
|
|||||||
WOLFSSL_API int wc_InitSha384(wc_Sha384*);
|
WOLFSSL_API int wc_InitSha384(wc_Sha384*);
|
||||||
WOLFSSL_API int wc_InitSha384_ex(wc_Sha384*, void*, int);
|
WOLFSSL_API int wc_InitSha384_ex(wc_Sha384*, void*, int);
|
||||||
WOLFSSL_API int wc_Sha384Update(wc_Sha384*, const byte*, word32);
|
WOLFSSL_API int wc_Sha384Update(wc_Sha384*, const byte*, word32);
|
||||||
|
WOLFSSL_API int wc_Sha384FinalRaw(wc_Sha384*, byte*);
|
||||||
WOLFSSL_API int wc_Sha384Final(wc_Sha384*, byte*);
|
WOLFSSL_API int wc_Sha384Final(wc_Sha384*, byte*);
|
||||||
WOLFSSL_API void wc_Sha384Free(wc_Sha384*);
|
WOLFSSL_API void wc_Sha384Free(wc_Sha384*);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user