Merge pull request #1366 from ejohnstown/hmac-sha3

HMAC-SHA-3
This commit is contained in:
toddouska
2018-02-13 11:41:34 -08:00
committed by GitHub
6 changed files with 387 additions and 10 deletions

View File

@ -107,7 +107,7 @@ enum {
/* HMAC */
typedef struct CRYPT_HMAC_CTX {
long long holder[72]; /* big enough to hold internal, but check on init */
long long holder[98]; /* big enough to hold internal, but check on init */
} CRYPT_HMAC_CTX;
int CRYPT_HMAC_SetKey(CRYPT_HMAC_CTX*, int, const unsigned char*, unsigned int);

View File

@ -1,4 +1,4 @@
/* hmac.h
/* hmac.c
*
* Copyright (C) 2006-2017 wolfSSL Inc.
*
@ -46,7 +46,8 @@
{
if (hmac == NULL || (key == NULL && keySz != 0) ||
!(type == WC_MD5 || type == WC_SHA || type == WC_SHA256 ||
type == WC_SHA384 || type == WC_SHA512 || type == BLAKE2B_ID)) {
type == WC_SHA384 || type == WC_SHA512 ||
type == BLAKE2B_ID)) {
return BAD_FUNC_ARG;
}
@ -110,8 +111,11 @@ int wc_HmacSizeByType(int type)
{
int ret;
if (!(type == WC_MD5 || type == WC_SHA || type == WC_SHA224 ||
type == WC_SHA256 || type == WC_SHA384 || type == WC_SHA512 ||
if (!(type == WC_MD5 || type == WC_SHA ||
type == WC_SHA224 || type == WC_SHA256 ||
type == WC_SHA384 || type == WC_SHA512 ||
type == WC_SHA3_224 || type == WC_SHA3_256 ||
type == WC_SHA3_384 || type == WC_SHA3_512 ||
type == BLAKE2B_ID)) {
return BAD_FUNC_ARG;
}
@ -158,6 +162,25 @@ int wc_HmacSizeByType(int type)
break;
#endif /* HAVE_BLAKE2 */
#ifdef WOLFSSL_SHA3
case WC_SHA3_224:
ret = WC_SHA3_224_DIGEST_SIZE;
break;
case WC_SHA3_256:
ret = WC_SHA3_256_DIGEST_SIZE;
break;
case WC_SHA3_384:
ret = WC_SHA3_384_DIGEST_SIZE;
break;
case WC_SHA3_512:
ret = WC_SHA3_512_DIGEST_SIZE;
break;
#endif
default:
ret = BAD_FUNC_ARG;
break;
@ -212,6 +235,21 @@ int _InitHmac(Hmac* hmac, int type, void* heap)
break;
#endif /* HAVE_BLAKE2 */
#ifdef WOLFSSL_SHA3
case WC_SHA3_224:
ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID);
break;
case WC_SHA3_256:
ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID);
break;
case WC_SHA3_384:
ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID);
break;
case WC_SHA3_512:
ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID);
break;
#endif
default:
ret = BAD_FUNC_ARG;
break;
@ -237,8 +275,11 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
void* heap = NULL;
if (hmac == NULL || (key == NULL && length != 0) ||
!(type == WC_MD5 || type == WC_SHA || type == WC_SHA224 ||
type == WC_SHA256 || type == WC_SHA384 || type == WC_SHA512 ||
!(type == WC_MD5 || type == WC_SHA ||
type == WC_SHA224 || type == WC_SHA256 ||
type == WC_SHA384 || type == WC_SHA512 ||
type == WC_SHA3_224 || type == WC_SHA3_256 ||
type == WC_SHA3_384 || type == WC_SHA3_512 ||
type == BLAKE2B_ID)) {
return BAD_FUNC_ARG;
}
@ -423,6 +464,81 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
break;
#endif /* HAVE_BLAKE2 */
#ifdef WOLFSSL_SHA3
case WC_SHA3_224:
hmac_block_size = WC_SHA3_224_BLOCK_SIZE;
if (length <= SHA3_224_DIGEST_SIZE) {
if (key != NULL) {
XMEMCPY(ip, key, length);
}
}
else {
ret = wc_Sha3_224_Update(&hmac->hash.sha3, key, length);
if (ret != 0)
break;
ret = wc_Sha3_224_Final(&hmac->hash.sha3, ip);
if (ret != 0)
break;
length = SHA3_224_DIGEST_SIZE;
}
break;
case WC_SHA3_256:
hmac_block_size = WC_SHA3_256_BLOCK_SIZE;
if (length <= SHA3_256_DIGEST_SIZE) {
if (key != NULL) {
XMEMCPY(ip, key, length);
}
}
else {
ret = wc_Sha3_256_Update(&hmac->hash.sha3, key, length);
if (ret != 0)
break;
ret = wc_Sha3_256_Final(&hmac->hash.sha3, ip);
if (ret != 0)
break;
length = SHA3_256_DIGEST_SIZE;
}
break;
case WC_SHA3_384:
hmac_block_size = WC_SHA3_384_BLOCK_SIZE;
if (length <= SHA3_384_DIGEST_SIZE) {
if (key != NULL) {
XMEMCPY(ip, key, length);
}
}
else {
ret = wc_Sha3_384_Update(&hmac->hash.sha3, key, length);
if (ret != 0)
break;
ret = wc_Sha3_384_Final(&hmac->hash.sha3, ip);
if (ret != 0)
break;
length = SHA3_384_DIGEST_SIZE;
}
break;
case WC_SHA3_512:
hmac_block_size = WC_SHA3_512_BLOCK_SIZE;
if (length <= SHA3_512_DIGEST_SIZE) {
if (key != NULL) {
XMEMCPY(ip, key, length);
}
}
else {
ret = wc_Sha3_512_Update(&hmac->hash.sha3, key, length);
if (ret != 0)
break;
ret = wc_Sha3_512_Final(&hmac->hash.sha3, ip);
if (ret != 0)
break;
length = SHA3_512_DIGEST_SIZE;
}
break;
#endif /* WOLFSSL_SHA3 */
default:
return BAD_FUNC_ARG;
}
@ -508,6 +624,25 @@ static int HmacKeyInnerHash(Hmac* hmac)
break;
#endif /* HAVE_BLAKE2 */
#ifdef WOLFSSL_SHA3
case WC_SHA3_224:
ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
WC_SHA3_224_BLOCK_SIZE);
break;
case WC_SHA3_256:
ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
WC_SHA3_256_BLOCK_SIZE);
break;
case WC_SHA3_384:
ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
WC_SHA3_384_BLOCK_SIZE);
break;
case WC_SHA3_512:
ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->ipad,
WC_SHA3_512_BLOCK_SIZE);
break;
#endif /* WOLFSSL_SHA3 */
default:
break;
}
@ -586,6 +721,21 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
break;
#endif /* HAVE_BLAKE2 */
#ifdef WOLFSSL_SHA3
case WC_SHA3_224:
ret = wc_Sha3_224_Update(&hmac->hash.sha3, msg, length);
break;
case WC_SHA3_256:
ret = wc_Sha3_256_Update(&hmac->hash.sha3, msg, length);
break;
case WC_SHA3_384:
ret = wc_Sha3_384_Update(&hmac->hash.sha3, msg, length);
break;
case WC_SHA3_512:
ret = wc_Sha3_512_Update(&hmac->hash.sha3, msg, length);
break;
#endif /* WOLFSSL_SHA3 */
default:
break;
}
@ -747,6 +897,65 @@ int wc_HmacFinal(Hmac* hmac, byte* hash)
break;
#endif /* HAVE_BLAKE2 */
#ifdef WOLFSSL_SHA3
case WC_SHA3_224:
ret = wc_Sha3_224_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
if (ret != 0)
break;
ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->opad,
WC_SHA3_224_BLOCK_SIZE);
if (ret != 0)
break;
ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
SHA3_224_DIGEST_SIZE);
if (ret != 0)
break;
ret = wc_Sha3_224_Final(&hmac->hash.sha3, hash);
break;
case WC_SHA3_256:
ret = wc_Sha3_256_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
if (ret != 0)
break;
ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->opad,
WC_SHA3_256_BLOCK_SIZE);
if (ret != 0)
break;
ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
SHA3_256_DIGEST_SIZE);
if (ret != 0)
break;
ret = wc_Sha3_256_Final(&hmac->hash.sha3, hash);
break;
case WC_SHA3_384:
ret = wc_Sha3_384_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
if (ret != 0)
break;
ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->opad,
WC_SHA3_384_BLOCK_SIZE);
if (ret != 0)
break;
ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
SHA3_384_DIGEST_SIZE);
if (ret != 0)
break;
ret = wc_Sha3_384_Final(&hmac->hash.sha3, hash);
break;
case WC_SHA3_512:
ret = wc_Sha3_512_Final(&hmac->hash.sha3, (byte*)hmac->innerHash);
if (ret != 0)
break;
ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->opad,
WC_SHA3_512_BLOCK_SIZE);
if (ret != 0)
break;
ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->innerHash,
SHA3_512_DIGEST_SIZE);
if (ret != 0)
break;
ret = wc_Sha3_512_Final(&hmac->hash.sha3, hash);
break;
#endif /* WOLFSSL_SHA3 */
default:
ret = BAD_FUNC_ARG;
break;

