diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/export.c | 2 | ||||
-rw-r--r-- | g10/keygen.c | 16 | ||||
-rw-r--r-- | g10/pkglue.c | 180 | ||||
-rw-r--r-- | g10/sign.c | 23 |
4 files changed, 128 insertions, 93 deletions
diff --git a/g10/export.c b/g10/export.c index d06896026..909b98701 100644 --- a/g10/export.c +++ b/g10/export.c @@ -568,6 +568,8 @@ match_curve_skey_pk (gcry_sexp_t s_key, PKT_public_key *pk) log_error ("no curve name\n"); return gpg_error (GPG_ERR_UNKNOWN_CURVE); } + if (!strcmp (curve_str, "Ed448")) + is_eddsa = 1; oidstr = openpgp_curve_to_oid (curve_str, NULL, NULL); if (!oidstr) { diff --git a/g10/keygen.c b/g10/keygen.c index 590536726..d87b8480a 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1750,16 +1750,25 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root, curve = "Ed25519"; else if (!ascii_strcasecmp (curve, "cv448")) curve = "X448"; + else if (!ascii_strcasecmp (curve, "ed448")) + curve = "Ed448"; /* Note that we use the "comp" flag with EdDSA to request the use of a 0x40 compression prefix octet. */ - if (algo == PUBKEY_ALGO_EDDSA) + if (algo == PUBKEY_ALGO_EDDSA && !strcmp (curve, "Ed25519")) keyparms = xtryasprintf ("(genkey(ecc(curve %zu:%s)(flags eddsa comp%s)))", strlen (curve), curve, (((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY) && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))? " transient-key" : "")); + else if (algo == PUBKEY_ALGO_EDDSA && !strcmp (curve, "Ed448")) + keyparms = xtryasprintf + ("(genkey(ecc(curve %zu:%s)(flags comp%s)))", + strlen (curve), curve, + (((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY) + && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))? + " transient-key" : "")); else if (algo == PUBKEY_ALGO_ECDH && !strcmp (curve, "Curve25519")) keyparms = xtryasprintf ("(genkey(ecc(curve %zu:%s)(flags djb-tweak comp%s)))", @@ -2326,6 +2335,8 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage, { if (!strcmp (algostr, "ed25519")) kpi->algo = PUBKEY_ALGO_EDDSA; + else if (!strcmp (algostr, "ed448")) + kpi->algo = PUBKEY_ALGO_EDDSA; else if (!strcmp (algostr, "cv25519")) kpi->algo = PUBKEY_ALGO_ECDH; else if (!strcmp (algostr, "cv448")) @@ -3481,6 +3492,8 @@ parse_key_parameter_part (ctrl_t ctrl, { if (!strcmp (algostr, "ed25519")) algo = PUBKEY_ALGO_EDDSA; + else if (!strcmp (algostr, "ed448")) + kpi->algo = PUBKEY_ALGO_EDDSA; else if (!strcmp (algostr, "cv25519")) algo = PUBKEY_ALGO_ECDH; else if (!strcmp (algostr, "cv448")) @@ -3611,6 +3624,7 @@ parse_key_parameter_part (ctrl_t ctrl, * dsa2048 := DSA with 2048 bit. * elg2048 := Elgamal with 2048 bit. * ed25519 := EDDSA using curve Ed25519. + * ed448 := EDDSA using curve Ed448. * cv25519 := ECDH using curve Curve25519. * cv448 := ECDH using curve X448. * nistp256:= ECDSA or ECDH using curve NIST P-256 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); } } diff --git a/g10/sign.c b/g10/sign.c index 8f72d8102..d6c938acc 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -630,7 +630,7 @@ match_dsa_hash (unsigned int qbytes) usable for the pubkey algorithm. If --personal-digest-prefs isn't set, then take the OpenPGP default (i.e. SHA-1). - Note that Ed25519+EdDSA takes an input of arbitrary length and thus + Note that EdDSA takes an input of arbitrary length and thus we don't enforce any particular algorithm like we do for standard ECDSA. However, we use SHA256 as the default algorithm. @@ -649,13 +649,15 @@ hash_for (PKT_public_key *pk) { return recipient_digest_algo; } - else if (pk->pubkey_algo == PUBKEY_ALGO_EDDSA - && openpgp_oid_is_ed25519 (pk->pkey[0])) + else if (pk->pubkey_algo == PUBKEY_ALGO_EDDSA) { if (opt.personal_digest_prefs) return opt.personal_digest_prefs[0].value; else - return DIGEST_ALGO_SHA256; + if (gcry_mpi_get_nbits (pk->pkey[1]) > 256) + return DIGEST_ALGO_SHA512; + else + return DIGEST_ALGO_SHA256; } else if (pk->pubkey_algo == PUBKEY_ALGO_DSA || pk->pubkey_algo == PUBKEY_ALGO_ECDSA) @@ -1742,14 +1744,15 @@ make_keysig_packet (ctrl_t ctrl, digest_algo = opt.cert_digest_algo; else if (pksk->pubkey_algo == PUBKEY_ALGO_DSA) /* Meet DSA requirements. */ digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8); - else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA /* Meet ECDSA requirements. */ - || pksk->pubkey_algo == PUBKEY_ALGO_EDDSA) + else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA) /* Meet ECDSA requirements. */ + digest_algo = match_dsa_hash + (ecdsa_qbits_from_Q (gcry_mpi_get_nbits (pksk->pkey[1]))/8); + else if (pksk->pubkey_algo == PUBKEY_ALGO_EDDSA) { - if (openpgp_oid_is_ed25519 (pksk->pkey[0])) - digest_algo = DIGEST_ALGO_SHA256; + if (gcry_mpi_get_nbits (pksk->pkey[1]) > 256) + digest_algo = DIGEST_ALGO_SHA512; else - digest_algo = match_dsa_hash - (ecdsa_qbits_from_Q (gcry_mpi_get_nbits (pksk->pkey[1]))/8); + digest_algo = DIGEST_ALGO_SHA256; } else /* Use the default. */ digest_algo = DEFAULT_DIGEST_ALGO; |