Skip to content

Commit e8e7cd1

Browse files
MarkAtwoodclaude
andcommitted
Fix RSA-OAEP to allow zero-length plaintext per RFC 8017
RsaPublicEncryptEx() rejected inLen==0 unconditionally with BAD_FUNC_ARG. RFC 8017 Section 7.1.1 (RSAES-OAEP-ENCRYPT) permits zero-length messages: the only length constraint is mLen <= k - 2*hLen - 2, which mLen=0 always satisfies. RsaPrivateDecryptEx() converted a zero-length decryption result to RSA_BUFFER_E (unless WOLFSSL_RSA_DECRYPT_TO_0_LEN was defined). RFC 8017 Section 7.1.2 (RSAES-OAEP-DECRYPT) produces the original message M which may be empty. The fix uses constant-time masking to allow ret==0 when pad_type is WC_RSA_OAEP_PAD, preserving the existing timing-safe behavior for other padding types. Both OpenSSL and BoringSSL accept empty OAEP plaintexts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Found via Wycheproof test vectors.
1 parent d343ea6 commit e8e7cd1

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

wolfcrypt/src/rsa.c

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

3357-
if (in == NULL || inLen == 0 || out == NULL || key == NULL) {
3357+
if (out == NULL || key == NULL) {
3358+
return BAD_FUNC_ARG;
3359+
}
3360+
3361+
/* For OAEP padding (RFC 8017, Section 7.1.1), zero-length messages are
3362+
* permitted: the spec requires mLen <= k - 2*hLen - 2, and mLen = 0
3363+
* satisfies this for all supported key sizes. For other padding types,
3364+
* a zero-length input is invalid. */
3365+
if (in == NULL || (inLen == 0 && pad_type != WC_RSA_OAEP_PAD)) {
33583366
return BAD_FUNC_ARG;
33593367
}
33603368

@@ -3752,8 +3760,13 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out,
37523760
ret = ctMaskSelInt(ctMaskLTE(ret, (int)outLen), ret,
37533761
WC_NO_ERR_TRACE(RSA_BUFFER_E));
37543762
#ifndef WOLFSSL_RSA_DECRYPT_TO_0_LEN
3755-
ret = ctMaskSelInt(ctMaskNotEq(ret, 0), ret,
3756-
WC_NO_ERR_TRACE(RSA_BUFFER_E));
3763+
/* RFC 8017 Section 7.1.2: OAEP decryption may produce a valid
3764+
* zero-length message. Only reject ret==0 for non-OAEP types. */
3765+
{
3766+
int zeroOk = ctMaskEq(pad_type, WC_RSA_OAEP_PAD);
3767+
ret = ctMaskSelInt(ctMaskNotEq(ret, 0) | zeroOk, ret,
3768+
WC_NO_ERR_TRACE(RSA_BUFFER_E));
3769+
}
37573770
#endif
37583771
#else
37593772
if (outLen < (word32)ret)

0 commit comments

Comments
 (0)