[PATCH] Allow the user to specify AES256 as well as AES128.

Kyle Butt kylebutt at gmail.com
Tue May 21 19:34:00 CEST 2013


---
 agent/agent.h     |   4 +++
 agent/gpg-agent.c |   6 +++-
 agent/protect.c   | 104 +++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 81 insertions(+), 33 deletions(-)

diff --git a/agent/agent.h b/agent/agent.h
index 2fd0b8b..a4f83f8 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -133,6 +133,10 @@ struct
 
   /* This global option enables the ssh-agent subsystem.  */
   int ssh_support;
+
+  /* This global option sets the protect mode for keys in the private key
+     store */
+  const char* protect_cipher;
 } opt;
 
 
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 4690114..2c2d915 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -112,7 +112,8 @@ enum cmd_and_opt_values
   oKeepDISPLAY,
   oSSHSupport,
   oDisableScdaemon,
-  oWriteEnvFile
+  oWriteEnvFile,
+  oProtectCipher,
 };
 
 
@@ -187,6 +188,7 @@ static ARGPARSE_OPTS opts[] = {
   { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") },
   { oWriteEnvFile, "write-env-file", 2|8,
             N_("|FILE|write environment settings also to FILE")},
+  { oProtectCipher, "protect-cipher", 2, N_("|CIPHER|protect private keys using CIPHER")},
   {0}
 };
 
@@ -814,6 +816,8 @@ main (int argc, char **argv )
           else
             env_file_name = make_filename ("~/.gpg-agent-info", NULL);
           break;
+        case oProtectCipher:
+          opt.protect_cipher = xstrdup(pargs.r.ret_str); break;
 
         default : pargs.err = configfp? 1:2; break;
 	}
diff --git a/agent/protect.c b/agent/protect.c
index 3e2cbb9..d0985b2 100644
--- a/agent/protect.c
+++ b/agent/protect.c
@@ -44,6 +44,21 @@
 /* Decode an rfc4880 encoded S2K count.  */
 #define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6))
 
+/* A table containing the information needed to encrypt a protected
+   private key */
+static struct {
+  const char *algo;
+  int cipher;
+  int mode;
+  int keylen;
+} cipher_info[] = {
+  {"openpgp-s2k3-sha1-aes-cbc", GCRY_CIPHER_AES,
+   GCRY_CIPHER_MODE_CBC, (128/8)},
+  {"openpgp-s2k3-sha1-aes256-cbc", GCRY_CIPHER_AES256,
+   GCRY_CIPHER_MODE_CBC, (256/8)},
+  { NULL }
+};
+#define FALLBACK_CIPHER_INDEX 0
 
 /* A table containing the information needed to create a protected
    private key.  */
@@ -75,6 +90,19 @@ struct calibrate_time_s
 
 
 static int
