diff --git a/wolfcrypt/src/blake2b.c b/wolfcrypt/src/blake2b.c index 1f473cdd1..2295bb307 100644 --- a/wolfcrypt/src/blake2b.c +++ b/wolfcrypt/src/blake2b.c @@ -511,7 +511,65 @@ int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz) } -/* end CTaoCrypt API */ +int wc_Blake2bHmac(const byte * in, size_t in_len, + const byte * key, size_t key_len, + byte * out, size_t out_len) +{ + byte x_key[BLAKE2B_BLOCKBYTES]; + byte i_hash[BLAKE2B_OUTBYTES]; + Blake2b state; + int i; + int ret; + + if (in == NULL || key == NULL || out == NULL) + return BAD_FUNC_ARG; + + if (out_len != BLAKE2B_OUTBYTES) + return BUFFER_E; + + if (key_len > BLAKE2B_BLOCKBYTES) { + if ((ret = wc_InitBlake2b(&state, BLAKE2B_OUTBYTES)) != 0) + return ret; + if ((ret = wc_Blake2bUpdate(&state, key, (word32)key_len)) != 0) + return ret; + if ((ret = wc_Blake2bFinal(&state, x_key, 0)) != 0) + return ret; + } else { + XMEMCPY(x_key, key, key_len); + XMEMSET(x_key + key_len, 0, BLAKE2B_BLOCKBYTES - key_len); + } + + for (i = 0; i < BLAKE2B_BLOCKBYTES; ++i) + x_key[i] ^= 0x36U; + + if ((ret = wc_InitBlake2b(&state, BLAKE2B_OUTBYTES)) != 0) + return ret; + if ((ret = wc_Blake2bUpdate(&state, x_key, BLAKE2B_BLOCKBYTES)) != 0) + return ret; + if ((ret = wc_Blake2bUpdate(&state, in, (word32)in_len)) != 0) + return ret; + if ((ret = wc_Blake2bFinal(&state, i_hash, 0)) != 0) + return ret; + + for (i = 0; i < BLAKE2B_BLOCKBYTES; ++i) + x_key[i] ^= (0x5CU ^ 0x36U); + + if ((ret = wc_InitBlake2b(&state, BLAKE2B_OUTBYTES)) != 0) + return ret; + if ((ret = wc_Blake2bUpdate(&state, x_key, BLAKE2B_BLOCKBYTES)) != 0) + return ret; + if ((ret = wc_Blake2bUpdate(&state, i_hash, BLAKE2B_OUTBYTES)) != 0) + return ret; + if ((ret = wc_Blake2bFinal(&state, i_hash, 0)) != 0) + return ret; + + XMEMCPY(out, i_hash, BLAKE2B_OUTBYTES); + XMEMSET(x_key, 0, BLAKE2B_BLOCKBYTES); + XMEMSET(i_hash, 0, BLAKE2B_OUTBYTES); + + return 0; +} + +/* end wolfCrypt API */ #endif /* HAVE_BLAKE2 */ - diff --git a/wolfcrypt/src/blake2s.c b/wolfcrypt/src/blake2s.c index cf5c9f2ff..7dfd9b67e 100644 --- a/wolfcrypt/src/blake2s.c +++ b/wolfcrypt/src/blake2s.c @@ -505,7 +505,65 @@ int wc_Blake2sFinal(Blake2s* b2s, byte* final, word32 requestSz) } -/* end CTaoCrypt API */ +int wc_Blake2sHmac(const byte * in, size_t in_len, + const byte * key, size_t key_len, + byte * out, size_t out_len) +{ + byte x_key[BLAKE2S_BLOCKBYTES]; + byte i_hash[BLAKE2S_OUTBYTES]; + Blake2s state; + int i; + int ret; + + if (in == NULL || key == NULL || out == NULL) + return BAD_FUNC_ARG; + + if (out_len != BLAKE2S_OUTBYTES) + return BUFFER_E; + + if (key_len > BLAKE2S_BLOCKBYTES) { + if ((ret = wc_InitBlake2s(&state, BLAKE2S_OUTBYTES)) != 0) + return ret; + if ((ret = wc_Blake2sUpdate(&state, key, (word32)key_len)) != 0) + return ret; + if ((ret = wc_Blake2sFinal(&state, x_key, 0)) != 0) + return ret; + } else { + XMEMCPY(x_key, key, key_len); + XMEMSET(x_key + key_len, 0, BLAKE2S_BLOCKBYTES - key_len); + } + + for (i = 0; i < BLAKE2S_BLOCKBYTES; ++i) + x_key[i] ^= 0x36U; + + if ((ret = wc_InitBlake2s(&state, BLAKE2S_OUTBYTES)) != 0) + return ret; + if ((ret = wc_Blake2sUpdate(&state, x_key, BLAKE2S_BLOCKBYTES)) != 0) + return ret; + if ((ret = wc_Blake2sUpdate(&state, in, (word32)in_len)) != 0) + return ret; + if ((ret = wc_Blake2sFinal(&state, i_hash, 0)) != 0) + return ret; + + for (i = 0; i < BLAKE2S_BLOCKBYTES; ++i) + x_key[i] ^= (0x5CU ^ 0x36U); + + if ((ret = wc_InitBlake2s(&state, BLAKE2S_OUTBYTES)) != 0) + return ret; + if ((ret = wc_Blake2sUpdate(&state, x_key, BLAKE2S_BLOCKBYTES)) != 0) + return ret; + if ((ret = wc_Blake2sUpdate(&state, i_hash, BLAKE2S_OUTBYTES)) != 0) + return ret; + if ((ret = wc_Blake2sFinal(&state, i_hash, 0)) != 0) + return ret; + + XMEMCPY(out, i_hash, BLAKE2S_OUTBYTES); + XMEMSET(x_key, 0, BLAKE2S_BLOCKBYTES); + XMEMSET(i_hash, 0, BLAKE2S_OUTBYTES); + + return 0; +} + +/* end wolfCrypt API */ #endif /* HAVE_BLAKE2S */ - diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 54f8d7221..efe70cfeb 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -776,9 +776,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t scrypt_test(void); #endif #ifdef HAVE_BLAKE2 WOLFSSL_TEST_SUBROUTINE wc_test_ret_t blake2b_test(void); + WOLFSSL_TEST_SUBROUTINE wc_test_ret_t blake2b_hmac_test(void); #endif #ifdef HAVE_BLAKE2S WOLFSSL_TEST_SUBROUTINE wc_test_ret_t blake2s_test(void); + WOLFSSL_TEST_SUBROUTINE wc_test_ret_t blake2s_hmac_test(void); #endif #ifdef HAVE_LIBZ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t compress_test(void); @@ -2187,12 +2189,20 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ TEST_FAIL("BLAKE2b test failed!\n", ret); else TEST_PASS("BLAKE2b test passed!\n"); + if ( (ret = blake2b_hmac_test()) != 0) + TEST_FAIL("HMAC-BLAKE2b test failed!\n", ret); + else + TEST_PASS("HMAC-BLAKE2b test passed!\n"); #endif #ifdef HAVE_BLAKE2S if ( (ret = blake2s_test()) != 0) TEST_FAIL("BLAKE2s test failed!\n", ret); else TEST_PASS("BLAKE2s test passed!\n"); + if ( (ret = blake2s_hmac_test()) != 0) + TEST_FAIL("HMAC-BLAKE2s test failed!\n", ret); + else + TEST_PASS("HMAC-BLAKE2s test passed!\n"); #endif #ifndef NO_HMAC @@ -4581,7 +4591,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ripemd_test(void) #ifdef HAVE_BLAKE2 - #define BLAKE2B_TESTS 3 static const byte blake2b_vec[BLAKE2B_TESTS][BLAKE2B_OUTBYTES] = @@ -4651,10 +4660,71 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t blake2b_test(void) return 0; } + +WOLFSSL_TEST_SUBROUTINE wc_test_ret_t blake2b_hmac_test(void) +{ + static const byte key1[] = {0x41, 0x42, 0x43, 0x44}; /* ABCD */ + static const byte message1[] = {0x48, 0x65, 0x6c, 0x6c, 0x6f}; /* Hello */ + static const byte expected1[] = { + 0x46, 0x76, 0xbb, 0x0e, 0xf8, 0xa1, 0x56, 0x33, + 0xde, 0xdc, 0x44, 0xe3, 0x2b, 0xf3, 0xee, 0x5b, + 0x5f, 0x7f, 0x04, 0x00, 0x2c, 0xaa, 0xd4, 0x93, + 0xc6, 0xa6, 0xb4, 0xf3, 0x14, 0x8d, 0x6d, 0x9c, + 0x6a, 0x12, 0x02, 0x85, 0x66, 0xed, 0x9b, 0x5d, + 0x8d, 0x0e, 0x3d, 0xf4, 0x78, 0xee, 0x5a, 0xf6, + 0x2f, 0x97, 0xa5, 0x77, 0x88, 0x8c, 0xc4, 0x66, + 0x46, 0xb1, 0xba, 0x51, 0x29, 0x19, 0xd7, 0xaa, + }; + static const byte key2[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, + 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, + 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33 + }; /* 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123 */ + static const byte message2[] = { + 0x61, 0x62, 0x63, 0x64, 0x62, 0x63, 0x64, 0x65, 0x63, 0x64, 0x65, 0x66, + 0x64, 0x65, 0x66, 0x67, 0x65, 0x66, 0x67, 0x68, 0x66, 0x67, 0x68, 0x69, + 0x67, 0x68, 0x69, 0x6a, 0x68, 0x69, 0x6a, 0x6b, 0x69, 0x6a, 0x6b, 0x6c, + 0x6a, 0x6b, 0x6c, 0x6d, 0x6b, 0x6c, 0x6d, 0x6e, 0x6c, 0x6d, 0x6e, 0x6f, + 0x6d, 0x6e, 0x6f, 0x70, 0x6e, 0x6f, 0x70, 0x71 + }; /* abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq */ + static const byte expected2[] = { + 0x2a, 0xda, 0xf6, 0x94, 0x79, 0xce, 0xe2, 0xd2, + 0x5d, 0x89, 0x8b, 0xd7, 0x0d, 0xbc, 0x11, 0x1f, + 0x98, 0x99, 0xe0, 0x17, 0x7c, 0x5b, 0x8f, 0x94, + 0xf5, 0x95, 0xbc, 0x1b, 0xb1, 0x95, 0xe8, 0x60, + 0xbb, 0x29, 0xa4, 0xd9, 0x27, 0x2e, 0x00, 0xea, + 0xba, 0xc3, 0x3e, 0xe6, 0x9c, 0xc7, 0xd7, 0x8d, + 0x69, 0xc7, 0xb4, 0xf7, 0x31, 0x4a, 0xb1, 0xf0, + 0x3c, 0xed, 0x06, 0x49, 0x6f, 0x46, 0x99, 0xea, + }; + + byte out[BLAKE2B_OUTBYTES]; + + int ret; + + ret = wc_Blake2bHmac(message1, sizeof(message1), + key1, sizeof(key1), out, sizeof(out)); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + if (XMEMCMP(out, expected1, sizeof(out)) != 0) + return WC_TEST_RET_ENC_NC; + + ret = wc_Blake2bHmac(message2, sizeof(message2), + key2, sizeof(key2), out, sizeof(out)); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + if (XMEMCMP(out, expected2, sizeof(out)) != 0) + return WC_TEST_RET_ENC_NC; + + return 0; +} #endif /* HAVE_BLAKE2 */ -#ifdef HAVE_BLAKE2S +#ifdef HAVE_BLAKE2S #define BLAKE2S_TESTS 3 @@ -4713,6 +4783,56 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t blake2s_test(void) return 0; } + +WOLFSSL_TEST_SUBROUTINE wc_test_ret_t blake2s_hmac_test(void) +{ + static const byte key1[] = {0x41, 0x42, 0x43, 0x44}; /* ABCD */ + static const byte message1[] = {0x48, 0x65, 0x6c, 0x6c, 0x6f}; /* Hello */ + static const byte expected1[] = { + 0x96, 0xca, 0x1d, 0xaa, 0x9a, 0x33, 0x97, 0x3d, + 0xc5, 0x95, 0x3e, 0xce, 0x49, 0x93, 0x75, 0xc1, + 0x2a, 0x7c, 0x8f, 0x5b, 0xf0, 0x28, 0xef, 0xc3, + 0xfb, 0xc5, 0x97, 0xcd, 0xcc, 0x74, 0x44, 0x68, + }; + static const byte key2[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, + 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33 + }; /* 0123456789ABCDEF0123456789ABCDEF0123 */ + static const byte message2[] = { + 0x61, 0x62, 0x63, 0x64, 0x62, 0x63, 0x64, 0x65, 0x63, 0x64, 0x65, 0x66, + 0x64, 0x65, 0x66, 0x67, 0x65, 0x66, 0x67, 0x68, 0x66, 0x67, 0x68, 0x69, + 0x67, 0x68, 0x69, 0x6a, 0x68, 0x69, 0x6a, 0x6b, 0x69, 0x6a, 0x6b, 0x6c, + 0x6a, 0x6b, 0x6c, 0x6d, 0x6b, 0x6c, 0x6d, 0x6e, 0x6c, 0x6d, 0x6e, 0x6f, + 0x6d, 0x6e, 0x6f, 0x70, 0x6e, 0x6f, 0x70, 0x71 + }; /* abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq */ + static const byte expected2[] = { + 0xc4, 0x63, 0xdb, 0x28, 0x97, 0x60, 0x6a, 0xa7, + 0x1e, 0xe6, 0xcf, 0x93, 0x85, 0x3c, 0x90, 0x71, + 0xea, 0x76, 0x7f, 0x6a, 0xa7, 0x20, 0x80, 0x35, + 0xe1, 0x68, 0x95, 0xfe, 0x65, 0x65, 0x43, 0x76, + }; + + byte out[BLAKE2S_OUTBYTES]; + + int ret; + + ret = wc_Blake2sHmac(message1, sizeof(message1), + key1, sizeof(key1), out, sizeof(out)); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + if (XMEMCMP(out, expected1, sizeof(out)) != 0) + return WC_TEST_RET_ENC_NC; + + ret = wc_Blake2sHmac(message2, sizeof(message2), + key2, sizeof(key2), out, sizeof(out)); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + if (XMEMCMP(out, expected2, sizeof(out)) != 0) + return WC_TEST_RET_ENC_NC; + + return 0; +} #endif /* HAVE_BLAKE2S */ diff --git a/wolfssl/wolfcrypt/blake2.h b/wolfssl/wolfcrypt/blake2.h index da66d9ba9..cc6900de5 100644 --- a/wolfssl/wolfcrypt/blake2.h +++ b/wolfssl/wolfcrypt/blake2.h @@ -88,6 +88,9 @@ WOLFSSL_API int wc_InitBlake2b_WithKey(Blake2b* b2b, word32 digestSz, const byte *key, word32 keylen); WOLFSSL_API int wc_Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz); WOLFSSL_API int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz); +WOLFSSL_API int wc_Blake2bHmac(const byte * in, size_t in_len, + const byte * key, size_t key_len, + byte * out, size_t out_len); #endif #ifdef HAVE_BLAKE2S @@ -96,6 +99,9 @@ WOLFSSL_API int wc_InitBlake2s_WithKey(Blake2s* b2s, word32 digestSz, const byte *key, word32 keylen); WOLFSSL_API int wc_Blake2sUpdate(Blake2s* b2s, const byte* data, word32 sz); WOLFSSL_API int wc_Blake2sFinal(Blake2s* b2s, byte* final, word32 requestSz); +WOLFSSL_API int wc_Blake2sHmac(const byte * in, size_t in_len, + const byte * key, size_t key_len, + byte * out, size_t out_len); #endif