aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-09-01 08:15:21 +0000
committerWerner Koch <[email protected]>2014-09-01 08:15:21 +0000
commitc913e09ebdbb1a1e9838a0a5897448841f5e9bc3 (patch)
treee3169937292ea34d79e295cb731cd514834f984c
parentspeedo: Fix for non-Windows build of glib. (diff)
downloadgnupg-c913e09ebdbb1a1e9838a0a5897448841f5e9bc3.tar.gz
gnupg-c913e09ebdbb1a1e9838a0a5897448841f5e9bc3.zip
agent: Allow key unprotection using AES-256.
* agent/protect.c (PROT_CIPHER): Rename to GCRY_CIPHER_AES128 for clarity. (do_decryption): Add args prot_cipher and prot_cipher_keylen. USe them instead of the hardwired values. (agent_unprotect): Change to use a table of protection algorithms. Add AES-256 variant. -- This patch will make a possible future key protection algorithm changes smoother. AES-256 is also allowed although there is currently no way to encrypt using it.
Diffstat (limited to '')
-rw-r--r--agent/protect.c79
1 files changed, 50 insertions, 29 deletions
diff --git a/agent/protect.c b/agent/protect.c
index 3a0021871..f633d562e 100644
--- a/agent/protect.c
+++ b/agent/protect.c
@@ -42,7 +42,9 @@
#include "cvt-openpgp.h"
#include "sexp-parse.h"
-#define PROT_CIPHER GCRY_CIPHER_AES
+/* The protection mode for encryption. The supported modes for
+ decryption are listed in agent_unprotect(). */
+#define PROT_CIPHER GCRY_CIPHER_AES128
#define PROT_CIPHER_STRING "aes"
#define PROT_CIPHER_KEYLEN (128/8)
@@ -632,6 +634,7 @@ do_decryption (const unsigned char *protected, size_t protectedlen,
const char *passphrase,
const unsigned char *s2ksalt, unsigned long s2kcount,
const unsigned char *iv, size_t ivlen,
+ int prot_cipher, int prot_cipher_keylen,
unsigned char **result)
{
int rc = 0;
@@ -640,11 +643,11 @@ 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 (prot_cipher);
if (protectedlen < 4 || (protectedlen%blklen))
return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
- rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
+ rc = gcry_cipher_open (&hd, prot_cipher, GCRY_CIPHER_MODE_CBC,
GCRY_CIPHER_SECURE);
if (rc)
return rc;
@@ -657,17 +660,16 @@ do_decryption (const unsigned char *protected, size_t protectedlen,
if (!rc)
{
unsigned char *key;
- size_t keylen = PROT_CIPHER_KEYLEN;
- key = gcry_malloc_secure (keylen);
+ key = gcry_malloc_secure (prot_cipher_keylen);
if (!key)
rc = out_of_core ();
else
{
rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
- 3, s2ksalt, s2kcount, key, keylen);
+ 3, s2ksalt, s2kcount, key, prot_cipher_keylen);
if (!rc)
- rc = gcry_cipher_setkey (hd, key, keylen);
+ rc = gcry_cipher_setkey (hd, key, prot_cipher_keylen);
xfree (key);
}
}
@@ -860,6 +862,15 @@ agent_unprotect (ctrl_t ctrl,
gnupg_isotime_t protected_at,
unsigned char **result, size_t *resultlen)
{
+ static struct {
+ const char *name; /* Name of the protection method. */
+ int algo; /* (A zero indicates the "openpgp-native" hack.) */
+ int keylen; /* Used key length in bytes. */
+ } algotable[] = {
+ { "openpgp-s2k3-sha1-aes-cbc", GCRY_CIPHER_AES128, (128/8)},
+ { "openpgp-s2k3-sha1-aes256-cbc", GCRY_CIPHER_AES256, (256/8)},
+ { "openpgp-native", 0, 0 }
+ };
int rc;
const unsigned char *s;
const unsigned char *protect_list;
@@ -869,6 +880,7 @@ agent_unprotect (ctrl_t ctrl,
const unsigned char *s2ksalt;
unsigned long s2kcount;
const unsigned char *iv;
+ int prot_cipher, prot_cipher_keylen;
const unsigned char *prot_begin;
unsigned char *cleartext;
unsigned char *final;
@@ -959,31 +971,40 @@ agent_unprotect (ctrl_t ctrl,
n = snext (&s);
if (!n)
return gpg_error (GPG_ERR_INV_SEXP);
- if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
+
+ /* Lookup the protection algo. */
+ prot_cipher = 0; /* (avoid gcc warning) */
+ prot_cipher_keylen = 0; /* (avoid gcc warning) */
+ for (i= 0; i < DIM (algotable); i++)
+ if (smatch (&s, n, algotable[i].name))
+ {
+ prot_cipher = algotable[i].algo;
+ prot_cipher_keylen = algotable[i].keylen;
+ break;
+ }
+ if (i == DIM (algotable))
+ return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
+
+ if (!prot_cipher) /* This is "openpgp-native". */
{
- if (smatch (&s, n, "openpgp-native"))
- {
- gcry_sexp_t s_prot_begin;
+ gcry_sexp_t s_prot_begin;
- rc = gcry_sexp_sscan (&s_prot_begin, NULL,
- prot_begin,
- gcry_sexp_canon_len (prot_begin, 0,NULL,NULL));
- if (rc)
- return rc;
+ rc = gcry_sexp_sscan (&s_prot_begin, NULL,
+ prot_begin,
+ gcry_sexp_canon_len (prot_begin, 0,NULL,NULL));
+ if (rc)
+ return rc;
- rc = convert_from_openpgp_native (ctrl,
- s_prot_begin, passphrase, &final);
- gcry_sexp_release (s_prot_begin);
- if (!rc)
- {
- *result = final;
- *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
- }
- return rc;
+ rc = convert_from_openpgp_native (ctrl, s_prot_begin, passphrase, &final);
+ gcry_sexp_release (s_prot_begin);
+ if (!rc)
+ {
+ *result = final;
+ *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
}
- else
- return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
+ return rc;
}
+
if (*s != '(' || s[1] != '(')
return gpg_error (GPG_ERR_INV_SEXP);
s += 2;
@@ -1026,7 +1047,7 @@ agent_unprotect (ctrl_t ctrl,
s++; /* skip list end */
n = snext (&s);
- if (n != 16) /* Wrong blocksize for IV (we support only aes-128). */
+ if (n != 16) /* Wrong blocksize for IV (we support only 128 bit). */
return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
iv = s;
s += n;
@@ -1040,7 +1061,7 @@ agent_unprotect (ctrl_t ctrl,
cleartext = NULL; /* Avoid cc warning. */
rc = do_decryption (s, n,
passphrase, s2ksalt, s2kcount,
- iv, 16,
+ iv, 16, prot_cipher, prot_cipher_keylen,
&cleartext);
if (rc)
return rc;