Merge pull request #9642 from holtrop-wolfssl/hmac-blake2

Add HMAC-BLAKE2b and HMAC-BLAKE2s API functions
This commit is contained in:
Daniel Pouzzner
2026-01-19 16:49:08 -06:00
committed by GitHub
7 changed files with 755 additions and 19 deletions

5
README
View File

@@ -7,8 +7,9 @@ and feature set. It is commonly used in standard operating environments as well
because of its royalty-free pricing and excellent cross platform support.
wolfSSL supports industry standards up to the current TLS 1.3 and DTLS 1.3
levels, is up to 20 times smaller than OpenSSL, and offers progressive ciphers
such as ChaCha20, Curve25519, and Blake2b. User benchmarking and feedback
reports dramatically better performance when using wolfSSL over OpenSSL.
such as ChaCha20, Curve25519, BLAKE2b/BLAKE2s and Post-Quantum TLS 1.3 groups.
User benchmarking and feedback reports dramatically better performance when
using wolfSSL over OpenSSL.
wolfSSL is powered by the wolfCrypt library. Two versions of the wolfCrypt
cryptography library have been FIPS 140-2 validated (Certificate #2425 and

View File

@@ -8,8 +8,8 @@ standard operating environments as well because of its royalty-free pricing
and excellent cross platform support. wolfSSL supports industry standards up
to the current [TLS 1.3](https://www.wolfssl.com/tls13) and DTLS 1.3, is up to
20 times smaller than OpenSSL, and offers progressive ciphers such as ChaCha20,
Curve25519, Blake2b and Post-Quantum TLS 1.3 groups. User benchmarking and
feedback reports dramatically better performance when using wolfSSL over
Curve25519, BLAKE2b/BLAKE2s and Post-Quantum TLS 1.3 groups. User benchmarking
and feedback reports dramatically better performance when using wolfSSL over
OpenSSL.
wolfSSL is powered by the wolfCrypt cryptography library. Two versions of

View File

@@ -14,7 +14,7 @@
\code
Blake2b b2b;
// initialize Blake2b structure with 64 byte digest
wc_InitBlake2b(&b2b, 64);
wc_InitBlake2b(&b2b, WC_BLAKE2B_DIGEST_SIZE);
\endcode
\sa wc_Blake2bUpdate
@@ -41,13 +41,13 @@ int wc_InitBlake2b(Blake2b* b2b, word32 digestSz);
int ret;
Blake2b b2b;
// initialize Blake2b structure with 64 byte digest
wc_InitBlake2b(&b2b, 64);
wc_InitBlake2b(&b2b, WC_BLAKE2B_DIGEST_SIZE);
byte plain[] = { // initialize input };
ret = wc_Blake2bUpdate(&b2b, plain, sizeof(plain));
if( ret != 0) {
// error updating blake2b
if (ret != 0) {
// error updating blake2b
}
\endcode
@@ -78,14 +78,14 @@ int wc_Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz);
\code
int ret;
Blake2b b2b;
byte hash[64];
byte hash[WC_BLAKE2B_DIGEST_SIZE];
// initialize Blake2b structure with 64 byte digest
wc_InitBlake2b(&b2b, 64);
wc_InitBlake2b(&b2b, WC_BLAKE2B_DIGEST_SIZE);
... // call wc_Blake2bUpdate to add data to hash
ret = wc_Blake2bFinal(&b2b, hash, 64);
if( ret != 0) {
// error generating blake2b hash
ret = wc_Blake2bFinal(&b2b, hash, WC_BLAKE2B_DIGEST_SIZE);
if (ret != 0) {
// error generating blake2b hash
}
\endcode
@@ -93,3 +93,326 @@ int wc_Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz);
\sa wc_Blake2bUpdate
*/
int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz);
/*!
\ingroup BLAKE2
\brief Initialize an HMAC-BLAKE2b message authentication code computation.
\return 0 Returned upon successfully initializing the HMAC-BLAKE2b MAC
computation.
\param b2b Blake2b structure to be used for the MAC computation.
\param key pointer to the key
\param key_len length of the key
_Example_
\code
Blake2b b2b;
int ret;
byte key[] = {4, 5, 6};
ret = wc_Blake2bHmacInit(&b2b, key);
if (ret != 0) {
// error generating HMAC-BLAKE2b
}
\endcode
*/
int wc_Blake2bHmacInit(Blake2b * b2b,
const byte * key, size_t key_len);
/*!
\ingroup BLAKE2
\brief Update an HMAC-BLAKE2b message authentication code computation with
additional input data.
\return 0 Returned upon successfully updating the HMAC-BLAKE2b MAC
computation.
\param b2b Blake2b structure to be used for the MAC computation.
\param in pointer to the input data
\param in_len length of the input data
_Example_
\code
Blake2b b2b;
int ret;
byte key[] = {4, 5, 6};
byte data[] = {1, 2, 3};
ret = wc_Blake2bHmacInit(&b2b, key, sizeof(key));
ret = wc_Blake2bHmacUpdate(&b2b, data, sizeof(data));
\endcode
*/
int wc_Blake2bHmacUpdate(Blake2b * b2b,
const byte * in, size_t in_len);
/*!
\ingroup BLAKE2
\brief Finalize an HMAC-BLAKE2b message authentication code computation.
\return 0 Returned upon successfully finalizing the HMAC-BLAKE2b MAC
computation.
\param b2b Blake2b structure to be used for the MAC computation.
\param key pointer to the key
\param key_len length of the key
\param out output buffer to store computed MAC
\param out_len length of output buffer
_Example_
\code
Blake2b b2b;
int ret;
byte key[] = {4, 5, 6};
byte data[] = {1, 2, 3};
byte mac[WC_BLAKE2B_DIGEST_SIZE];
ret = wc_Blake2bHmacInit(&b2b, key, sizeof(key));
ret = wc_Blake2bHmacUpdate(&b2b, data, sizeof(data));
ret = wc_Blake2bHmacFinalize(&b2b, key, sizeof(key), mac, sizezof(mac));
\endcode
*/
int wc_Blake2bHmacFinal(Blake2b * b2b,
const byte * key, size_t key_len,
byte * out, size_t out_len);
/*!
\ingroup BLAKE2
\brief Compute the HMAC-BLAKE2b message authentication code of the given
input data using the given key.
\return 0 Returned upon successfully computing the HMAC-BLAKE2b MAC.
\param in pointer to the input data
\param in_len length of the input data
\param key pointer to the key
\param key_len length of the key
\param out output buffer to store computed MAC
\param out_len length of output buffer
_Example_
\code
int ret;
byte mac[WC_BLAKE2B_DIGEST_SIZE];
byte data[] = {1, 2, 3};
byte key[] = {4, 5, 6};
ret = wc_Blake2bHmac(data, sizeof(data), key, sizeof(key), mac, sizeof(mac));
if (ret != 0) {
// error generating HMAC-BLAKE2b
}
\endcode
*/
int wc_Blake2bHmac(const byte * in, size_t in_len,
const byte * key, size_t key_len,
byte * out, size_t out_len);
/*!
\ingroup BLAKE2
\brief This function initializes a Blake2s structure for use with the
Blake2 hash function.
\return 0 Returned upon successfully initializing the Blake2s structure and
setting the digest size.
\param b2s pointer to the Blake2s structure to initialize
\param digestSz length of the blake 2 digest to implement
_Example_
\code
Blake2s b2s;
// initialize Blake2s structure with 32 byte digest
wc_InitBlake2s(&b2s, WC_BLAKE2S_DIGEST_SIZE);
\endcode
\sa wc_Blake2sUpdate
*/
int wc_InitBlake2s(Blake2s* b2s, word32 digestSz);
/*!
\ingroup BLAKE2
\brief This function updates the Blake2s hash with the given input data.
This function should be called after wc_InitBlake2s, and repeated until
one is ready for the final hash: wc_Blake2sFinal.
\return 0 Returned upon successfully update the Blake2s structure with
the given data
\return -1 Returned if there is a failure while compressing the input data
\param b2s pointer to the Blake2s structure to update
\param data pointer to a buffer containing the data to append
\param sz length of the input data to append
_Example_
\code
int ret;
Blake2s b2s;
// initialize Blake2s structure with 32 byte digest
wc_InitBlake2s(&b2s, WC_BLAKE2S_DIGEST_SIZE);
byte plain[] = { // initialize input };
ret = wc_Blake2sUpdate(&b2s, plain, sizeof(plain));
if (ret != 0) {
// error updating blake2s
}
\endcode
\sa wc_InitBlake2s
\sa wc_Blake2sFinal
*/
int wc_Blake2sUpdate(Blake2s* b2s, const byte* data, word32 sz);
/*!
\ingroup BLAKE2
\brief This function computes the Blake2s hash of the previously supplied
input data. The output hash will be of length requestSz, or, if
requestSz==0, the digestSz of the b2s structure. This function should be
called after wc_InitBlake2s and wc_Blake2sUpdate has been processed for
each piece of input data desired.
\return 0 Returned upon successfully computing the Blake2s hash
\return -1 Returned if there is a failure while parsing the Blake2s hash
\param b2s pointer to the Blake2s structure to update
\param final pointer to a buffer in which to store the blake2s hash.
Should be of length requestSz
\param requestSz length of the digest to compute. When this is zero,
b2s->digestSz will be used instead
_Example_
\code
int ret;
Blake2s b2s;
byte hash[WC_BLAKE2S_DIGEST_SIZE];
// initialize Blake2s structure with 32 byte digest
wc_InitBlake2s(&b2s, WC_BLAKE2S_DIGEST_SIZE);
... // call wc_Blake2sUpdate to add data to hash
ret = wc_Blake2sFinal(&b2s, hash, WC_BLAKE2S_DIGEST_SIZE);
if (ret != 0) {
// error generating blake2s hash
}
\endcode
\sa wc_InitBlake2s
\sa wc_Blake2sUpdate
*/
int wc_Blake2sFinal(Blake2s* b2s, byte* final, word32 requestSz);
/*!
\ingroup BLAKE2
\brief Initialize an HMAC-BLAKE2s message authentication code computation.
\return 0 Returned upon successfully initializing the HMAC-BLAKE2s MAC
computation.
\param b2s Blake2s structure to be used for the MAC computation.
\param key pointer to the key
\param key_len length of the key
_Example_
\code
Blake2s b2s;
int ret;
byte key[] = {4, 5, 6};
ret = wc_Blake2sHmacInit(&b2s, key);
if (ret != 0) {
// error generating HMAC-BLAKE2s
}
\endcode
*/
int wc_Blake2sHmacInit(Blake2s * b2s,
const byte * key, size_t key_len);
/*!
\ingroup BLAKE2
\brief Update an HMAC-BLAKE2s message authentication code computation with
additional input data.
\return 0 Returned upon successfully updating the HMAC-BLAKE2s MAC
computation.
\param b2s Blake2s structure to be used for the MAC computation.
\param in pointer to the input data
\param in_len length of the input data
_Example_
\code
Blake2s b2s;
int ret;
byte key[] = {4, 5, 6};
byte data[] = {1, 2, 3};
ret = wc_Blake2sHmacInit(&b2s, key, sizeof(key));
ret = wc_Blake2sHmacUpdate(&b2s, data, sizeof(data));
\endcode
*/
int wc_Blake2sHmacUpdate(Blake2s * b2s,
const byte * in, size_t in_len);
/*!
\ingroup BLAKE2
\brief Finalize an HMAC-BLAKE2s message authentication code computation.
\return 0 Returned upon successfully finalizing the HMAC-BLAKE2s MAC
computation.
\param b2s Blake2s structure to be used for the MAC computation.
\param key pointer to the key
\param key_len length of the key
\param out output buffer to store computed MAC
\param out_len length of output buffer
_Example_
\code
Blake2s b2s;
int ret;
byte key[] = {4, 5, 6};
byte data[] = {1, 2, 3};
byte mac[WC_BLAKE2S_DIGEST_SIZE];
ret = wc_Blake2sHmacInit(&b2s, key, sizeof(key));
ret = wc_Blake2sHmacUpdate(&b2s, data, sizeof(data));
ret = wc_Blake2sHmacFinalize(&b2s, key, sizeof(key), mac, sizezof(mac));
\endcode
*/
int wc_Blake2sHmacFinal(Blake2s * b2s,
const byte * key, size_t key_len,
byte * out, size_t out_len);
/*!
\ingroup BLAKE2
\brief This function computes the HMAC-BLAKE2s message authentication code
of the given input data using the given key.
\return 0 Returned upon successfully computing the HMAC-BLAKE2s MAC.
\param in pointer to the input data
\param in_len length of the input data
\param key pointer to the key
\param key_len length of the key
\param out output buffer to store computed MAC
\param out_len length of output buffer
_Example_
\code
int ret;
byte mac[WC_BLAKE2S_DIGEST_SIZE];
byte data[] = {1, 2, 3};
byte key[] = {4, 5, 6};
ret = wc_Blake2sHmac(data, sizeof(data), key, sizeof(key), mac, sizeof(mac));
if (ret != 0) {
// error generating HMAC-BLAKE2s
}
\endcode
*/
int wc_Blake2sHmac(const byte * in, size_t in_len,
const byte * key, size_t key_len,
byte * out, size_t out_len);

View File

@@ -37,6 +37,12 @@
#include <wolfssl/wolfcrypt/blake2.h>
#include <wolfssl/wolfcrypt/blake2-impl.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
static const word64 blake2b_IV[8] =
{
@@ -511,7 +517,111 @@ int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz)
}
/* end CTaoCrypt API */
int wc_Blake2bHmacInit(Blake2b* b2b, const byte* key, size_t key_len)
{
byte x_key[BLAKE2B_BLOCKBYTES];
int i;
int ret = 0;
if (key == NULL)
return BAD_FUNC_ARG;
if (key_len > BLAKE2B_BLOCKBYTES) {
ret = wc_InitBlake2b(b2b, BLAKE2B_OUTBYTES);
if (ret == 0)
ret = wc_Blake2bUpdate(b2b, key, (word32)key_len);
if (ret == 0)
ret = wc_Blake2bFinal(b2b, x_key, 0);
} else {
XMEMCPY(x_key, key, key_len);
XMEMSET(x_key + key_len, 0, BLAKE2B_BLOCKBYTES - key_len);
}
if (ret == 0) {
for (i = 0; i < BLAKE2B_BLOCKBYTES; ++i)
x_key[i] ^= 0x36U;
}
if (ret == 0)
ret = wc_InitBlake2b(b2b, BLAKE2B_OUTBYTES);
if (ret == 0)
ret = wc_Blake2bUpdate(b2b, x_key, BLAKE2B_BLOCKBYTES);
ForceZero(x_key, sizeof(x_key));
return ret;
}
int wc_Blake2bHmacUpdate(Blake2b* b2b, const byte* in, size_t in_len)
{
if (in == NULL)
return BAD_FUNC_ARG;
return wc_Blake2bUpdate(b2b, in, (word32)in_len);
}
int wc_Blake2bHmacFinal(Blake2b* b2b, const byte* key, size_t key_len,
byte* out, size_t out_len)
{
byte x_key[BLAKE2B_BLOCKBYTES];
int i;
int ret = 0;
if (key == NULL)
return BAD_FUNC_ARG;
if (out_len != BLAKE2B_OUTBYTES)
return BUFFER_E;
if (key_len > BLAKE2B_BLOCKBYTES) {
ret = wc_InitBlake2b(b2b, BLAKE2B_OUTBYTES);
if (ret == 0)
ret = wc_Blake2bUpdate(b2b, key, (word32)key_len);
if (ret == 0)
ret = wc_Blake2bFinal(b2b, x_key, 0);
} else {
XMEMCPY(x_key, key, key_len);
XMEMSET(x_key + key_len, 0, BLAKE2B_BLOCKBYTES - key_len);
}
if (ret == 0) {
for (i = 0; i < BLAKE2B_BLOCKBYTES; ++i)
x_key[i] ^= 0x5CU;
}
if (ret == 0)
ret = wc_Blake2bFinal(b2b, out, 0);
if (ret == 0)
ret = wc_InitBlake2b(b2b, BLAKE2B_OUTBYTES);
if (ret == 0)
ret = wc_Blake2bUpdate(b2b, x_key, BLAKE2B_BLOCKBYTES);
if (ret == 0)
ret = wc_Blake2bUpdate(b2b, out, BLAKE2B_OUTBYTES);
if (ret == 0)
ret = wc_Blake2bFinal(b2b, out, 0);
ForceZero(x_key, sizeof(x_key));
return ret;
}
int wc_Blake2bHmac(const byte* in, size_t in_len,
const byte* key, size_t key_len,
byte* out, size_t out_len)
{
Blake2b state;
int ret;
ret = wc_Blake2bHmacInit(&state, key, key_len);
if (ret == 0)
ret = wc_Blake2bHmacUpdate(&state, in, in_len);
if (ret == 0)
ret = wc_Blake2bHmacFinal(&state, key, key_len, out, out_len);
return ret;
}
/* end wolfCrypt API */
#endif /* HAVE_BLAKE2 */

View File

@@ -37,6 +37,12 @@
#include <wolfssl/wolfcrypt/blake2.h>
#include <wolfssl/wolfcrypt/blake2-impl.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
static const word32 blake2s_IV[8] =
{
@@ -505,7 +511,111 @@ int wc_Blake2sFinal(Blake2s* b2s, byte* final, word32 requestSz)
}
/* end CTaoCrypt API */
int wc_Blake2sHmacInit(Blake2s* b2s, const byte* key, size_t key_len)
{
byte x_key[BLAKE2S_BLOCKBYTES];
int i;
int ret = 0;
if (key == NULL)
return BAD_FUNC_ARG;
if (key_len > BLAKE2S_BLOCKBYTES) {
ret = wc_InitBlake2s(b2s, BLAKE2S_OUTBYTES);
if (ret == 0)
ret = wc_Blake2sUpdate(b2s, key, (word32)key_len);
if (ret == 0)
ret = wc_Blake2sFinal(b2s, x_key, 0);
} else {
XMEMCPY(x_key, key, key_len);
XMEMSET(x_key + key_len, 0, BLAKE2S_BLOCKBYTES - key_len);
}
if (ret == 0) {
for (i = 0; i < BLAKE2S_BLOCKBYTES; ++i)
x_key[i] ^= 0x36U;
}
if (ret == 0)
ret = wc_InitBlake2s(b2s, BLAKE2S_OUTBYTES);
if (ret == 0)
ret = wc_Blake2sUpdate(b2s, x_key, BLAKE2S_BLOCKBYTES);
ForceZero(x_key, sizeof(x_key));
return ret;
}
int wc_Blake2sHmacUpdate(Blake2s* b2s, const byte* in, size_t in_len)
{
if (in == NULL)
return BAD_FUNC_ARG;
return wc_Blake2sUpdate(b2s, in, (word32)in_len);
}
int wc_Blake2sHmacFinal(Blake2s* b2s, const byte* key, size_t key_len,
byte* out, size_t out_len)
{
byte x_key[BLAKE2S_BLOCKBYTES];
int i;
int ret = 0;
if (key == NULL)
return BAD_FUNC_ARG;
if (out_len != BLAKE2S_OUTBYTES)
return BUFFER_E;
if (key_len > BLAKE2S_BLOCKBYTES) {
ret = wc_InitBlake2s(b2s, BLAKE2S_OUTBYTES);
if (ret == 0)
ret = wc_Blake2sUpdate(b2s, key, (word32)key_len);
if (ret == 0)
ret = wc_Blake2sFinal(b2s, x_key, 0);
} else {
XMEMCPY(x_key, key, key_len);
XMEMSET(x_key + key_len, 0, BLAKE2S_BLOCKBYTES - key_len);
}
if (ret == 0) {
for (i = 0; i < BLAKE2S_BLOCKBYTES; ++i)
x_key[i] ^= 0x5CU;
}
if (ret == 0)
ret = wc_Blake2sFinal(b2s, out, 0);
if (ret == 0)
ret = wc_InitBlake2s(b2s, BLAKE2S_OUTBYTES);
if (ret == 0)
ret = wc_Blake2sUpdate(b2s, x_key, BLAKE2S_BLOCKBYTES);
if (ret == 0)
ret = wc_Blake2sUpdate(b2s, out, BLAKE2S_OUTBYTES);
if (ret == 0)
ret = wc_Blake2sFinal(b2s, out, 0);
ForceZero(x_key, sizeof(x_key));
return ret;
}
int wc_Blake2sHmac(const byte* in, size_t in_len,
const byte* key, size_t key_len,
byte* out, size_t out_len)
{
Blake2s state;
int ret;
ret = wc_Blake2sHmacInit(&state, key, key_len);
if (ret == 0)
ret = wc_Blake2sHmacUpdate(&state, in, in_len);
if (ret == 0)
ret = wc_Blake2sHmacFinal(&state, key, key_len, out, out_len);
return ret;
}
/* end wolfCrypt API */
#endif /* HAVE_BLAKE2S */

View File

@@ -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,97 @@ 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;
Blake2b b2b;
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;
ret = wc_Blake2bHmacInit(&b2b, key1, sizeof(key1));
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2bHmacUpdate(&b2b, message1, sizeof(message1) / 2U);
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2bHmacUpdate(&b2b, &message1[sizeof(message1) / 2U], sizeof(message1) - sizeof(message1) / 2U);
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2bHmacFinal(&b2b, key1, sizeof(key1), out, sizeof(out));
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2bHmacInit(&b2b, key2, sizeof(key2));
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2bHmacUpdate(&b2b, message2, sizeof(message2) / 2U);
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2bHmacUpdate(&b2b, &message2[sizeof(message2) / 2U], sizeof(message2) - sizeof(message2) / 2U);
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2bHmacFinal(&b2b, key2, sizeof(key2), out, sizeof(out));
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
return 0;
}
#endif /* HAVE_BLAKE2 */
#ifdef HAVE_BLAKE2S
#ifdef HAVE_BLAKE2S
#define BLAKE2S_TESTS 3
@@ -4713,6 +4809,82 @@ 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;
Blake2s b2s;
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;
ret = wc_Blake2sHmacInit(&b2s, key1, sizeof(key1));
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2sHmacUpdate(&b2s, message1, sizeof(message1) / 2U);
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2sHmacUpdate(&b2s, &message1[sizeof(message1) / 2U], sizeof(message1) - sizeof(message1) / 2U);
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2sHmacFinal(&b2s, key1, sizeof(key1), out, sizeof(out));
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2sHmacInit(&b2s, key2, sizeof(key2));
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2sHmacUpdate(&b2s, message2, sizeof(message2) / 2U);
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2sHmacUpdate(&b2s, &message2[sizeof(message2) / 2U], sizeof(message2) - sizeof(message2) / 2U);
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
ret = wc_Blake2sHmacFinal(&b2s, key2, sizeof(key2), out, sizeof(out));
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
return 0;
}
#endif /* HAVE_BLAKE2S */

View File

@@ -88,6 +88,16 @@ 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_Blake2bHmacInit(Blake2b* b2b,
const byte* key, size_t key_len);
WOLFSSL_API int wc_Blake2bHmacUpdate(Blake2b* b2b,
const byte* in, size_t in_len);
WOLFSSL_API int wc_Blake2bHmacFinal(Blake2b* b2b,
const byte* key, size_t key_len,
byte* out, size_t out_len);
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 +106,16 @@ 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_Blake2sHmacInit(Blake2s* b2s,
const byte* key, size_t key_len);
WOLFSSL_API int wc_Blake2sHmacUpdate(Blake2s* b2s,
const byte* in, size_t in_len);
WOLFSSL_API int wc_Blake2sHmacFinal(Blake2s* b2s,
const byte* key, size_t key_len,
byte* out, size_t out_len);
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