mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
gpg: Fix false negatives in Ed25519 signature verification.
* g10/pkglue.c (pk_verify): Fix Ed25519 signatrue values. * tests/openpgp/verify.scm (msg_ed25519_rshort): New (msg_ed25519_sshort): New. ("Checking that a valid Ed25519 signature is verified as such"): New. -- About one out of 256 signature won't verify due to stripped zero bytes. See the source comment for details. Reported-by: Andre Heinecke Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
74a082bc10
commit
0a5a854510
56
g10/pkglue.c
56
g10/pkglue.c
@ -58,6 +58,7 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
|
|||||||
{
|
{
|
||||||
gcry_sexp_t s_sig, s_hash, s_pkey;
|
gcry_sexp_t s_sig, s_hash, s_pkey;
|
||||||
int rc;
|
int rc;
|
||||||
|
unsigned int neededfixedlen = 0;
|
||||||
|
|
||||||
/* Make a sexp from pkey. */
|
/* Make a sexp from pkey. */
|
||||||
if (pkalgo == PUBKEY_ALGO_DSA)
|
if (pkalgo == PUBKEY_ALGO_DSA)
|
||||||
@ -103,6 +104,9 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
|
|||||||
curve, pkey[1]);
|
curve, pkey[1]);
|
||||||
xfree (curve);
|
xfree (curve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (openpgp_oid_is_ed25519 (pkey[0]))
|
||||||
|
neededfixedlen = 256 / 8;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return GPG_ERR_PUBKEY_ALGO;
|
return GPG_ERR_PUBKEY_ALGO;
|
||||||
@ -144,11 +148,59 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
|
|||||||
}
|
}
|
||||||
else if (pkalgo == PUBKEY_ALGO_EDDSA)
|
else if (pkalgo == PUBKEY_ALGO_EDDSA)
|
||||||
{
|
{
|
||||||
if (!data[0] || !data[1])
|
gcry_mpi_t r = data[0];
|
||||||
|
gcry_mpi_t s = data[1];
|
||||||
|
size_t rlen, slen, n; /* (bytes) */
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
log_assert (neededfixedlen <= sizeof buf);
|
||||||
|
|
||||||
|
if (!r || !s)
|
||||||
|
rc = gpg_error (GPG_ERR_BAD_MPI);
|
||||||
|
else if ((rlen = (gcry_mpi_get_nbits (r)+7)/8) > neededfixedlen || !rlen)
|
||||||
|
rc = gpg_error (GPG_ERR_BAD_MPI);
|
||||||
|
else if ((slen = (gcry_mpi_get_nbits (s)+7)/8) > neededfixedlen || !slen)
|
||||||
rc = gpg_error (GPG_ERR_BAD_MPI);
|
rc = gpg_error (GPG_ERR_BAD_MPI);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/* We need to fixup the length in case of leading zeroes.
|
||||||
|
* OpenPGP does not allow leading zeroes and the parser for
|
||||||
|
* the signature packet has no information on the use curve,
|
||||||
|
* thus we need to do it here. We won't do it for opaque
|
||||||
|
* MPIs under the assumption that they are known to be fine;
|
||||||
|
* we won't see them here anyway but the check is anyway
|
||||||
|
* required. Fixme: A nifty feature for gcry_sexp_build
|
||||||
|
* would be a format to left pad the value (e.g. "%*M"). */
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
if (rlen < neededfixedlen
|
||||||
|
&& !gcry_mpi_get_flag (r, GCRYMPI_FLAG_OPAQUE)
|
||||||
|
&& !(rc=gcry_mpi_print (GCRYMPI_FMT_USG, buf, sizeof buf, &n, r)))
|
||||||
|
{
|
||||||
|
log_assert (n < neededfixedlen);
|
||||||
|
memmove (buf + (neededfixedlen - n), buf, n);
|
||||||
|
memset (buf, 0, neededfixedlen - n);
|
||||||
|
r = gcry_mpi_set_opaque_copy (NULL, buf, neededfixedlen * 8);
|
||||||
|
}
|
||||||
|
if (slen < neededfixedlen
|
||||||
|
&& !gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE)
|
||||||
|
&& !(rc=gcry_mpi_print (GCRYMPI_FMT_USG, buf, sizeof buf, &n, s)))
|
||||||
|
{
|
||||||
|
log_assert (n < neededfixedlen);
|
||||||
|
memmove (buf + (neededfixedlen - n), buf, n);
|
||||||
|
memset (buf, 0, neededfixedlen - n);
|
||||||
|
s = gcry_mpi_set_opaque_copy (NULL, buf, neededfixedlen * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rc)
|
||||||
rc = gcry_sexp_build (&s_sig, NULL,
|
rc = gcry_sexp_build (&s_sig, NULL,
|
||||||
"(sig-val(eddsa(r%M)(s%M)))", data[0], data[1]);
|
"(sig-val(eddsa(r%M)(s%M)))", r, s);
|
||||||
|
|
||||||
|
if (r != data[0])
|
||||||
|
gcry_mpi_release (r);
|
||||||
|
if (s != data[1])
|
||||||
|
gcry_mpi_release (s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (pkalgo == PUBKEY_ALGO_ELGAMAL || pkalgo == PUBKEY_ALGO_ELGAMAL_E)
|
else if (pkalgo == PUBKEY_ALGO_ELGAMAL || pkalgo == PUBKEY_ALGO_ELGAMAL_E)
|
||||||
{
|
{
|
||||||
|
@ -236,6 +236,67 @@ FWIAQUplk7JWbyRKAJ92ZJyJpWfzb0yc1s7MY65r2qEHrg==
|
|||||||
;; Two clear text signatures in a row
|
;; Two clear text signatures in a row
|
||||||
(define msg_clsclss_asc_multiple (string-append msg_cls_asc msg_clss_asc))
|
(define msg_clsclss_asc_multiple (string-append msg_cls_asc msg_clss_asc))
|
||||||
|
|
||||||
|
|
||||||
|
;; An Ed25519 cleartext message with an R parameter of only 247 bits
|
||||||
|
;; so that the code to re-insert the stripped zero byte kicks in. The
|
||||||
|
;; S parameter has 253 bits but that does not strip a full byte.
|
||||||
|
(define msg_ed25519_rshort "
|
||||||
|
-----BEGIN PGP SIGNED MESSAGE-----
|
||||||
|
Hash: SHA256
|
||||||
|
|
||||||
|
Dear Emily:
|
||||||
|
I'm still confused as to what groups articles should be posted
|
||||||
|
to. How about an example?
|
||||||
|
-- Still Confused
|
||||||
|
|
||||||
|
Dear Still:
|
||||||
|
Ok. Let's say you want to report that Gretzky has been traded from
|
||||||
|
the Oilers to the Kings. Now right away you might think rec.sport.hockey
|
||||||
|
would be enough. WRONG. Many more people might be interested. This is a
|
||||||
|
big trade! Since it's a NEWS article, it belongs in the news.* hierarchy
|
||||||
|
as well. If you are a news admin, or there is one on your machine, try
|
||||||
|
news.admin. If not, use news.misc.
|
||||||
|
The Oilers are probably interested in geology, so try sci.physics.
|
||||||
|
He is a big star, so post to sci.astro, and sci.space because they are also
|
||||||
|
interested in stars. Next, his name is Polish sounding. So post to
|
||||||
|
soc.culture.polish. But that group doesn't exist, so cross-post to
|
||||||
|
news.groups suggesting it should be created. With this many groups of
|
||||||
|
interest, your article will be quite bizarre, so post to talk.bizarre as
|
||||||
|
well. (And post to comp.std.mumps, since they hardly get any articles
|
||||||
|
there, and a \"comp\" group will propagate your article further.)
|
||||||
|
You may also find it is more fun to post the article once in each
|
||||||
|
group. If you list all the newsgroups in the same article, some newsreaders
|
||||||
|
will only show the the article to the reader once! Don't tolerate this.
|
||||||
|
-- Emily Postnews Answers Your Questions on Netiquette
|
||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iJEEARYIADoWIQSyHeq0+HX7PaQvHR0TlWNoKgINCgUCV772DhwccGF0cmljZS5s
|
||||||
|
dW11bWJhQGV4YW1wbGUubmV0AAoJEBOVY2gqAg0KMAIA90EtUwAja0iJGpO91wyz
|
||||||
|
GLh9pS5v495V0r94yU6uUyUA/RT/StyPWe1wbnEZuacZnLbUV6Yy/aTXCVAlxf0r
|
||||||
|
TusO
|
||||||
|
=vQ3f
|
||||||
|
-----END PGP SIGNATURE-----
|
||||||
|
")
|
||||||
|
|
||||||
|
;; An Ed25519 cleartext message with an S parameter of only 248 bits
|
||||||
|
;; so that the code to re-insert the stripped zero byte kicks in.
|
||||||
|
(define msg_ed25519_sshort "
|
||||||
|
-----BEGIN PGP SIGNED MESSAGE-----
|
||||||
|
Hash: SHA256
|
||||||
|
|
||||||
|
All articles that coruscate with resplendence are not truly auriferous.
|
||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iJEEARYIADoWIQSyHeq0+HX7PaQvHR0TlWNoKgINCgUCV771QhwccGF0cmljZS5s
|
||||||
|
dW11bWJhQGV4YW1wbGUubmV0AAoJEBOVY2gqAg0KHVEBAI66OPDYXKWO3r6SaFT+
|
||||||
|
uxmh8x4ZerW41vMA9gkJ4AEKAPjoe/Z7fDqo1lCptIFutFAGbfNxcm/53prfx2fT
|
||||||
|
GisM
|
||||||
|
=L7sk
|
||||||
|
-----END PGP SIGNATURE-----
|
||||||
|
")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; Fixme: We need more tests with manipulated cleartext signatures.
|
;; Fixme: We need more tests with manipulated cleartext signatures.
|
||||||
|
|
||||||
;;
|
;;
|
||||||
@ -272,3 +333,15 @@ FWIAQUplk7JWbyRKAJ92ZJyJpWfzb0yc1s7MY65r2qEHrg==
|
|||||||
(pipe:spawn `(,@GPG --verify)))
|
(pipe:spawn `(,@GPG --verify)))
|
||||||
(error "verification succeded but should not")))
|
(error "verification succeded but should not")))
|
||||||
'(bad_ls_asc bad_fols_asc bad_olsf_asc bad_ools_asc))
|
'(bad_ls_asc bad_fols_asc bad_olsf_asc bad_ools_asc))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Need to import the ed25519 sample key used for
|
||||||
|
;;; the next two tests.
|
||||||
|
(call-check `(,@GPG --quiet --yes --import ,(in-srcdir key-file2)))
|
||||||
|
(for-each-p
|
||||||
|
"Checking that a valid Ed25519 signature is verified as such"
|
||||||
|
(lambda (armored-file)
|
||||||
|
(pipe:do
|
||||||
|
(pipe:echo (eval armored-file (current-environment)))
|
||||||
|
(pipe:spawn `(,@GPG --verify))))
|
||||||
|
'(msg_ed25519_rshort msg_ed25519_sshort))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user