aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2021-10-08 03:00:56 +0000
committerNIIBE Yutaka <[email protected]>2021-10-08 08:22:15 +0000
commitc450eb1ccbc8530ba7854911783ea958ed10f747 (patch)
treeb55b7e5d7835e230d491480a81917144d56c6616
parentcommon: Respect gpgconf.ctl when looking up translations (diff)
downloadgnupg-c450eb1ccbc8530ba7854911783ea958ed10f747.tar.gz
gnupg-c450eb1ccbc8530ba7854911783ea958ed10f747.zip
experiment: Try to support new 448 key and signature.
-- Keygrip computation is still wrong, need to fix soon. Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r--agent/cvt-openpgp.c24
-rw-r--r--common/Makefile.am2
-rw-r--r--common/openpgpdefs.h5
-rw-r--r--g10/keyid.c6
-rw-r--r--g10/misc.c3
-rw-r--r--g10/pkglue.c54
6 files changed, 83 insertions, 11 deletions
diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c
index 76932a7a8..7defc200a 100644
--- a/agent/cvt-openpgp.c
+++ b/agent/cvt-openpgp.c
@@ -27,7 +27,7 @@
#include "../common/i18n.h"
#include "cvt-openpgp.h"
#include "../common/host2net.h"
-
+#include "../common/openpgpdefs.h"
/* Helper to pass data via the callback to do_unprotect. */
struct try_do_unprotect_arg_s
@@ -153,6 +153,9 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
else
{
const char *format;
+ gcry_mpi_t pubkey = NULL;
+ gcry_mpi_t seckey = NULL;
+ pubkey_algo_t pkalgo = 0; /* Specify NONE */
if (!strcmp (curve, "Ed25519"))
/* Do not store the OID as name but the real name and the
@@ -161,9 +164,24 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
else if (!strcmp (curve, "Curve25519"))
format = "(private-key(ecc(curve %s)(flags djb-tweak)(q%m)(d%m)))";
else
- format = "(private-key(ecc(curve %s)(q%m)(d%m)))";
+ {
+ if (!strcmp (curve, "Ed448"))
+ pkalgo = PUBKEY_ALGO_EDDSA;
+ else if (!strcmp (curve, "X448"))
+ pkalgo = PUBKEY_ALGO_ECDH;
+ format = "(private-key(ecc(curve %s)(q%m)(d%m)))";
+ }
- err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], skey[1]);
+ if (pkalgo)
+ {
+ pubkey = openpgp_ecc_parse_pubkey (pkalgo, curve, skey[0]);
+ seckey = openpgp_ecc_parse_seckey (pkalgo, curve, skey[1]);
+ err = gcry_sexp_build (&s_skey, NULL, format, curve, pubkey, seckey);
+ gcry_mpi_release (pubkey);
+ gcry_mpi_release (seckey);
+ }
+ else
+ err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], skey[1]);
}
break;
diff --git a/common/Makefile.am b/common/Makefile.am
index d8368fc22..8dbf05af7 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -85,7 +85,7 @@ common_sources = \
localename.c \
session-env.c session-env.h \
userids.c userids.h \
- openpgp-oid.c openpgp-s2k.c \
+ openpgp-oid.c openpgp-s2k.c openpgp-misc.c \
ssh-utils.c ssh-utils.h \
agent-opt.c \
helpfile.c \
diff --git a/common/openpgpdefs.h b/common/openpgpdefs.h
index 625747983..4e5500d0b 100644
--- a/common/openpgpdefs.h
+++ b/common/openpgpdefs.h
@@ -239,5 +239,10 @@ pubkey_algo_t map_gcry_pk_to_openpgp (enum gcry_pk_algos algo);
enum gcry_pk_algos map_openpgp_pk_to_gcry (pubkey_algo_t algo);
+/*-- openpgp-misc.c --*/
+gcry_mpi_t openpgp_ecc_parse_pubkey (pubkey_algo_t pkalgo, const char *curve,
+ gcry_mpi_t pubkey);
+gcry_mpi_t openpgp_ecc_parse_seckey (pubkey_algo_t pkalgo, const char *curve_oid,
+ gcry_mpi_t seckey);
#endif /*GNUPG_COMMON_OPENPGPDEFS_H*/
diff --git a/g10/keyid.c b/g10/keyid.c
index 522cc9cda..d0a3e4057 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -1068,6 +1068,9 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
err = gpg_error_from_syserror ();
else
{
+ gcry_mpi_t pubkey = openpgp_ecc_parse_pubkey (pk->pubkey_algo,
+ curve, pk->pkey[1]);
+
err = gcry_sexp_build (&s_pkey, NULL,
pk->pubkey_algo == PUBKEY_ALGO_EDDSA?
"(public-key(ecc(curve%s)(flags eddsa)(q%m)))":
@@ -1075,8 +1078,9 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
&& openpgp_oid_is_cv25519 (pk->pkey[0]))?
"(public-key(ecc(curve%s)(flags djb-tweak)(q%m)))":
"(public-key(ecc(curve%s)(q%m)))",
- curve, pk->pkey[1]);
+ curve, pubkey);
xfree (curve);
+ gcry_mpi_release (pubkey);
}
}
break;
diff --git a/g10/misc.c b/g10/misc.c
index 2a431b137..c329bef55 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1805,10 +1805,13 @@ pubkey_nbits( int algo, gcry_mpi_t *key )
rc = gpg_error_from_syserror ();
else
{
+ gcry_mpi_t pubkey = openpgp_ecc_parse_pubkey (algo, curve, key[1]);
+
rc = gcry_sexp_build (&sexp, NULL,
"(public-key(ecc(curve%s)(q%m)))",
curve, key[1]);
xfree (curve);
+ gcry_mpi_release (pubkey);
}
}
else
diff --git a/g10/pkglue.c b/g10/pkglue.c
index 1e0191e12..137e520e4 100644
--- a/g10/pkglue.c
+++ b/g10/pkglue.c
@@ -121,6 +121,26 @@ get_data_from_sexp (gcry_sexp_t sexp, const char *item, size_t *r_size)
}
+static void
+openpgp_ecc_parse_signature (pubkey_algo_t pkalgo, gcry_mpi_t sig_data,
+ gcry_mpi_t *r, gcry_mpi_t *s)
+{
+ unsigned int nbits = 0;
+ unsigned char *buf;
+
+ if (pkalgo != PUBKEY_ALGO_EDDSA)
+ return;
+
+ buf = gcry_mpi_get_opaque (sig_data, &nbits);
+ if ((nbits+7)/8 != (8 /*prefix*/ + 448 + 8 /*r*/ + 448 + 8 /*s*/)/8)
+ return;
+
+ /* Ed448 signature with the prefix. */
+ *r = gcry_mpi_set_opaque_copy (NULL, buf+1, 8 + 448);
+ *s = gcry_mpi_set_opaque_copy (NULL, buf+1+57, 8 + 448);
+}
+
+
/****************
* Emulate our old PK interface here - sometime in the future we might
* change the internal design to directly fit to libgcrypt.
@@ -171,14 +191,17 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
else
{
const char *fmt;
+ gcry_mpi_t pubkey;
+ pubkey = openpgp_ecc_parse_pubkey (pkalgo, curve, pkey[1]);
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]);
+ rc = gcry_sexp_build (&s_pkey, NULL, fmt, curve, pubkey);
xfree (curve);
+ gcry_mpi_release (pubkey);
}
}
else
@@ -298,6 +321,9 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
}
}
}
+ else if (!gcry_mpi_cmp_ui (s, 0))
+ /* When data[1] == MPI(0), parse the signature into R and S parts. */
+ openpgp_ecc_parse_signature (pkalgo, r, &r, &s);
else
rc = 0;
@@ -388,14 +414,17 @@ pk_encrypt (pubkey_algo_t algo, gcry_mpi_t *resarr, gcry_mpi_t data,
else
{
int with_djb_tweak_flag = openpgp_oid_is_cv25519 (pkey[0]);
+ gcry_mpi_t pubkey;
+ pubkey = openpgp_ecc_parse_pubkey (algo, curve, pkey[1]);
/* Now use the ephemeral secret to compute the shared point. */
rc = gcry_sexp_build (&s_pkey, NULL,
with_djb_tweak_flag ?
- "(public-key(ecdh(curve%s)(flags djb-tweak)(q%m)))"
- : "(public-key(ecdh(curve%s)(q%m)))",
- curve, pkey[1]);
+ "(public-key(ecc(curve%s)(flags djb-tweak)(q%m)))"
+ : "(public-key(ecc(curve%s)(q%m)))",
+ curve, pubkey);
xfree (curve);
+ gcry_mpi_release (pubkey);
/* Put K into a simplified S-expression. */
if (!rc)
rc = gcry_sexp_build (&s_data, NULL, "%m", k);
@@ -508,10 +537,17 @@ pk_check_secret_key (pubkey_algo_t pkalgo, gcry_mpi_t *skey)
rc = gpg_error_from_syserror ();
else
{
+ gcry_mpi_t pubkey;
+ gcry_mpi_t seckey;
+
+ pubkey = openpgp_ecc_parse_pubkey (pkalgo, curve, skey[1]);
+ seckey = openpgp_ecc_parse_seckey (pkalgo, curve, skey[2]);
rc = gcry_sexp_build (&s_skey, NULL,
"(private-key(ecc(curve%s)(q%m)(d%m)))",
- curve, skey[1], skey[2]);
+ curve, pubkey, seckey);
xfree (curve);
+ gcry_mpi_release (pubkey);
+ gcry_mpi_release (seckey);
}
}
else if (pkalgo == PUBKEY_ALGO_EDDSA)
@@ -522,14 +558,20 @@ pk_check_secret_key (pubkey_algo_t pkalgo, gcry_mpi_t *skey)
else
{
const char *fmt;
+ gcry_mpi_t pubkey;
+ gcry_mpi_t seckey;
+ pubkey = openpgp_ecc_parse_pubkey (pkalgo, curve, skey[1]);
+ seckey = openpgp_ecc_parse_seckey (pkalgo, curve, skey[2]);
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]);
+ rc = gcry_sexp_build (&s_skey, NULL, fmt, curve, pubkey, seckey);
xfree (curve);
+ gcry_mpi_release (pubkey);
+ gcry_mpi_release (seckey);
}
}
else