diff options
Diffstat (limited to 'g10/pkglue.c')
-rw-r--r-- | g10/pkglue.c | 180 |
1 files changed, 98 insertions, 82 deletions
diff --git a/g10/pkglue.c b/g10/pkglue.c index eda13009b..cd6e90838 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -131,7 +131,6 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash, { gcry_sexp_t s_sig, s_hash, s_pkey; int rc; - unsigned int neededfixedlen = 0; /* Make a sexp from pkey. */ if (pkalgo == PUBKEY_ALGO_DSA) @@ -171,15 +170,16 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash, rc = gpg_error_from_syserror (); else { - rc = gcry_sexp_build (&s_pkey, NULL, - "(public-key(ecc(curve %s)" - "(flags eddsa)(q%m)))", - curve, pkey[1]); + const char *fmt; + + if (openpgp_oid_is_ed25519 (pkey[0])) + fmt = "(public-key(ecc(curve %s)(flags eddsa)(q%m)))"; + else + fmt = "(public-key(ecc(curve %s)(q%m)))"; + + rc = gcry_sexp_build (&s_pkey, NULL, fmt, curve, pkey[1]); xfree (curve); } - - if (openpgp_oid_is_ed25519 (pkey[0])) - neededfixedlen = 256 / 8; } else return GPG_ERR_PUBKEY_ALGO; @@ -190,9 +190,14 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash, /* Put hash into a S-Exp s_hash. */ if (pkalgo == PUBKEY_ALGO_EDDSA) { - if (gcry_sexp_build (&s_hash, NULL, - "(data(flags eddsa)(hash-algo sha512)(value %m))", - hash)) + const char *fmt; + + if (openpgp_oid_is_ed25519 (pkey[0])) + fmt = "(data(flags eddsa)(hash-algo sha512)(value %m))"; + else + fmt = "(data(value %m))"; + + if (gcry_sexp_build (&s_hash, NULL, fmt, hash)) BUG (); /* gcry_sexp_build should never fail. */ } else @@ -223,80 +228,87 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash, { gcry_mpi_t r = data[0]; gcry_mpi_t s = data[1]; - size_t rlen, slen, n; /* (bytes) */ - char buf[64]; - unsigned int nbits; - - 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); - else + if (openpgp_oid_is_ed25519 (pkey[0])) { - /* 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); - } - else if (rlen < neededfixedlen - && gcry_mpi_get_flag (r, GCRYMPI_FLAG_OPAQUE)) - { - const unsigned char *p; + size_t rlen, slen, n; /* (bytes) */ + char buf[64]; + unsigned int nbits; + unsigned int neededfixedlen = 256 / 8; - p = gcry_mpi_get_opaque (r, &nbits); - n = (nbits+7)/8; - memcpy (buf + (neededfixedlen - n), p, n); - memset (buf, 0, neededfixedlen - n); - gcry_mpi_set_opaque_copy (r, 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); - } - else if (slen < neededfixedlen - && gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE)) - { - const unsigned char *p; + log_assert (neededfixedlen <= sizeof buf); - p = gcry_mpi_get_opaque (s, &nbits); - n = (nbits+7)/8; - memcpy (buf + (neededfixedlen - n), p, n); - memset (buf, 0, neededfixedlen - n); - gcry_mpi_set_opaque_copy (s, buf, neededfixedlen * 8); + 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); + 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); + } + else if (rlen < neededfixedlen + && gcry_mpi_get_flag (r, GCRYMPI_FLAG_OPAQUE)) + { + const unsigned char *p; + + p = gcry_mpi_get_opaque (r, &nbits); + n = (nbits+7)/8; + memcpy (buf + (neededfixedlen - n), p, n); + memset (buf, 0, neededfixedlen - n); + gcry_mpi_set_opaque_copy (r, 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); + } + else if (slen < neededfixedlen + && gcry_mpi_get_flag (s, GCRYMPI_FLAG_OPAQUE)) + { + const unsigned char *p; + + p = gcry_mpi_get_opaque (s, &nbits); + n = (nbits+7)/8; + memcpy (buf + (neededfixedlen - n), p, n); + memset (buf, 0, neededfixedlen - n); + gcry_mpi_set_opaque_copy (s, buf, neededfixedlen * 8); + } } + } + else + rc = 0; - if (!rc) - rc = gcry_sexp_build (&s_sig, NULL, - "(sig-val(eddsa(r%M)(s%M)))", r, s); + if (!rc) + rc = gcry_sexp_build (&s_sig, NULL, + "(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); - } + 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) { @@ -506,10 +518,14 @@ pk_check_secret_key (pubkey_algo_t pkalgo, gcry_mpi_t *skey) rc = gpg_error_from_syserror (); else { - rc = gcry_sexp_build (&s_skey, NULL, - "(private-key(ecc(curve %s)" - "(flags eddsa)(q%m)(d%m)))", - curve, skey[1], skey[2]); + const char *fmt; + + if (openpgp_oid_is_ed25519 (skey[0])) + fmt = "(private-key(ecc(curve %s)(flags eddsa)(q%m)(d%m)))"; + else + fmt = "(private-key(ecc(curve %s)(q%m)(d%m)))"; + + rc = gcry_sexp_build (&s_skey, NULL, fmt, curve, skey[1], skey[2]); xfree (curve); } } |