+get_default_cipher(int *result) {
+  int cipher_idx;
+  for (cipher_idx=0; cipher_info[cipher_idx].algo
+              && strcmp (opt.protect_cipher, cipher_info[cipher_idx].algo);
+              cipher_idx++)
+    ;
+  if (!cipher_info[cipher_idx].algo)
+    return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
+  *result = cipher_idx;
+  return 0;
+}
+
+static int
 hash_passphrase (const char *passphrase, int hashalgo,
                  int s2kmode,
                  const unsigned char *s2ksalt, unsigned long s2kcount,
@@ -133,10 +161,10 @@ calibrate_elapsed_time (struct calibrate_time_s *starttime)
 /* Run a test hashing for COUNT and return the time required in
    milliseconds.  */
 static unsigned long
-calibrate_s2k_count_one (unsigned long count)
+calibrate_s2k_count_one (int cipher_idx, unsigned long count)
 {
   int rc;
-  char keybuf[PROT_CIPHER_KEYLEN];
+  char keybuf[cipher_info[cipher_idx].keylen];
   struct calibrate_time_s starttime;
 
   calibrate_get_time (&starttime);
@@ -155,10 +183,13 @@ calibrate_s2k_count (void)
 {
   unsigned long count;
   unsigned long ms;
+  int cipher_idx;
+  if (get_default_cipher(&cipher_idx))
+    cipher_idx = FALLBACK_CIPHER_INDEX;
 
   for (count = 65536; count; count *= 2)
     {
-      ms = calibrate_s2k_count_one (count);
+      ms = calibrate_s2k_count_one (cipher_idx, count);
       if (opt.verbose > 1)
         log_info ("S2K calibration: %lu -> %lums\n", count, ms);
       if (ms > 100)
@@ -173,7 +204,7 @@ calibrate_s2k_count (void)
 
   if (opt.verbose)
     {
-      ms = calibrate_s2k_count_one (count);
+      ms = calibrate_s2k_count_one (cipher_idx, count);
       log_info ("S2K calibration: %lu -> %lums\n", count, ms);
     }
 
@@ -309,12 +340,12 @@ 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 long s2k_count)
+               int cipher_idx, const char *passphrase,
+               const unsigned char *sha1hash, 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";
+  char *modestr = cipher_info[cipher_idx].algo;
   int blklen, enclen, outlen;
   unsigned char *iv = NULL;
   int rc;
@@ -325,8 +356,8 @@ do_encryption (const unsigned char *protbegin, size_t protlen,
   *resultlen = 0;
   *result = NULL;
 
-  rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
-                         GCRY_CIPHER_SECURE);
+  rc = gcry_cipher_open (&hd, cipher_info[cipher_idx].cipher,
+                         cipher_info[cipher_idx].mode, GCRY_CIPHER_SECURE);
   if (rc)
     return rc;
 
@@ -340,7 +371,7 @@ do_encryption (const unsigned char *protbegin, size_t protlen,
 
      We always append a full block of random bytes as padding but
      encrypt only what is needed for a full blocksize.  */
-  blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
+  blklen = gcry_cipher_get_algo_blklen (cipher_info[cipher_idx].cipher);
   outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen;
   enclen = outlen/blklen * blklen;
   outbuf = gcry_malloc_secure (outlen);
@@ -361,7 +392,7 @@ do_encryption (const unsigned char *protbegin, size_t protlen,
   if (!rc)
     {
       unsigned char *key;
-      size_t keylen = PROT_CIPHER_KEYLEN;
+      size_t keylen = cipher_info[cipher_idx].keylen;
 
       key = gcry_malloc_secure (keylen);
       if (!key)
@@ -457,7 +488,8 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
   const unsigned char *hash_begin, *hash_end;
   const unsigned char *prot_begin, *prot_end, *real_end;
   size_t n;
-  int c, infidx, i;
+  int c, i;
+  int inf_idx, cipher_idx;
   unsigned char hashvalue[20];
   char timestamp_exp[35];
   unsigned char *protected;
@@ -491,15 +523,19 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
   if (!n)
     return gpg_error (GPG_ERR_INV_SEXP);
 
-  for (infidx=0; protect_info[infidx].algo
-              && !smatch (&s, n, protect_info[infidx].algo); infidx++)
+  for (inf_idx=0; protect_info[inf_idx].algo
+              && !smatch (&s, n, protect_info[inf_idx].algo); inf_idx++)
     ;
-  if (!protect_info[infidx].algo)
+  if (!protect_info[inf_idx].algo)
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
 
-  parmlist      = protect_info[infidx].parmlist;
-  prot_from_idx = protect_info[infidx].prot_from;
-  prot_to_idx   = protect_info[infidx].prot_to;
+  /* Get protection cipher */
+  if (get_default_cipher(&cipher_idx))
+    cipher_idx = FALLBACK_CIPHER_INDEX;
+
+  parmlist      = protect_info[inf_idx].parmlist;
+  prot_from_idx = protect_info[inf_idx].prot_from;
+  prot_to_idx   = protect_info[inf_idx].prot_to;
   prot_begin = prot_end = NULL;
   for (i=0; (c=parmlist[i]); i++)
     {
@@ -515,7 +551,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
       if (n != 1 || c != *s)
         {
           if (n == 5 && !memcmp (s, "curve", 5)
-              && !i && protect_info[infidx].ecc_hack)
+              && !i && protect_info[inf_idx].ecc_hack)
             {
               /* This is a private ECC key but the first parameter is
                  the name of the curve.  We change the parameter list
@@ -565,7 +601,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
   gcry_md_close (md);
 
   rc = do_encryption (prot_begin, prot_end - prot_begin + 1,
-                      passphrase,  hashvalue,
+                      cipher_idx, passphrase,  hashvalue,
                       &protected, &protectedlen, s2k_count);
   if (rc)
     return rc;
@@ -608,7 +644,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
 /* Do the actual decryption and check the return list for consistency.  */
 static int
 do_decryption (const unsigned char *protected, size_t protectedlen,
-               const char *passphrase,
+               int cipher_idx, const char *passphrase,
                const unsigned char *s2ksalt, unsigned long s2kcount,
                const unsigned char *iv, size_t ivlen,
                unsigned char **result)
@@ -619,12 +655,12 @@ do_decryption (const unsigned char *protected, size_t protectedlen,
   unsigned char *outbuf;
   size_t reallen;
 
-  blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
+  blklen = gcry_cipher_get_algo_blklen (cipher_info[cipher_idx].cipher);
   if (protectedlen < 4 || (protectedlen%blklen))
     return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
 
-  rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
-                         GCRY_CIPHER_SECURE);
+  rc = gcry_cipher_open (&hd, cipher_info[cipher_idx].cipher,
+                         cipher_info[cipher_idx].mode, GCRY_CIPHER_SECURE);
   if (rc)
     return rc;
 
@@ -636,7 +672,7 @@ do_decryption (const unsigned char *protected, size_t protectedlen,
   if (!rc)
     {
       unsigned char *key;
-      size_t keylen = PROT_CIPHER_KEYLEN;
+      size_t keylen = cipher_info[cipher_idx].keylen;
 
       key = gcry_malloc_secure (keylen);
       if (!key)
@@ -842,7 +878,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
   const unsigned char *s;
   const unsigned char *protect_list;
   size_t n;
-  int infidx, i;
+  int inf_idx, cipher_idx, i;
   unsigned char sha1hash[20], sha1hash2[20];
   const unsigned char *s2ksalt;
   unsigned long s2kcount;
@@ -872,10 +908,10 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
   if (!n)
     return gpg_error (GPG_ERR_INV_SEXP);
 
-  for (infidx=0; protect_info[infidx].algo
-              && !smatch (&s, n, protect_info[infidx].algo); infidx++)
+  for (inf_idx=0; protect_info[inf_idx].algo
+              && !smatch (&s, n, protect_info[inf_idx].algo); inf_idx++)
     ;
-  if (!protect_info[infidx].algo)
+  if (!protect_info[inf_idx].algo)
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
 
 
@@ -937,8 +973,12 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
   n = snext (&s);
   if (!n)
     return gpg_error (GPG_ERR_INV_SEXP);
-  if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
+  for (cipher_idx=0; cipher_info[cipher_idx].algo
+              && !smatch (&s, n, cipher_info[cipher_idx].algo); cipher_idx++)
+    ;
+  if (!cipher_info[cipher_idx].algo)
     return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
+
   if (*s != '(' || s[1] != '(')
     return gpg_error (GPG_ERR_INV_SEXP);
   s += 2;
@@ -993,7 +1033,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
     return gpg_error (GPG_ERR_INV_SEXP);
 
   cleartext = NULL; /* Avoid cc warning. */
-  rc = do_decryption (s, n,
+  rc = do_decryption (s, n, cipher_idx,
                       passphrase, s2ksalt, s2kcount,
                       iv, 16,
                       &cleartext);
-- 
1.7.11.7




More information about the Gnupg-devel mailing list