View File

@ -230,6 +230,7 @@ int hmac_sha256_test(void);
int hmac_sha384_test(void);
int hmac_sha512_test(void);
int hmac_blake2b_test(void);
int hmac_sha3_test(void);
int hkdf_test(void);
int x963kdf_test(void);
int arc4_test(void);
@ -579,6 +580,13 @@ int wolfcrypt_test(void* args)
printf( "HMAC-BLAKE2 test passed!\n");
#endif
#ifdef WOLFSSL_SHA3
if ( (ret = hmac_sha3_test()) != 0)
return err_sys("HMAC-SHA3 test failed!\n", ret);
else
printf( "HMAC-SHA3 test passed!\n");
#endif
#ifdef HAVE_HKDF
if ( (ret = hkdf_test()) != 0)
return err_sys("HMAC-KDF test failed!\n", ret);
@ -3231,6 +3239,134 @@ int hmac_sha512_test(void)
#endif
#if !defined(NO_HMAC) && defined(WOLFSSL_SHA3)
int hmac_sha3_test(void)
{
Hmac hmac;
byte hash[SHA3_512_DIGEST_SIZE];
const char* key[3] =
{
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
"Jefe",
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
};
const char* input[3] =
{
"Hi There",
"what do ya want for nothing?",
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
};
const int hashType[4] =
{
WC_SHA3_224, WC_SHA3_256, WC_SHA3_384, WC_SHA3_512
};
const int hashSz[4] =
{
SHA3_224_DIGEST_SIZE, SHA3_256_DIGEST_SIZE,
SHA3_384_DIGEST_SIZE, SHA3_512_DIGEST_SIZE
};
const char* output[12] =
{
/* key = 0b..., input = Hi There */
/* HMAC-SHA3-224 */
"\x3b\x16\x54\x6b\xbc\x7b\xe2\x70\x6a\x03\x1d\xca\xfd\x56\x37\x3d"
"\x98\x84\x36\x76\x41\xd8\xc5\x9a\xf3\xc8\x60\xf7",
/* HMAC-SHA3-256 */
"\xba\x85\x19\x23\x10\xdf\xfa\x96\xe2\xa3\xa4\x0e\x69\x77\x43\x51"
"\x14\x0b\xb7\x18\x5e\x12\x02\xcd\xcc\x91\x75\x89\xf9\x5e\x16\xbb",
/* HMAC-SHA3-384 */
"\x68\xd2\xdc\xf7\xfd\x4d\xdd\x0a\x22\x40\xc8\xa4\x37\x30\x5f\x61"
"\xfb\x73\x34\xcf\xb5\xd0\x22\x6e\x1b\xc2\x7d\xc1\x0a\x2e\x72\x3a"
"\x20\xd3\x70\xb4\x77\x43\x13\x0e\x26\xac\x7e\x3d\x53\x28\x86\xbd",
/* HMAC-SHA3-512 */
"\xeb\x3f\xbd\x4b\x2e\xaa\xb8\xf5\xc5\x04\xbd\x3a\x41\x46\x5a\xac"
"\xec\x15\x77\x0a\x7c\xab\xac\x53\x1e\x48\x2f\x86\x0b\x5e\xc7\xba"
"\x47\xcc\xb2\xc6\xf2\xaf\xce\x8f\x88\xd2\x2b\x6d\xc6\x13\x80\xf2"
"\x3a\x66\x8f\xd3\x88\x8b\xb8\x05\x37\xc0\xa0\xb8\x64\x07\x68\x9e",
/* key = jefe, input = what do ya want for nothing? */
/* HMAC-SHA3-224 */
"\x7f\xdb\x8d\xd8\x8b\xd2\xf6\x0d\x1b\x79\x86\x34\xad\x38\x68\x11"
"\xc2\xcf\xc8\x5b\xfa\xf5\xd5\x2b\xba\xce\x5e\x66",
/* HMAC-SHA3-256 */
"\xc7\xd4\x07\x2e\x78\x88\x77\xae\x35\x96\xbb\xb0\xda\x73\xb8\x87"
"\xc9\x17\x1f\x93\x09\x5b\x29\x4a\xe8\x57\xfb\xe2\x64\x5e\x1b\xa5",
/* HMAC-SHA3-384 */
"\xf1\x10\x1f\x8c\xbf\x97\x66\xfd\x67\x64\xd2\xed\x61\x90\x3f\x21"
"\xca\x9b\x18\xf5\x7c\xf3\xe1\xa2\x3c\xa1\x35\x08\xa9\x32\x43\xce"
"\x48\xc0\x45\xdc\x00\x7f\x26\xa2\x1b\x3f\x5e\x0e\x9d\xf4\xc2\x0a",
/* HMAC-SHA3-512 */
"\x5a\x4b\xfe\xab\x61\x66\x42\x7c\x7a\x36\x47\xb7\x47\x29\x2b\x83"
"\x84\x53\x7c\xdb\x89\xaf\xb3\xbf\x56\x65\xe4\xc5\xe7\x09\x35\x0b"
"\x28\x7b\xae\xc9\x21\xfd\x7c\xa0\xee\x7a\x0c\x31\xd0\x22\xa9\x5e"
"\x1f\xc9\x2b\xa9\xd7\x7d\xf8\x83\x96\x02\x75\xbe\xb4\xe6\x20\x24",
/* key = aa..., output = dd... */
/* HMAC-SHA3-224 */
"\x67\x6c\xfc\x7d\x16\x15\x36\x38\x78\x03\x90\x69\x2b\xe1\x42\xd2"
"\xdf\x7c\xe9\x24\xb9\x09\xc0\xc0\x8d\xbf\xdc\x1a",
/* HMAC-SHA3-256 */
"\x84\xec\x79\x12\x4a\x27\x10\x78\x65\xce\xdd\x8b\xd8\x2d\xa9\x96"
"\x5e\x5e\xd8\xc3\x7b\x0a\xc9\x80\x05\xa7\xf3\x9e\xd5\x8a\x42\x07",
/* HMAC-SHA3-384 */
"\x27\x5c\xd0\xe6\x61\xbb\x8b\x15\x1c\x64\xd2\x88\xf1\xf7\x82\xfb"
"\x91\xa8\xab\xd5\x68\x58\xd7\x2b\xab\xb2\xd4\x76\xf0\x45\x83\x73"
"\xb4\x1b\x6a\xb5\xbf\x17\x4b\xec\x42\x2e\x53\xfc\x31\x35\xac\x6e",
/* HMAC-SHA3-512 */
"\x30\x9e\x99\xf9\xec\x07\x5e\xc6\xc6\xd4\x75\xed\xa1\x18\x06\x87"
"\xfc\xf1\x53\x11\x95\x80\x2a\x99\xb5\x67\x74\x49\xa8\x62\x51\x82"
"\x85\x1c\xb3\x32\xaf\xb6\xa8\x9c\x41\x13\x25\xfb\xcb\xcd\x42\xaf"
"\xcb\x7b\x6e\x5a\xab\x7e\xa4\x2c\x66\x0f\x97\xfd\x85\x84\xbf\x03"
};
int i, iMax = sizeof(input) / sizeof(input[0]),
j, jMax = sizeof(hashType) / sizeof(hashType[0]),
ret;
for (i = 0; i < iMax; i++) {
for (j = 0; j < jMax; j++) {
if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0)
return -3114;
ret = wc_HmacSetKey(&hmac, hashType[j], (byte*)key[i],
(word32)XSTRLEN(key[i]));
if (ret != 0)
return -3115;
ret = wc_HmacUpdate(&hmac, (byte*)input[i],
(word32)XSTRLEN(input[i]));
if (ret != 0)
return -3116;
ret = wc_HmacFinal(&hmac, hash);
if (ret != 0)
return -3117;
if (XMEMCMP(hash, output[(i*jMax) + j], hashSz[j]) != 0)
return -3118;
wc_HmacFree(&hmac);
}
}
return 0;
}
#endif
#ifndef NO_RC4
int arc4_test(void)
{

View File

@ -40,6 +40,9 @@
#ifdef HAVE_BLAKE2
#include <wolfssl/wolfcrypt/blake2.h>
#endif
#ifdef WOLFSSL_SHA3
#include <wolfssl/wolfcrypt/sha3.h>
#endif
#ifdef __cplusplus
extern "C" {
@ -87,7 +90,9 @@ typedef union {
/* Find largest possible digest size
Note if this gets up to the size of 80 or over check smallstack build */
#if defined(WOLFSSL_SHA512)
#if defined(WOLFSSL_SHA3)
#define WC_MAX_DIGEST_SIZE WC_SHA3_512_DIGEST_SIZE
#elif defined(WOLFSSL_SHA512)
#define WC_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE
#elif defined(HAVE_BLAKE2)
#define WC_MAX_DIGEST_SIZE BLAKE2B_OUTBYTES

View File

@ -76,10 +76,25 @@ enum {
#ifndef WOLFSSL_SHA224
WC_SHA224 = 8,
#endif
#ifndef WOLFSSL_SHA3
WC_SHA3_224 = 10,
WC_SHA3_256 = 11,
WC_SHA3_384 = 12,
WC_SHA3_512 = 13,
#else
/* These values are used for HMAC, not SHA-3 directly.
* They come from from FIPS PUB 202. */
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
/* Select the largest available hash for the buffer size. */
#if defined(WOLFSSL_SHA512)
#if defined(WOLFSSL_SHA3)
WC_HMAC_BLOCK_SIZE = WC_SHA3_224_BLOCK_SIZE
/* SHA3-224 has the largest block size */
#elif defined(WOLFSSL_SHA512)
WC_HMAC_BLOCK_SIZE = WC_SHA512_BLOCK_SIZE,
#elif defined(HAVE_BLAKE2)
WC_HMAC_BLOCK_SIZE = BLAKE2B_BLOCKBYTES,
@ -122,6 +137,9 @@ typedef union {
#ifdef HAVE_BLAKE2
Blake2b blake2b;
#endif
#ifdef WOLFSSL_SHA3
Sha3 sha3;
#endif
} Hash;
/* Hmac digest */

View File

@ -61,6 +61,15 @@ enum {
SHA3_512_COUNT = 9
};
#define WC_SHA3_224 SHA3_224
#define WC_SHA3_224_DIGEST_SIZE SHA3_224_DIGEST_SIZE
#define WC_SHA3_256 SHA3_256
#define WC_SHA3_256_DIGEST_SIZE SHA3_256_DIGEST_SIZE
#define WC_SHA3_384 SHA3_384
#define WC_SHA3_384_DIGEST_SIZE SHA3_384_DIGEST_SIZE
#define WC_SHA3_512 SHA3_512
#define WC_SHA3_512_DIGEST_SIZE SHA3_512_DIGEST_SIZE
#ifdef WOLFSSL_XILINX_CRYPT
#include "wolfssl/wolfcrypt/port/xilinx/xil-sha3.h"