diff options
Diffstat (limited to 'agent')
-rw-r--r-- | agent/agent.h | 1 | ||||
-rw-r--r-- | agent/findkey.c | 29 | ||||
-rw-r--r-- | agent/pksign.c | 35 | ||||
-rw-r--r-- | agent/protect.c | 15 |
4 files changed, 71 insertions, 9 deletions
diff --git a/agent/agent.h b/agent/agent.h index ae4e4686f..d40930018 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -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, diff --git a/agent/findkey.c b/agent/findkey.c index d11f0888a..aa2c6a2c1 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -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 diff --git a/agent/pksign.c b/agent/pksign.c index 9c7341a7f..b2ee28f22 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -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: diff --git a/agent/protect.c b/agent/protect.c index b29f494fb..749867cc1 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -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); } |