diff options
Diffstat (limited to 'agent')
-rw-r--r-- | agent/ChangeLog | 6 | ||||
-rw-r--r-- | agent/agent.h | 1 | ||||
-rw-r--r-- | agent/cvt-openpgp.c | 47 | ||||
-rw-r--r-- | agent/findkey.c | 10 | ||||
-rw-r--r-- | agent/gpg-agent.c | 10 | ||||
-rw-r--r-- | agent/pksign.c | 27 | ||||
-rw-r--r-- | agent/protect.c | 6 |
7 files changed, 89 insertions, 18 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog index 542695bea..7dace3aef 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -2,6 +2,12 @@ * trustlist.c (read_one_trustfile): Also chop an CR. +2011-01-21 Werner Koch <[email protected]> + + * pksign.c (do_encode_dsa): Compare MDLEN to bytes. + + * cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: New. + 2010-12-02 Werner Koch <[email protected]> * gpg-agent.c (CHECK_OWN_SOCKET_INTERVAL) [W32CE]: Set to 60 diff --git a/agent/agent.h b/agent/agent.h index 7716bb0c2..e31b6a78e 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -215,6 +215,7 @@ const char *get_agent_ssh_socket_name (void); void *get_agent_scd_notify_event (void); #endif void agent_sighup_action (void); +int map_pk_openpgp_to_gcry (int openpgp_algo); /*-- command.c --*/ gpg_error_t agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid); diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c index e6a14c436..02c2bc841 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -28,6 +28,13 @@ #include "i18n.h" #include "cvt-openpgp.h" +/* Macros for compatibility with older libgcrypt versions. */ +#ifndef HAVE_GCRY_PK_ECDSA +# define GCRY_PK_ECDH 302 +#endif + + + /* Helper to pass data via the callback to do_unprotect. */ struct try_do_unprotect_arg_s @@ -80,6 +87,12 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip) "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]); break; + case GCRY_PK_ECDSA: + case GCRY_PK_ECDH: + err = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecc(c%m)(q%m)))", pkey[0], pkey[1]); + break; + default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); break; @@ -94,7 +107,9 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip) /* Convert a secret key given as algorithm id and an array of key - parameters into our s-expression based format. */ + parameters into our s-expression based format. Note that + PUBKEY_ALGO is a standard id and not an OpenPGP id. + */ static gpg_error_t convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) { @@ -103,6 +118,9 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) *r_key = NULL; + /* FIXME: This is not consistent with the above comment. */ + pubkey_algo = map_pk_openpgp_to_gcry (pubkey_algo); + switch (pubkey_algo) { case GCRY_PK_DSA: @@ -128,6 +146,18 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) skey[5]); break; + case GCRY_PK_ECDSA: + err = gcry_sexp_build (&s_skey, NULL, + "(private-key(ecdsa(c%m)(q%m)(d%m)))", + skey[0], skey[1], skey[2]); + break; + + case GCRY_PK_ECDH: + err = gcry_sexp_build (&s_skey, NULL, + "(private-key(ecdh(c%m)(q%m)(p%m)(d%m)))", + skey[0], skey[1], skey[2], skey[3]); + break; + default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); break; @@ -202,6 +232,10 @@ do_unprotect (const char *passphrase, *r_key = NULL; + /* Unfortunately, the OpenPGP PK algorithm numbers need to be + re-mapped for Libgcrypt. */ + pubkey_algo = map_pk_openpgp_to_gcry (pubkey_algo); + /* Count the actual number of MPIs is in the array and set the remainder to NULL for easier processing later on. */ for (skeylen = 0; skey[skeylen]; skeylen++) @@ -219,9 +253,6 @@ do_unprotect (const char *passphrase, if (gcry_pk_test_algo (pubkey_algo)) { - /* The algorithm numbers are Libgcrypt numbers but fortunately - the OpenPGP algorithm numbers map one-to-one to the Libgcrypt - numbers. */ log_info (_("public key algorithm %d (%s) is not supported\n"), pubkey_algo, gcry_pk_algo_name (pubkey_algo)); return gpg_error (GPG_ERR_PUBKEY_ALGO); @@ -1007,7 +1038,8 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, case GCRY_PK_ELG: algoname = "elg"; npkey = 3; elems = "pgyx"; break; case GCRY_PK_ELG_E: algoname = "elg"; npkey = 3; elems = "pgyx"; break; case GCRY_PK_DSA: algoname = "dsa"; npkey = 4; elems = "pqgyx"; break; - case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 6; elems = "pabgnqd"; break; + case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 2; elems = "cqd"; break; + case GCRY_PK_ECDH: algoname = "ecdh"; npkey = 3; elems = "cqpd"; break; default: algoname = ""; npkey = 0; elems = NULL; break; } assert (!elems || strlen (elems) < DIM (array) ); @@ -1037,7 +1069,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, int format_args_buf_int[1]; void *format_args[10+2]; size_t n; - gcry_sexp_t tmpkey, tmpsexp; + gcry_sexp_t tmpkey, tmpsexp = NULL; snprintf (countbuf, sizeof countbuf, "%lu", s2k_count); @@ -1085,7 +1117,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, for (i=0; i < DIM (array); i++) gcry_mpi_release (array[i]); - + return err; } - diff --git a/agent/findkey.c b/agent/findkey.c index 91fb8c14c..02e938e6e 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -726,6 +726,16 @@ key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list, algoname = "dsa"; elems = "pqgy"; } + else if (n==5 && !memcmp (name, "ecdsa", 5)) + { + algoname = "ecdsa"; + elems = "cq"; + } + else if (n==4 && !memcmp (name, "ecdh", 4)) + { + algoname = "ecdh"; + elems = "cqp"; + } else if (n==3 && !memcmp (name, "elg", 3)) { algoname = "elg"; diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index ca150b471..db9039278 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -51,6 +51,7 @@ #include "gc-opt-flags.h" #include "exechelp.h" #include "asshelp.h" +#include "../include/cipher.h" /* for PUBKEY_ALGO_ECDSA, PUBKEY_ALGO_ECDH */ enum cmd_and_opt_values { aNull = 0, @@ -2301,3 +2302,12 @@ check_for_running_agent (int silent, int mode) assuan_release (ctx); return 0; } + +/* TODO: it is also in misc, which is not linked with the agent */ +/* FIXME: The agent should not know about openpgp internals - weel + except for some stuff in cvt-openpgp. */ +int +map_pk_openpgp_to_gcry (int algo) +{ + return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo)); +} diff --git a/agent/pksign.c b/agent/pksign.c index ac5f4e1a0..0414bc347 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -113,18 +113,21 @@ get_dsa_qbits (gcry_sexp_t key) /* 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, +do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, gcry_sexp_t *r_hash) { gpg_error_t err; gcry_sexp_t hash; unsigned int qbits; + int pkalgo; *r_hash = NULL; - if (dsaalgo == GCRY_PK_ECDSA) + pkalgo = map_pk_openpgp_to_gcry (dsaalgo); + + if (pkalgo == GCRY_PK_ECDSA) qbits = gcry_pk_get_nbits (pkey); - else if (dsaalgo == GCRY_PK_DSA) + else if (pkalgo == GCRY_PK_DSA) qbits = get_dsa_qbits (pkey); else return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); @@ -143,20 +146,28 @@ do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, if (qbits < 160) { log_error (_("%s key uses an unsafe (%u bit) hash\n"), - gcry_pk_algo_name (dsaalgo), qbits); + gcry_pk_algo_name (pkalgo), qbits); return gpg_error (GPG_ERR_INV_LENGTH); } /* Check if we're too short. Too long is safe as we'll - automatically left-truncate. */ - if (mdlen < qbits/8) + * automatically left-truncate. + * + * This check would require the use of SHA512 with ECDSA 512. I + * think this is overkill to fail in this case. Therefore, relax + * the check, but only for ECDSA keys. We may need to adjust it + * later for general case. (Note that the check is really a bug for + * ECDSA 521 as the only hash that matches it is SHA 512, but 512 < + * 521 ). + */ + if (mdlen < ((pkalgo==GCRY_PK_ECDSA && qbits > 521) ? 512 : qbits)/8) { log_error (_("a %zu bit hash is not valid for a %u bit %s key\n"), mdlen*8, gcry_pk_get_nbits (pkey), - gcry_pk_algo_name (dsaalgo)); + gcry_pk_algo_name (pkalgo)); /* FIXME: we need to check the requirements for ECDSA. */ - if (mdlen < 20 || dsaalgo == GCRY_PK_DSA) + if (mdlen < 20 || pkalgo == GCRY_PK_DSA) return gpg_error (GPG_ERR_INV_LENGTH); } diff --git a/agent/protect.c b/agent/protect.c index 795d06231..d0a5fe9e3 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -43,7 +43,7 @@ /* A table containing the information needed to create a protected - private key */ + private key. */ static struct { const char *algo; const char *parmlist; @@ -52,6 +52,8 @@ static struct { { "rsa", "nedpqu", 2, 5 }, { "dsa", "pqgyx", 4, 4 }, { "elg", "pgyx", 3, 3 }, + { "ecdsa","cqd", 2, 2 }, + { "ecdh", "cqpd", 3, 3 }, { NULL } }; @@ -488,7 +490,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, depth--; hash_end = s; s++; - /* skip to the end of the S-exp */ + /* Skip to the end of the S-expression. */ assert (depth == 1); rc = sskip (&s, &depth); if (rc) |