1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-21 10:09:57 +01:00

experiment: Handle S=0 in EdDSA by SOS("0").

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2021-12-22 20:11:42 +09:00
parent aa4b138f4d
commit d080720939
2 changed files with 33 additions and 15 deletions

View File

@ -188,6 +188,22 @@ mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure)
} }
/* Return an object for SOS which represents MPI(0). */
static gcry_mpi_t
sos_zero (void)
{
/*
* We don't do gcry_mpi_set_opaque (NULL, NULL, 0), becase it may
* cause undefined behavior. We use a kind of cork stopper to avoid
* undefined behavior.
*/
byte *buf = gcry_xcalloc (1, 1);
gcry_mpi_t a = gcry_mpi_set_opaque (NULL, buf, 1);
gcry_mpi_set_flag (a, GCRYMPI_FLAG_USER2);
return a;
}
/* Read an external representation of an SOS and return the opaque MPI /* Read an external representation of an SOS and return the opaque MPI
with GCRYMPI_FLAG_USER2. The external format is a 16-bit unsigned with GCRYMPI_FLAG_USER2. The external format is a 16-bit unsigned
value stored in network byte order giving information for the value stored in network byte order giving information for the
@ -222,7 +238,12 @@ sos_read (iobuf_t inp, unsigned int *ret_nread, int secure)
goto leave; goto leave;
++nread; ++nread;
nbits |= c; nbits |= c;
if (nbits > MAX_EXTERN_MPI_BITS) if (nbits == 0)
{
*ret_nread = nread;
return sos_zero ();
}
else if (nbits > MAX_EXTERN_MPI_BITS)
{ {
log_error ("mpi too large (%u bits)\n", nbits); log_error ("mpi too large (%u bits)\n", nbits);
goto leave; goto leave;
@ -231,8 +252,6 @@ sos_read (iobuf_t inp, unsigned int *ret_nread, int secure)
nbytes = (nbits + 7) / 8; nbytes = (nbits + 7) / 8;
if (nbytes) if (nbytes)
buf = secure ? gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes); buf = secure ? gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes);
else
buf = NULL;
p = buf; p = buf;
for (i = 0; i < nbytes; i++) for (i = 0; i < nbytes; i++)
{ {
@ -2378,9 +2397,12 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
} }
if (!sig->data[i]) if (!sig->data[i])
rc = GPG_ERR_INV_PACKET; rc = GPG_ERR_INV_PACKET;
if (!pktlen && sig->pubkey_algo == PUBKEY_ALGO_EDDSA) if (i == 0 && !pktlen && sig->pubkey_algo == PUBKEY_ALGO_EDDSA)
/* Allow the R part only. */ {
break; /* Accept the case: R part only, missing S. */
sig->data[1] = sos_zero ();
break;
}
} }
} }

View File

@ -319,15 +319,11 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
} }
} }
} }
/* else if (gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE)
* When data[1] is NULL or [0], parse the signature into R and S && ((p = gcry_mpi_get_opaque (s, &nbits)) == NULL
* parts. || nbits == 0
*/ || ((nbits+7)/8 == 1 && p[0] == 0)))
else if (!s /* When data[1] is MPI(0), parse the signature into R and S parts. */
|| (gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE)
&& ((p = gcry_mpi_get_opaque (s, &nbits)) == NULL
|| nbits == 0
|| ((nbits+7)/8 == 1 && p[0] == 0))))
openpgp_ecc_parse_signature (pkalgo, r, &r, &s); openpgp_ecc_parse_signature (pkalgo, r, &r, &s);
else else
rc = 0; rc = 0;