Skip to content

Commit 4c49ea4

Browse files
committed
Fix ChaCha20-Poly1305 and RSA-OAEP to allow empty plaintext
ChaCha20-Poly1305 Final() rejected the READY state (no data or AAD provided), though RFC 8439 §2.8 explicitly permits empty plaintext and produces a well-defined authentication tag. RSA-OAEP rejected zero-length plaintexts at both encrypt and decrypt. RFC 8017 §7.1.1 permits empty messages; OpenSSL and BoringSSL both accept them. Found via Wycheproof test vectors.
1 parent c4c71ee commit 4c49ea4

2 files changed

Lines changed: 18 additions & 4 deletions

File tree

wolfcrypt/src/chacha20_poly1305.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,8 @@ int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead,
275275
if (aead == NULL || outAuthTag == NULL) {
276276
return BAD_FUNC_ARG;
277277
}
278-
if (aead->state != CHACHA20_POLY1305_STATE_AAD &&
278+
if (aead->state != CHACHA20_POLY1305_STATE_READY &&
279+
aead->state != CHACHA20_POLY1305_STATE_AAD &&
279280
aead->state != CHACHA20_POLY1305_STATE_DATA) {
280281
return BAD_STATE_E;
281282
}

wolfcrypt/src/rsa.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3437,7 +3437,15 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
34373437
RsaPadding padding;
34383438
#endif
34393439

3440-
if (in == NULL || inLen == 0 || out == NULL || key == NULL) {
3440+
if (out == NULL || key == NULL) {
3441+
return BAD_FUNC_ARG;
3442+
}
3443+
3444+
/* For OAEP padding (RFC 8017, Section 7.1.1), zero-length messages are
3445+
* permitted: the spec requires mLen <= k - 2*hLen - 2, and mLen = 0
3446+
* satisfies this for all supported key sizes. For other padding types,
3447+
* a zero-length input is invalid. */
3448+
if (in == NULL || (inLen == 0 && pad_type != WC_RSA_OAEP_PAD)) {
34413449
return BAD_FUNC_ARG;
34423450
}
34433451

@@ -3837,8 +3845,13 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out,
38373845
ret = ctMaskSelInt(ctMaskLTE(ret, (int)outLen), ret,
38383846
WC_NO_ERR_TRACE(RSA_BUFFER_E));
38393847
#ifndef WOLFSSL_RSA_DECRYPT_TO_0_LEN
3840-
ret = ctMaskSelInt(ctMaskNotEq(ret, 0), ret,
3841-
WC_NO_ERR_TRACE(RSA_BUFFER_E));
3848+
/* RFC 8017 Section 7.1.2: OAEP decryption may produce a valid
3849+
* zero-length message. Only reject ret==0 for non-OAEP types. */
3850+
{
3851+
int zeroOk = ctMaskEq(pad_type, WC_RSA_OAEP_PAD);
3852+
ret = ctMaskSelInt(ctMaskNotEq(ret, 0) | zeroOk, ret,
3853+
WC_NO_ERR_TRACE(RSA_BUFFER_E));
3854+
}
38423855
#endif
38433856
#else
38443857
if (outLen < (word32)ret)

0 commit comments

Comments
 (0)