Skip to content

Commit eefa39a

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>
1 parent 922d04b commit eefa39a

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
@@ -3318,7 +3318,15 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
33183318
RsaPadding padding;
33193319
#endif
33203320

3321-
if (in == NULL || inLen == 0 || out == NULL || key == NULL) {
3321+
if (out == NULL || key == NULL) {
3322+
return BAD_FUNC_ARG;
3323+
}
3324+
3325+
/* For OAEP padding (RFC 8017, Section 7.1.1), zero-length messages are
3326+
* permitted: the spec requires mLen <= k - 2*hLen - 2, and mLen = 0
3327+
* satisfies this for all supported key sizes. For other padding types,
3328+
* a zero-length input is invalid. */
3329+
if (in == NULL || (inLen == 0 && pad_type != WC_RSA_OAEP_PAD)) {
33223330
return BAD_FUNC_ARG;
33233331
}
33243332

@@ -3706,8 +3714,13 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out,
37063714
ret = ctMaskSelInt(ctMaskLTE(ret, (int)outLen), ret,
37073715
WC_NO_ERR_TRACE(RSA_BUFFER_E));
37083716
#ifndef WOLFSSL_RSA_DECRYPT_TO_0_LEN
3709-
ret = ctMaskSelInt(ctMaskNotEq(ret, 0), ret,
3710-
WC_NO_ERR_TRACE(RSA_BUFFER_E));
3717+
/* RFC 8017 Section 7.1.2: OAEP decryption may produce a valid
3718+
* zero-length message. Only reject ret==0 for non-OAEP types. */
3719+
{
3720+
int zeroOk = ctMaskEq(pad_type, WC_RSA_OAEP_PAD);
3721+
ret = ctMaskSelInt(ctMaskNotEq(ret, 0) | zeroOk, ret,
3722+
WC_NO_ERR_TRACE(RSA_BUFFER_E));
3723+
}
37113724
#endif
37123725
#else
37133726
if (outLen < (word32)ret)

0 commit comments

Comments
 (0)