1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

gpg: Rework ECC support and add experimental support for Ed25519.

* agent/findkey.c (key_parms_from_sexp): Add algo name "ecc".
(agent_is_dsa_key): Ditto.
(agent_is_eddsa_key): New.  Not finished, though.
* agent/pksign.c (do_encode_eddsa): New.
(agent_pksign_do): Use gcry_log_debug functions.
* agent/protect.c (agent_protect): Parse a flags parameter.
* g10/keygen.c (gpg_curve_to_oid): Move to ...
* common/openpgp-oid.c (openpgp_curve_to_oid): here and rename.
(oid_ed25519): New.
(openpgp_oid_is_ed25519): New.
(openpgp_oid_to_curve): New.
* common/t-openpgp-oid.c (test_openpgp_oid_is_ed25519): New.
* g10/build-packet.c (gpg_mpi_write): Write the length header also for
opaque MPIs.
(gpg_mpi_write_nohdr): New.
(do_key): Use gpg_mpi_write_nohdr depending on algorithm.
(do_pubkey_enc): Ditto.
* g10/ecdh.c (pk_ecdh_encrypt_with_shared_point): Use
gpg_mpi_write_nohdr.
* g10/export.c (transfer_format_to_openpgp):
* g10/keygen.c (ecckey_from_sexp): Return the error.
(gen_ecc): Repalce arg NBITS by CURVE.
(read_parameter_file): Add keywords "Key-Curve" and "Subkey-Curve".
(ask_curve): New.
(generate_keypair, generate_subkeypair): Use ask_curve.
(do_generate_keypair): Also pass curve name.
* g10/keylist.c (list_keyblock_print, list_keyblock_colon): Print
curve name.
* g10/parse-packet.c (mpi_read): Remove workaround for
Libcgrypt < 1.5.
(parse_key): Fix ECC case.  Print the curve name.
* g10/pkglue.c (mpi_from_sexp): Rename to get_mpi_from_sexp.
(pk_verify, pk_check_secret_key): Add special case for Ed25519.
* g10/seskey.c (encode_md_value): Ditto.
* g10/sign.c (do_sign, hash_for, sign_file): Ditto.
--

Be warned that this code is subject to further changes and that the
format will very likely change before a release.  There are also known
bugs and missing code.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2013-11-15 08:59:45 +01:00
parent 9ae48b173c
commit 402aa0f948
20 changed files with 574 additions and 139 deletions

View file

@ -324,6 +324,7 @@ gpg_error_t agent_public_key_from_file (ctrl_t ctrl,
const unsigned char *grip,
gcry_sexp_t *result);
int agent_is_dsa_key (gcry_sexp_t s_key);
int agent_is_eddsa_key (gcry_sexp_t s_key);
int agent_key_available (const unsigned char *grip);
gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
int *r_keytype,

View file

@ -729,6 +729,11 @@ key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list,
algoname = "dsa";
elems = "pqgy";
}
else if (n==3 && !memcmp (name, "ecc", 3))
{
algoname = "ecc";
elems = "pabgnq";
}
else if (n==5 && !memcmp (name, "ecdsa", 5))
{
algoname = "ecdsa";
@ -788,6 +793,8 @@ agent_is_dsa_key (gcry_sexp_t s_key)
if (!strcmp (algoname, "dsa"))
return GCRY_PK_DSA;
else if (!strcmp (algoname, "ecc"))
return GCRY_PK_ECDSA; /* FIXME: Check for the EdDSA flag. */
else if (!strcmp (algoname, "ecdsa"))
return GCRY_PK_ECDSA;
else
@ -795,6 +802,28 @@ agent_is_dsa_key (gcry_sexp_t s_key)
}
/* Return true if S_KEY is an EdDSA key as used with curve Ed25519. */
int
agent_is_eddsa_key (gcry_sexp_t s_key)
{
char algoname[6];
if (!s_key)
return 0;
if (key_parms_from_sexp (s_key, NULL, algoname, sizeof algoname, NULL, 0))
return 0; /* Error - assume it is not an DSA key. */
if (!strcmp (algoname, "dsa"))
return GCRY_PK_DSA;
else if (!strcmp (algoname, "ecc"))
return GCRY_PK_ECDSA; /* FIXME: Check for the EdDSA flag. */
else if (!strcmp (algoname, "ecdsa"))
return GCRY_PK_ECDSA;
else
return 0;
}
/* Return the key for the keygrip GRIP. The result is stored at
RESULT. This function extracts the key from the private key

View file

@ -131,6 +131,24 @@ rfc6979_hash_algo_string (size_t mdlen)
}
/* Encode a message digest for use with the EdDSA algorithm
(i.e. curve Ed25519). */
static gpg_error_t
do_encode_eddsa (const byte *md, size_t mdlen, gcry_sexp_t *r_hash)
{
gpg_error_t err;
gcry_sexp_t hash;
*r_hash = NULL;
err = gcry_sexp_build (&hash, NULL,
"(data(flags eddsa)(hash-algo sha512)(value %b))",
(int)mdlen, md);
if (!err)
*r_hash = hash;
return err;
}
/* Encode a message digest for use with an DSA algorithm. */
static gpg_error_t
do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
@ -400,7 +418,11 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
int dsaalgo;
/* Put the hash into a sexp */
if (ctrl->digest.algo == MD_USER_TLS_MD5SHA1)
if (agent_is_eddsa_key (s_skey))
rc = do_encode_eddsa (ctrl->digest.value,
ctrl->digest.valuelen,
&s_hash);
else if (ctrl->digest.algo == MD_USER_TLS_MD5SHA1)
rc = do_encode_raw_pkcs1 (ctrl->digest.value,
ctrl->digest.valuelen,
gcry_pk_get_nbits (s_skey),
@ -421,10 +443,8 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
if (DBG_CRYPTO)
{
log_debug ("skey:\n");
gcry_sexp_dump (s_skey);
log_debug ("hash:\n");
gcry_sexp_dump (s_hash);
gcry_log_debugsxp ("skey", s_skey);
gcry_log_debugsxp ("hash", s_hash);
}
/* sign */
@ -437,10 +457,7 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
}
if (DBG_CRYPTO)
{
log_debug ("result:\n");
gcry_sexp_dump (s_sig);
}
gcry_log_debugsxp ("rslt", s_sig);
}
leave:

View file

@ -467,6 +467,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
int depth = 0;
unsigned char *p;
gcry_md_hd_t md;
int have_curve = 0;
/* Create an S-expression with the protected-at timestamp. */
memcpy (timestamp_exp, "(12:protected-at15:", 19);
@ -499,6 +500,11 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
if (!protect_info[infidx].algo)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
/* The parser below is a complete mess: To make it robust for ECC
use we should reorder the s-expression to include only what we
really need and thus guarantee the right order for saving stuff.
This should be done before calling this function and maybe with
the help of the new gcry_sexp_extract_param. */
parmlist = protect_info[infidx].parmlist;
prot_from_idx = protect_info[infidx].prot_from;
prot_to_idx = protect_info[infidx].prot_to;
@ -522,10 +528,19 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
/* This is a private ECC key but the first parameter is
the name of the curve. We change the parameter list
here to the one we expect in this case. */
have_curve = 1;
parmlist = "?qd";
prot_from_idx = 2;
prot_to_idx = 2;
}
else if (n == 5 && !memcmp (s, "flags", 5)
&& i == 1 && have_curve)
{
/* "curve" followed by "flags": Change again. */
parmlist = "??qd";
prot_from_idx = 3;
prot_to_idx = 3;
}
else
return gpg_error (GPG_ERR_INV_SEXP);
}