Small-order Ed25519 public keys reach a fatal internal arithmetic assertion
Ed25519 verification checks that the supplied public point is on the curve but does not reject identity or other small-order points before scalar multiplication. A public gcry_pk_verify call with a degenerate attacker-supplied key can consequently reach log_bug in the field arithmetic and abort the entire process before signature validity is decided.
Vulnerable code
cipher/ecc-eddsa.c, _gcry_ecc_eddsa_verify:
c
if (!_gcry_mpi_ec_curve_point (ec->Q, ec))
{
rc = GPG_ERR_BROKEN_PUBKEY;
goto leave;
}The unchecked point is later consumed here:
c _gcry_mpi_ec_mul_point (&Ia, s, ec->G, ec); _gcry_mpi_ec_mul_point (&Ib, h, ec->Q, ec); _gcry_mpi_sub (Ib.x, ec->p, Ib.x);
mpi/ec.c, ec_mulm_25519, makes the failure fatal:
c
if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
log_bug ("mulm_25519: different sizes\n");Why it matters
Signature-verifying services often accept both the signature and public key from an untrusted peer, certificate, or stored object. The audit's public-API harness first verified a normal Ed25519 vector, then supplied a small-order public key and reproducibly terminated with mulm_25519: different sizes and exit status 134. The crash is raised by libgcrypt itself, not by a sanitizer. This establishes reliable denial of service; it does not require a valid attacker signature.
Proposed fix
Apply the Ed25519 verification rule to public keys before hashing or multiplication: reject the identity and low-order/torsion points, and enforce the intended subgroup policy. Invalid keys must return GPG_ERR_BAD_PUBKEY or GPG_ERR_BROKEN_PUBKEY, never reach log_bug. Add public-API tests for the identity, all standard low-order encodings, non-canonical point encodings, and a known-valid key/signature pair.