RSA verification accepts signature representatives greater than the modulus
Closed, ResolvedPublic

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

Description

RSA verification accepts signature representatives greater than the modulus

The RSA verification path applies the public operation to the supplied signature MPI without first requiring the representative to be in the canonical interval 0 <= s < n. Modular exponentiation therefore treats s and s + k*n identically. A test confirmed that a valid signature and the non-canonical value s+n are both accepted through the public API.

Vulnerable code

In cipher/rsa.c, the RSA verification routine directly calls public:

/* Do RSA computation and compare.  */
result = mpi_new (0);
public (result, sig, &pk);
if (DBG_CIPHER)
  log_printmpi ("rsa_verify  cmp", result);
if (ctx.verify_cmp)
  rc = ctx.verify_cmp (&ctx, result);
else
  rc = mpi_cmp (result, data) ? GPG_ERR_BAD_SIGNATURE : 0;

Why it matters

RSA signature encodings require an integer representative smaller than the modulus. Accepting larger representatives creates signature malleability and can break systems that assume each accepted signature has a canonical integer form -- for example, caches, replay identifiers, or cross-implementation validation. This does not forge a signature for a new message: the attacker needs an already valid signature and constructs an equivalent representative. Serialization limits in some protocols may also prevent carrying s+n, so the severity is LOW.

Proposed fix

Before public, reject a negative sig and any sig for which mpi_cmp(sig, pk.n) >= 0, returning GPG_ERR_BAD_SIGNATURE consistently with other verification failures. Preserve existing encoding-specific checks. Add public-API regression vectors showing that the original signature succeeds while s+n, s+2n, exactly n, and negative representatives fail; cover each supported RSA padding/encoding path.

Event Timeline

werner triaged this task as Normal priority.Tue, Aug 4, 5:06 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 changed the task status from Open to Testing.Wed, Aug 12, 4:54 AM
gniibe mentioned this in Unknown Object (Maniphest Task).Mon, Aug 24, 8:26 AM
werner shifted this object from the Restricted Space space to the S1 Public space.