mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
gpg,agent: Support Ed448 signing.
* agent/pksign.c (do_encode_eddsa): First argument is NBITs, so that it can support Ed448, as well as Ed25519. (agent_pksign_do): Follow the change. * agent/sexp-secret.c (fixup_when_ecc_private_key): No fix-up needed for Ed448, it's only for classic curves. * common/openpgp-oid.c (oidtable): Add Ed448. * common/sexputil.c (get_pk_algo_from_key): Ed448 is only for EdDSA. * g10/export.c (match_curve_skey_pk): Ed448 is for EdDSA. * g10/keygen.c (gen_ecc): Support Ed448 with the name of "ed448". (ask_algo, parse_key_parameter_part): Handle "ed448". * g10/pkglue.c (pk_verify): Support Ed448. (pk_check_secret_key): Support Ed448. * g10/sign.c (hash_for): Defaults to SHA512 for Ed448. (make_keysig_packet): Likewise. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
c94eea15d6
commit
a763bb2580
8 changed files with 147 additions and 98 deletions
178
g10/pkglue.c
178
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;
|
||||
size_t rlen, slen, n; /* (bytes) */
|
||||
char buf[64];
|
||||
unsigned int nbits;
|
||||
unsigned int neededfixedlen = 256 / 8;
|
||||
|
||||
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 (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
|
||||
{
|
||||
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;
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
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 (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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue