From dae4584f6ff4dbd6d95e73b72b51e23537110691 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Tue, 5 Mar 2013 21:27:41 -0500 Subject: [PATCH] Fix signing and verification when using DSA keys. Need to add a command line and SAVE option --sign-keyparams to generate new DSA keys. --- src/agent.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 123 insertions(+), 25 deletions(-) diff --git a/src/agent.c b/src/agent.c index a29a0678..4f0e4697 100644 --- a/src/agent.c +++ b/src/agent.c @@ -446,22 +446,106 @@ fail: return rc; } +static gpg_error_t +get_key_info (gcry_sexp_t pubkey, char **hash_str, int *hash_type, + size_t *len, int *pk_algo) +{ + unsigned nbits = gcry_pk_get_nbits (pubkey); + gcry_sexp_t sexp, tmp; + char *algo; + + tmp = gcry_sexp_find_token (pubkey, "public-key", 0); + if(!tmp) + return GPG_ERR_NO_PUBKEY; + + sexp = gcry_sexp_nth (tmp, 1); + gcry_sexp_release (tmp); + algo = gcry_sexp_nth_string (sexp, 0); + gcry_sexp_release (sexp); + + if (!algo) + { + return GPG_ERR_BAD_PUBKEY; + } + + if (!strcmp (algo, "rsa")) + { + *pk_algo = GCRY_PK_RSA; + *hash_str = "sha256"; + *hash_type = GCRY_MD_SHA256; + *len = gcry_md_get_algo_dlen (GCRY_MD_SHA256); + } + else if (!strcmp (algo, "dsa") || !strcmp (algo, "elg")) + { + if (!strcmp (algo, "dsa")) + *pk_algo = GCRY_PK_DSA; + else + *pk_algo = GCRY_PK_ELG; + + switch (nbits) + { + default: + case 512 ... 1024: + *hash_str = "sha1"; + *hash_type = GCRY_MD_SHA1; + *len = gcry_md_get_algo_dlen (GCRY_MD_SHA1); + break; + case 2048: + *hash_str = "sha224"; + *hash_type = GCRY_MD_SHA224; + *len = gcry_md_get_algo_dlen (GCRY_MD_SHA224); + break; + case 3072: + *hash_str = "sha256"; + *hash_type = GCRY_MD_SHA256; + *len = gcry_md_get_algo_dlen (GCRY_MD_SHA256); + break; + case 7680: + *hash_str = "sha384"; + *hash_type = GCRY_MD_SHA384; + *len = gcry_md_get_algo_dlen (GCRY_MD_SHA384); + break; + case 15360: + *hash_str = "sha512"; + *hash_type = GCRY_MD_SHA512; + *len = gcry_md_get_algo_dlen (GCRY_MD_SHA512); + break; + } + } + + gcry_free (algo); + return 0; +} + gpg_error_t -agent_verify (gcry_sexp_t pkey, gcry_sexp_t sig_sexp, const void *data, size_t len) +agent_verify (gcry_sexp_t pkey, gcry_sexp_t sig_sexp, const void *data, + size_t len) { - gpg_error_t rc; - unsigned hashlen = gcry_md_get_algo_dlen (GCRY_MD_SHA256); + size_t hashlen; + int pk_algo; unsigned char *hash; gcry_sexp_t data_sexp; + char *hash_str = NULL; + int hash_type; + gpg_error_t rc = get_key_info (pkey, &hash_str, &hash_type, &hashlen, + &pk_algo); + + if (rc) + return rc; hash = gcry_malloc (hashlen); if (!hash) return GPG_ERR_ENOMEM; - gcry_md_hash_buffer (GCRY_MD_SHA256, hash, data, len); - rc = gcry_sexp_build (&data_sexp, NULL, - "(data (flags pkcs1) (hash sha256 %b))", hashlen, - hash); + gcry_md_hash_buffer (hash_type, hash, data, len); + if (pk_algo == GCRY_PK_RSA) + rc = gcry_sexp_build (&data_sexp, NULL, + "(data (flags pkcs1) (hash %s %b))", hash_str, + hashlen, hash); + else + rc = gcry_sexp_build (&data_sexp, NULL, + "(data (flags raw) (value %b))", hashlen, hash); + gcry_free (hash); if (!rc) { @@ -545,14 +629,16 @@ agent_loopback_cb (void *user, const char *keyword) } static gpg_error_t -sign (gcry_sexp_t * rsexp, const char *sign_hexgrip, - struct crypto_s *crypto, const void *data, size_t len) +sign (gcry_sexp_t * rsexp, gcry_sexp_t sigpkey, struct crypto_s *crypto, + const void *data, size_t len) { gpg_error_t rc; char *result; - char *tmp = sign_hexgrip ? str_dup (sign_hexgrip) - : bin2hex (crypto->grip, sizeof (crypto->grip)); + unsigned char grip[20]; + char *tmp; + gcry_pk_get_keygrip (sigpkey, grip); + tmp = bin2hex (grip, sizeof(grip)); pthread_cleanup_push (xfree, tmp); log_write1 (_("Signed with keygrip %s"), tmp); rc = send_to_agent (crypto->agent, NULL, NULL, "SIGKEY %s", tmp); @@ -560,21 +646,34 @@ sign (gcry_sexp_t * rsexp, const char *sign_hexgrip, if (!rc) { unsigned char *hash; - unsigned hashlen = gcry_md_get_algo_dlen (GCRY_MD_SHA256); + size_t hashlen; + char *hash_str = NULL; + int hash_type; + int pk_algo; - hash = gcry_malloc (hashlen); - if (!hash) - return gpg_error (GPG_ERR_ENOMEM); + rc = get_key_info (sigpkey, &hash_str, &hash_type, &hashlen, &pk_algo); + if (!rc) + { + hash = gcry_malloc (hashlen); + if (!hash) + rc = gpg_error (GPG_ERR_ENOMEM); - gcry_md_hash_buffer (GCRY_MD_SHA256, hash, data, len); - tmp = bin2hex (hash, hashlen); - gcry_free (hash); - pthread_cleanup_push (xfree, tmp); - rc = send_to_agent (crypto->agent, NULL, NULL, - "SETHASH --hash=sha256 %s", tmp); - pthread_cleanup_pop (1); + if (!rc) + { + gcry_md_hash_buffer (hash_type, hash, data, len); + tmp = bin2hex (hash, hashlen); + gcry_free (hash); + pthread_cleanup_push (xfree, tmp); + rc = send_to_agent (crypto->agent, NULL, NULL, + "SETHASH --hash=%s %s", hash_str, tmp); + pthread_cleanup_pop (1); + } + } } + if (rc) + return rc; + if (!rc) { struct inquire_data_s idata = { 0 }; @@ -642,13 +741,12 @@ encrypt_data_file (assuan_context_t ctx, struct crypto_s * crypto, xfree (hexgrip); hexgrip = bin2hex (sig_grip, 20); pthread_cleanup_push (gcry_free, enc_xml); - rc = sign (&sig_sexp, hexgrip, crypto, enc_xml, enc_xml_len); + rc = sign (&sig_sexp, sigpkey, crypto, enc_xml, enc_xml_len); xfree (hexgrip); if (!rc) { rc = agent_verify (sigpkey, sig_sexp, enc_xml, enc_xml_len); - if (!rc) { gcry_sexp_t tmp_sexp; @@ -754,7 +852,7 @@ generate_key (struct crypto_s * crypto, char *sexpstr, int empty, int preset) gcry_pk_get_keygrip (crypto->save.pkey, grip); char *hexgrip = bin2hex (grip, sizeof (grip)); - log_write1 (_("Keygrip is %s"), hexgrip); + log_write (_("Keygrip is %s"), hexgrip); xfree (hexgrip); if (!crypto->save.sigpkey) -- 2.11.4.GIT