diff --git a/tests/api/test_chacha20_poly1305.c b/tests/api/test_chacha20_poly1305.c index 6f90c71712..921cf20b49 100644 --- a/tests/api/test_chacha20_poly1305.c +++ b/tests/api/test_chacha20_poly1305.c @@ -526,11 +526,11 @@ int test_wc_ChaCha20Poly1305_Stream(void) /* wc_ChaCha20Poly1305_Final: NULL aead */ ExpectIntEQ(wc_ChaCha20Poly1305_Final(NULL, outTag), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); - /* wc_ChaCha20Poly1305_Final: wrong state (INIT, not AAD/DATA) */ + /* wc_ChaCha20Poly1305_Final: READY state (Init, no UpdateAad/UpdateData) + * is valid -- RFC 8439 Section 2.8 permits empty plaintext + empty AAD. */ ExpectIntEQ(wc_ChaCha20Poly1305_Init(&aead, key, iv, CHACHA20_POLY1305_AEAD_ENCRYPT), 0); - ExpectIntEQ(wc_ChaCha20Poly1305_Final(&aead, outTag), - WC_NO_ERR_TRACE(BAD_STATE_E)); + ExpectIntEQ(wc_ChaCha20Poly1305_Final(&aead, outTag), 0); #endif return EXPECT_RESULT(); } /* END test_wc_ChaCha20Poly1305_Stream */ diff --git a/wolfcrypt/src/chacha20_poly1305.c b/wolfcrypt/src/chacha20_poly1305.c index 75b9b094d1..a53cec65e8 100644 --- a/wolfcrypt/src/chacha20_poly1305.c +++ b/wolfcrypt/src/chacha20_poly1305.c @@ -275,7 +275,8 @@ int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead, if (aead == NULL || outAuthTag == NULL) { return BAD_FUNC_ARG; } - if (aead->state != CHACHA20_POLY1305_STATE_AAD && + if (aead->state != CHACHA20_POLY1305_STATE_READY && + aead->state != CHACHA20_POLY1305_STATE_AAD && aead->state != CHACHA20_POLY1305_STATE_DATA) { return BAD_STATE_E; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index cd3275650b..0b32f05636 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -11790,6 +11790,22 @@ static wc_test_ret_t chacha20_poly1305_oneshot_test(void) static wc_test_ret_t chacha20_poly1305_stream_param_test(void) { + /* Wycheproof tc2: empty plaintext + empty AAD (valid per RFC 8439 Section 2.8) */ + WOLFSSL_SMALL_STACK_STATIC const byte key_tc2[] = { + 0x80, 0xba, 0x31, 0x92, 0xc8, 0x03, 0xce, 0x96, + 0x5e, 0xa3, 0x71, 0xd5, 0xff, 0x07, 0x3c, 0xf0, + 0xf4, 0x3b, 0x6a, 0x2a, 0xb5, 0x76, 0xb2, 0x08, + 0x42, 0x6e, 0x11, 0x40, 0x9c, 0x09, 0xb9, 0xb0 + }; + WOLFSSL_SMALL_STACK_STATIC const byte iv_tc2[] = { + 0x4d, 0xa5, 0xbf, 0x8d, 0xfd, 0x58, 0x52, 0xc1, + 0xea, 0x12, 0x37, 0x9d + }; + WOLFSSL_SMALL_STACK_STATIC const byte authTag_tc2[] = { + 0x76, 0xac, 0xb3, 0x42, 0xcf, 0x31, 0x66, 0xa5, + 0xb6, 0x3c, 0x0c, 0x0e, 0xa1, 0x38, 0x3c, 0x8d + }; + const byte* key1 = chacha20_poly1305_test1_key; const byte* iv1 = chacha20_poly1305_test1_iv; const byte* aad1 = chacha20_poly1305_test1_aad; @@ -11863,10 +11879,16 @@ static wc_test_ret_t chacha20_poly1305_stream_param_test(void) err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); if (err != WC_NO_ERR_TRACE(BAD_STATE_E)) return WC_TEST_RET_ENC_EC(err); - aead.state = CHACHA20_POLY1305_STATE_READY; + /* Wycheproof tc2: empty plaintext + empty AAD must succeed (RFC 8439 Section 2.8) */ + err = wc_ChaCha20Poly1305_Init(&aead, key_tc2, iv_tc2, + CHACHA20_POLY1305_AEAD_ENCRYPT); + if (err != 0) + return WC_TEST_RET_ENC_EC(err); err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); - if (err != WC_NO_ERR_TRACE(BAD_STATE_E)) + if (err != 0) return WC_TEST_RET_ENC_EC(err); + if (XMEMCMP(generatedAuthTag, authTag_tc2, sizeof(authTag_tc2)) != 0) + return WC_TEST_RET_ENC_NC; return 0; }