From b6b8de1f5975f261e9d91f430f82a477cd0670b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Wed, 1 Apr 2026 08:22:28 +0200 Subject: [PATCH] Add bounds checks for Blake2 digest size --- tests/api/test_blake2.c | 36 ++++++++++++++++++++++++++++++++++++ wolfcrypt/src/blake2b.c | 9 +++++++++ wolfcrypt/src/blake2s.c | 9 +++++++++ 3 files changed, 54 insertions(+) diff --git a/tests/api/test_blake2.c b/tests/api/test_blake2.c index 9cbd11de85..2067997fa2 100644 --- a/tests/api/test_blake2.c +++ b/tests/api/test_blake2.c @@ -50,6 +50,12 @@ int test_wc_InitBlake2b(void) ExpectIntEQ(wc_InitBlake2b(&blake, 128), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_InitBlake2b(NULL, WC_BLAKE2B_DIGEST_SIZE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* digestSz values that truncate via (byte) cast to a valid size must be + * rejected: 257 mod 256 = 1, 320 mod 256 = 64 - both within BLAKE2B range */ + ExpectIntEQ(wc_InitBlake2b(&blake, 257), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_InitBlake2b(&blake, 256 + BLAKE2B_OUTBYTES), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Test good arg. */ ExpectIntEQ(wc_InitBlake2b(&blake, WC_BLAKE2B_DIGEST_SIZE), 0); @@ -82,6 +88,12 @@ int test_wc_InitBlake2b_WithKey(void) ExpectIntEQ(wc_InitBlake2b_WithKey(NULL, digestSz, key, keylen), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* digestSz that truncates to a valid byte-sized value must be rejected */ + ExpectIntEQ(wc_InitBlake2b_WithKey(&blake, 257, NULL, keylen), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_InitBlake2b_WithKey(&blake, 256 + BLAKE2B_OUTBYTES, NULL, keylen), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Test good arg. */ ExpectIntEQ(wc_InitBlake2b_WithKey(&blake, digestSz, NULL, keylen), 0); ExpectIntEQ(wc_InitBlake2b_WithKey(&blake, digestSz, key, keylen), 0); @@ -127,8 +139,14 @@ int test_wc_Blake2bFinal(void) ExpectIntEQ(wc_Blake2bFinal(&blake, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_Blake2bFinal(NULL, hash, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* requestSz that truncates to valid byte must be rejected */ + ExpectIntEQ(wc_Blake2bFinal(&blake, hash, 257), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_Blake2bFinal(&blake, hash, 256 + BLAKE2B_OUTBYTES), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Test good args. */ + ExpectIntEQ(wc_InitBlake2b(&blake, WC_BLAKE2B_DIGEST_SIZE), 0); ExpectIntEQ(wc_Blake2bFinal(&blake, hash, WC_BLAKE2B_DIGEST_SIZE), 0); #endif return EXPECT_RESULT(); @@ -322,6 +340,12 @@ int test_wc_InitBlake2s(void) ExpectIntEQ(wc_InitBlake2s(&blake, 128), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_InitBlake2s(NULL, WC_BLAKE2S_DIGEST_SIZE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* digestSz that truncates via (byte) cast to a valid size must be rejected: + * 257 mod 256 = 1, 288 mod 256 = 32 - both within BLAKE2S range */ + ExpectIntEQ(wc_InitBlake2s(&blake, 257), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_InitBlake2s(&blake, 256 + BLAKE2S_OUTBYTES), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Test good arg. */ ExpectIntEQ(wc_InitBlake2s(&blake, WC_BLAKE2S_DIGEST_SIZE), 0); @@ -352,6 +376,12 @@ int test_wc_InitBlake2s_WithKey(void) ExpectIntEQ(wc_InitBlake2s_WithKey(NULL, digestSz, key, keylen), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* digestSz that truncates to a valid byte-sized value must be rejected */ + ExpectIntEQ(wc_InitBlake2s_WithKey(&blake, 257, NULL, keylen), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_InitBlake2s_WithKey(&blake, 256 + BLAKE2S_OUTBYTES, NULL, keylen), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Test good arg. */ ExpectIntEQ(wc_InitBlake2s_WithKey(&blake, digestSz, NULL, keylen), 0); ExpectIntEQ(wc_InitBlake2s_WithKey(&blake, digestSz, key, keylen), 0); @@ -397,8 +427,14 @@ int test_wc_Blake2sFinal(void) ExpectIntEQ(wc_Blake2sFinal(&blake, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_Blake2sFinal(NULL, hash, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* requestSz that truncates to valid byte must be rejected */ + ExpectIntEQ(wc_Blake2sFinal(&blake, hash, 257), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_Blake2sFinal(&blake, hash, 256 + BLAKE2S_OUTBYTES), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Test good args. */ + ExpectIntEQ(wc_InitBlake2s(&blake, WC_BLAKE2S_DIGEST_SIZE), 0); ExpectIntEQ(wc_Blake2sFinal(&blake, hash, WC_BLAKE2S_DIGEST_SIZE), 0); #endif return EXPECT_RESULT(); diff --git a/wolfcrypt/src/blake2b.c b/wolfcrypt/src/blake2b.c index 90776bbef1..7e7b60bab9 100644 --- a/wolfcrypt/src/blake2b.c +++ b/wolfcrypt/src/blake2b.c @@ -426,6 +426,9 @@ int wc_InitBlake2b(Blake2b* b2b, word32 digestSz) if (b2b == NULL){ return BAD_FUNC_ARG; } + if (digestSz == 0 || digestSz > BLAKE2B_OUTBYTES) { + return BAD_FUNC_ARG; + } b2b->digestSz = digestSz; return blake2b_init(b2b->S, (byte)digestSz); @@ -437,6 +440,9 @@ int wc_InitBlake2b_WithKey(Blake2b* b2b, word32 digestSz, const byte *key, word3 if (b2b == NULL){ return BAD_FUNC_ARG; } + if (digestSz == 0 || digestSz > BLAKE2B_OUTBYTES) { + return BAD_FUNC_ARG; + } b2b->digestSz = digestSz; if (keylen >= 256) @@ -478,6 +484,9 @@ int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz) } sz = requestSz ? requestSz : b2b->digestSz; + if (sz == 0 || sz > BLAKE2B_OUTBYTES) { + return BAD_FUNC_ARG; + } return blake2b_final(b2b->S, final, (byte)sz); } diff --git a/wolfcrypt/src/blake2s.c b/wolfcrypt/src/blake2s.c index ee105209bb..ae48b9b3d8 100644 --- a/wolfcrypt/src/blake2s.c +++ b/wolfcrypt/src/blake2s.c @@ -421,6 +421,9 @@ int wc_InitBlake2s(Blake2s* b2s, word32 digestSz) if (b2s == NULL){ return BAD_FUNC_ARG; } + if (digestSz == 0 || digestSz > BLAKE2S_OUTBYTES) { + return BAD_FUNC_ARG; + } b2s->digestSz = digestSz; return blake2s_init(b2s->S, (byte)digestSz); @@ -433,6 +436,9 @@ int wc_InitBlake2s_WithKey(Blake2s* b2s, word32 digestSz, const byte *key, word3 if (b2s == NULL){ return BAD_FUNC_ARG; } + if (digestSz == 0 || digestSz > BLAKE2S_OUTBYTES) { + return BAD_FUNC_ARG; + } b2s->digestSz = digestSz; if (keylen >= 256) @@ -475,6 +481,9 @@ int wc_Blake2sFinal(Blake2s* b2s, byte* final, word32 requestSz) } sz = requestSz ? requestSz : b2s->digestSz; + if (sz == 0 || sz > BLAKE2S_OUTBYTES) { + return BAD_FUNC_ARG; + } return blake2s_final(b2s->S, final, (byte)sz); }