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 3dba79ebd..73c31f786 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -27,7 +27,6 @@ #include "agent.h" #include "i18n.h" #include "cvt-openpgp.h" -#include "../include/cipher.h" /* for PUBKEY_ALGO_ECDSA, PUBKEY_ALGO_ECDH */ /* Helper to pass data via the callback to do_unprotect. */ @@ -50,12 +49,7 @@ struct try_do_unprotect_arg_s gcry_sexp_t *r_key; }; -/* TODO: it is also in misc, which is not linked with the agent */ -static int -map_pk_openpgp_to_gcry (int algo) -{ - return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo)); -} + /* Compute the keygrip from the public key and store it at GRIP. */ static gpg_error_t diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index ca150b471..d85283a5e 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,10 @@ 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 */ +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..a6dbf2509 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -119,12 +119,15 @@ do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, gpg_error_t err; gcry_sexp_t hash; unsigned int qbits; + int gcry_pkalgo; *r_hash = NULL; - if (dsaalgo == GCRY_PK_ECDSA) + gcry_pkalgo = map_pk_openpgp_to_gcry( dsaalgo ); + + if (gcry_pkalgo == GCRY_PK_ECDSA) qbits = gcry_pk_get_nbits (pkey); - else if (dsaalgo == GCRY_PK_DSA) + else if (gcry_pkalgo == GCRY_PK_DSA) qbits = get_dsa_qbits (pkey); else return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); @@ -143,20 +146,25 @@ 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 (gcry_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) + + /* 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 < ((gcry_pkalgo==GCRY_PK_ECDSA && qbits>521) ? 512 : qbits) ) { log_error (_("a %zu bit hash is not valid for a %u bit %s key\n"), - mdlen*8, + mdlen, gcry_pk_get_nbits (pkey), - gcry_pk_algo_name (dsaalgo)); + gcry_pk_algo_name (gcry_pkalgo)); /* FIXME: we need to check the requirements for ECDSA. */ - if (mdlen < 20 || dsaalgo == GCRY_PK_DSA) + if (mdlen < 20 || gcry_pkalgo == GCRY_PK_DSA) return gpg_error (GPG_ERR_INV_LENGTH); } diff --git a/g10/seskey.c b/g10/seskey.c index 4cc9158c9..e50cf5c02 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -288,7 +288,6 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) * Therefore, relax the check, but only for ECDSA keys. We may need to adjust it later for general case. * ( Note that the check will never pass for ECDSA 521 anyway as the only hash that intended to match it is SHA 512, but 512 < 521 ). */ - //if (gcry_md_get_algo_dlen (hash_algo) < qbytes ) if (gcry_md_get_algo_dlen (hash_algo) < ((gcry_pkalgo==GCRY_PK_ECDSA && qbytes>(521)/8) ? 512/8 : qbytes) ) { log_error (_("%s key %s requires a %zu bit or larger hash, used hash-algo=%d\n"), @@ -297,8 +296,9 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) return NULL; } + /* Note that in case of ECDSA 521 hash is always smaller than the key size */ if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG, - gcry_md_read (md, hash_algo), qbytes, &qbytes)) + gcry_md_read (md, hash_algo), gcry_md_get_algo_dlen (hash_algo), &qbytes)) BUG(); } else