From e48eb1ded8d684cedb83e0000dd087124500393f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 12 Feb 2018 13:22:28 -0800 Subject: [PATCH] added hmac-sha-3 --- mcapi/crypto.h | 2 +- wolfcrypt/src/hmac.c | 221 +++++++++++++++++++++++++++++++++++++-- wolfcrypt/test/test.c | 136 ++++++++++++++++++++++++ wolfssl/wolfcrypt/hash.h | 7 +- wolfssl/wolfcrypt/hmac.h | 22 +++- wolfssl/wolfcrypt/sha3.h | 9 ++ 6 files changed, 387 insertions(+), 10 deletions(-) diff --git a/mcapi/crypto.h b/mcapi/crypto.h index 21015fd71..9ab356e17 100644 --- a/mcapi/crypto.h +++ b/mcapi/crypto.h @@ -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); diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 355485d17..68a29430c 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -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; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 7bb33d078..f61f456f4 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -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) { diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index 4ebe40946..16642acf6 100644 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -40,6 +40,9 @@ #ifdef HAVE_BLAKE2 #include #endif +#ifdef WOLFSSL_SHA3 + #include +#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 diff --git a/wolfssl/wolfcrypt/hmac.h b/wolfssl/wolfcrypt/hmac.h index aff420aee..fa0f082a7 100644 --- a/wolfssl/wolfcrypt/hmac.h +++ b/wolfssl/wolfcrypt/hmac.h @@ -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 */ diff --git a/wolfssl/wolfcrypt/sha3.h b/wolfssl/wolfcrypt/sha3.h index b931db919..b6eb7dd3d 100644 --- a/wolfssl/wolfcrypt/sha3.h +++ b/wolfssl/wolfcrypt/sha3.h @@ -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"