From 137e3a0fbcdc579b56860651a9b5554f9449ed1e Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Tue, 28 Jun 2011 20:35:13 -0400 Subject: [PATCH] Added gpg-agent OPTION "s2k-count". When unset or 0, the calibrated count will be used. --- agent/ChangeLog | 8 ++++++++ agent/agent.h | 5 ++++- agent/command-ssh.c | 2 +- agent/command.c | 11 ++++++++++- agent/genkey.c | 12 +++++++----- agent/protect-tool.c | 2 +- agent/protect.c | 14 +++++++++----- agent/t-protect.c | 2 +- 8 files changed, 41 insertions(+), 15 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 156fbdb77..3234aae1f 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,11 @@ +2011-06-28 Ben Kibbey + + * command.c (option_handler): Add option s2k-count. + * agent.h (server_control_s): Add member s2k_count. + * genkey.c (store_key): Add parameter s2k_count. + * protect.c (agent_protect): Add parameter s2k_count. + * protect.c (do_encryption): Add parameter s2k_count. + 2011-06-01 Marcus Brinkmann * cvt-openpgp.c (convert_to_openpgp): Change type of N to unsigned diff --git a/agent/agent.h b/agent/agent.h index 9aaf26441..dfc82ec2f 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -181,6 +181,8 @@ struct server_control_s PKSIGN command to the scdaemon. */ int in_passwd; /* Hack to inhibit enforced passphrase change during an explicit passwd command. */ + + unsigned long s2k_count; /* Other than the calibrated count. */ }; @@ -332,7 +334,8 @@ gpg_error_t agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey, unsigned long get_standard_s2k_count (void); unsigned char get_standard_s2k_count_rfc4880 (void); int agent_protect (const unsigned char *plainkey, const char *passphrase, - unsigned char **result, size_t *resultlen); + unsigned char **result, size_t *resultlen, + unsigned long s2k_count); int agent_unprotect (const unsigned char *protectedkey, const char *passphrase, gnupg_isotime_t protected_at, unsigned char **result, size_t *resultlen); diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 8603a539b..e3a041012 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -2341,7 +2341,7 @@ ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase, gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n); /* FIXME: guarantee? */ - err = agent_protect (buffer_new, passphrase, buffer, buffer_n); + err = agent_protect (buffer_new, passphrase, buffer, buffer_n, 0); out: diff --git a/agent/command.c b/agent/command.c index 62bf14501..d1f6fb9b6 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1866,7 +1866,8 @@ cmd_import_key (assuan_context_t ctx, char *line) if (passphrase) { - err = agent_protect (key, passphrase, &finalkey, &finalkeylen); + err = agent_protect (key, passphrase, &finalkey, &finalkeylen, + ctrl->s2k_count); if (!err) err = agent_write_private_key (grip, finalkey, finalkeylen, 0); } @@ -2474,6 +2475,14 @@ option_handler (assuan_context_t ctx, const char *key, const char *value) { ctrl->cache_ttl_opt_preset = *value? atoi (value) : 0; } + else if (!strcmp (key, "s2k-count")) + { + ctrl->s2k_count = *value? strtoul(value, NULL, 10) : 0; + if (ctrl->s2k_count && ctrl->s2k_count < 65536) { + ctrl->s2k_count = 0; + err = gpg_error (GPG_ERR_INV_VALUE); + } + } else err = gpg_error (GPG_ERR_UNKNOWN_OPTION); diff --git a/agent/genkey.c b/agent/genkey.c index 79b99e6e5..e01a7bcb6 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -31,7 +31,8 @@ #include "sysutils.h" static int -store_key (gcry_sexp_t private, const char *passphrase, int force) +store_key (gcry_sexp_t private, const char *passphrase, int force, + unsigned long s2k_count) { int rc; unsigned char *buf; @@ -56,7 +57,7 @@ store_key (gcry_sexp_t private, const char *passphrase, int force) { unsigned char *p; - rc = agent_protect (buf, passphrase, &p, &len); + rc = agent_protect (buf, passphrase, &p, &len, s2k_count); if (rc) { xfree (buf); @@ -420,7 +421,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce, /* store the secret key */ if (DBG_CRYPTO) log_debug ("storing private key\n"); - rc = store_key (s_private, passphrase, 0); + rc = store_key (s_private, passphrase, 0, ctrl->s2k_count); if (!rc) { if (!cache_nonce) @@ -492,7 +493,8 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey, if (passphrase_addr && *passphrase_addr) { /* Take an empty string as request not to protect the key. */ - err = store_key (s_skey, **passphrase_addr? *passphrase_addr:NULL, 1); + err = store_key (s_skey, **passphrase_addr? *passphrase_addr:NULL, 1, + ctrl->s2k_count); } else { @@ -507,7 +509,7 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey, _("Please enter the new passphrase"), &pass); if (!err) - err = store_key (s_skey, pass, 1); + err = store_key (s_skey, pass, 1, ctrl->s2k_count); if (!err && passphrase_addr) *passphrase_addr = pass; else diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 512019b80..a2531438c 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -333,7 +333,7 @@ read_and_protect (const char *fname) return; pw = get_passphrase (1); - rc = agent_protect (key, pw, &result, &resultlen); + rc = agent_protect (key, pw, &result, &resultlen, 0); release_passphrase (pw); xfree (key); if (rc) diff --git a/agent/protect.c b/agent/protect.c index 7df82de03..64af4ed8e 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -309,7 +309,8 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash) static int do_encryption (const unsigned char *protbegin, size_t protlen, const char *passphrase, const unsigned char *sha1hash, - unsigned char **result, size_t *resultlen) + unsigned char **result, size_t *resultlen, + unsigned long s2k_count) { gcry_cipher_hd_t hd; const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"; @@ -368,7 +369,8 @@ do_encryption (const unsigned char *protbegin, size_t protlen, { rc = hash_passphrase (passphrase, GCRY_MD_SHA1, 3, iv+2*blklen, - get_standard_s2k_count (), key, keylen); + s2k_count ? s2k_count : get_standard_s2k_count(), + key, keylen); if (!rc) rc = gcry_cipher_setkey (hd, key, keylen); xfree (key); @@ -411,7 +413,8 @@ do_encryption (const unsigned char *protbegin, size_t protlen, { char countbuf[35]; - snprintf (countbuf, sizeof countbuf, "%lu", get_standard_s2k_count ()); + snprintf (countbuf, sizeof countbuf, "%lu", + s2k_count ? s2k_count : get_standard_s2k_count ()); p = xtryasprintf ("(9:protected%d:%s((4:sha18:%n_8bytes_%u:%s)%d:%n%*s)%d:%n%*s)", (int)strlen (modestr), modestr, @@ -443,7 +446,8 @@ do_encryption (const unsigned char *protbegin, size_t protlen, a valid S-Exp here. */ int agent_protect (const unsigned char *plainkey, const char *passphrase, - unsigned char **result, size_t *resultlen) + unsigned char **result, size_t *resultlen, + unsigned long s2k_count) { int rc; const unsigned char *s; @@ -544,7 +548,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, rc = do_encryption (prot_begin, prot_end - prot_begin + 1, passphrase, hashvalue, - &protected, &protectedlen); + &protected, &protectedlen, s2k_count); if (rc) return rc; diff --git a/agent/t-protect.c b/agent/t-protect.c index a14e5e1cc..4b6e0b48c 100644 --- a/agent/t-protect.c +++ b/agent/t-protect.c @@ -174,7 +174,7 @@ test_agent_protect (void) { ret = agent_protect ((const unsigned char*)specs[i].key, specs[i].passphrase, - &specs[i].result, &specs[i].resultlen); + &specs[i].result, &specs[i].resultlen, 0); if (gpg_err_code (ret) != specs[i].ret_expected) { printf ("agent_protect() returned `%i/%s'; expected `%i/%s'\n",