RSAES-PKCS1-v1_5 encoder emits padding strings as short as four bytes
Closed, ResolvedPublic

Assigned To
Authored By
werner
Tue, Aug 4, 5:08 PM

Description

RSAES-PKCS1-v1_5 encoder emits padding strings as short as four bytes

The RSAES-PKCS1-v1_5 encoder accepts a message whenever valuelen + 7 fits the modulus frame. Because the encoding also consumes three fixed bytes, this permits a padding string of only four bytes. PKCS #1 requires at least eight, so near-limit plaintexts produce nonconforming and materially weaker encodings.

Vulnerable code

In cipher/rsa-common.c, function _gcry_rsa_pkcs1_encode_for_enc:

if (valuelen + 7 > nframe || !nframe)
  {
    /* Can't encode a VALUELEN value in a NFRAME bytes frame.  */
    return GPG_ERR_TOO_SHORT; /* The key is too short.  */
  }

if ( !(frame = xtrymalloc_secure (nframe)))
  return gpg_err_code_from_syserror ();

n = 0;
frame[n++] = 0;
frame[n++] = 2; /* block type */
i = nframe - 3 - valuelen;
gcry_assert (i > 0);

Why it matters

The weakness is reachable only for messages close to the RSA modulus capacity; typical callers use smaller, structured plaintexts or hybrid encryption. Nevertheless, emitted ciphertext can have substantially less random padding than the format promises, reducing the search space when plaintext structure is predictable. This is an encoding-policy failure, not evidence that arbitrary RSA ciphertext can immediately be decrypted.

Proposed fix

Require nframe - valuelen to be at least 11 bytes, expressed with subtraction after checking valuelen <= nframe to avoid arithmetic overflow. Keep random_override_len tied to the resulting padding length. Add boundary tests for message sizes yielding padding lengths seven, eight, and nine, and assert that only standards-compliant frames are produced and round-trip through the decoder.

Event Timeline

werner triaged this task as Normal priority.Tue, Aug 4, 5:08 PM
werner created this task.
werner created this object with visibility "Public (No Login Required)".
werner created this object with edit policy "Contributor (Project)".
gniibe added a subscriber: gniibe.

Since PKCS#1 handling added by rCb72cee46eea1: * basic.c (verify_one_signature,check_pubkey_sign) (check_pubkey): New. (main)…, the check was valuelen + 7 > nframe (wrongly).

In PKCS#1 v1.5 (1993) https://web.archive.org/web/19970106151628/http://www.rsa.com/rsalabs/pubs/PKCS/ascii/pkcs-1.asc says:

The length of the data D shall not be more than k-11 octets,
which is positive since the length k of the modulus is at
least 12 octets. This limitation guarantees that the length
of the padding string PS is at least eight octets, which is
a security condition.

werner shifted this object from the Restricted Space space to the S1 Public space.Tue, Aug 25, 9:35 AM
gniibe changed the task status from Open to Testing.Wed, Aug 26, 4:40 AM
gniibe mentioned this in Unknown Object (Maniphest Task).Mon, Aug 31, 2:58 AM