[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