aboutsummaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
Diffstat (limited to 'agent')
-rw-r--r--agent/cvt-openpgp.c84
-rw-r--r--agent/protect.c79
2 files changed, 116 insertions, 47 deletions
diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c
index 58327c668..6ea266628 100644
--- a/agent/cvt-openpgp.c
+++ b/agent/cvt-openpgp.c
@@ -81,9 +81,16 @@ get_keygrip (int pubkey_algo, const char *curve, gcry_mpi_t *pkey,
break;
case GCRY_PK_ECC:
- err = gcry_sexp_build (&s_pkey, NULL,
- "(public-key(ecc(curve %s)(q%m)))",
- curve, pkey[0]);
+ if (!curve)
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
+ err = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(ecc(curve %s)(flags eddsa)(q%m)))",
+ "Ed25519", pkey[0]);
+ else
+ err = gcry_sexp_build (&s_pkey, NULL,
+ "(public-key(ecc(curve %s)(q%m)))",
+ curve, pkey[0]);
break;
default:
@@ -139,6 +146,15 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
case GCRY_PK_ECC:
if (!curve)
err = gpg_error (GPG_ERR_BAD_SECKEY);
+ else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
+ {
+ /* Do not store the OID as name but the real name and the
+ EdDSA flag. */
+ err = gcry_sexp_build (&s_skey, NULL,
+ "(private-key(ecc(curve%s)(flags eddsa)"
+ "(q%m)(d%m)))",
+ "Ed25519", skey[0], skey[1]);
+ }
else
err = gcry_sexp_build (&s_skey, NULL,
"(private-key(ecc(curve%s)(q%m)(d%m)))",
@@ -198,11 +214,24 @@ convert_transfer_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
break;
case GCRY_PK_ECC:
- err = gcry_sexp_build
- (&s_skey, NULL,
- "(protected-private-key(ecc(curve%s)(q%m)"
- "(protected openpgp-native%S)))",
- curve, skey[0], transfer_key);
+ if (!curve)
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
+ {
+ /* Do not store the OID as name but the real name and the
+ EdDSA flag. */
+ err = gcry_sexp_build
+ (&s_skey, NULL,
+ "(protected-private-key(ecc(curve%s)(flags eddsa)(q%m)"
+ "(protected openpgp-native%S)))",
+ "Ed25519", skey[0], transfer_key);
+ }
+ else
+ err = gcry_sexp_build
+ (&s_skey, NULL,
+ "(protected-private-key(ecc(curve%s)(q%m)"
+ "(protected openpgp-native%S)))",
+ curve, skey[0], transfer_key);
break;
default:
@@ -373,7 +402,7 @@ do_unprotect (const char *passphrase,
if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
return gpg_error (GPG_ERR_BAD_SECKEY);
- if (gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
+ if (gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
{
unsigned int nbits;
const unsigned char *buffer;
@@ -1064,15 +1093,36 @@ apply_protection (gcry_mpi_t *array, int npkey, int nskey,
ndata = 20; /* Space for the SHA-1 checksum. */
for (i = npkey, j = 0; i < nskey; i++, j++ )
{
- err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j, narr+j, array[i]);
- if (err)
+ if (gcry_mpi_get_flag (array[i], GCRYMPI_FLAG_OPAQUE))
{
- err = gpg_error_from_syserror ();
- for (i = 0; i < j; i++)
- xfree (bufarr[i]);
- return err;
+ const void *s;
+ unsigned int n;
+
+ s = gcry_mpi_get_opaque (array[i], &n);
+ nbits[j] = n;
+ n = (n+7)/8;
+ narr[j] = n;
+ bufarr[j] = gcry_is_secure (s)? xtrymalloc_secure (n):xtrymalloc (n);
+ if (!bufarr[j])
+ {
+ err = gpg_error_from_syserror ();
+ for (i = 0; i < j; i++)
+ xfree (bufarr[i]);
+ return err;
+ }
+ memcpy (bufarr[j], s, n);
+ }
+ else
+ {
+ err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j, narr+j, array[i]);
+ if (err)
+ {
+ for (i = 0; i < j; i++)
+ xfree (bufarr[i]);
+ return err;
+ }
+ nbits[j] = gcry_mpi_get_nbits (array[i]);
}
- nbits[j] = gcry_mpi_get_nbits (array[i]);
ndata += 2 + narr[j];
}
@@ -1218,8 +1268,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
assert (iob.len < sizeof iobbuf -1);
iobbuf[iob.len] = 0;
err = gcry_sexp_build (&curve, NULL, "(curve %s)", iobbuf);
-
- gcry_log_debugsxp ("at 1", curve);
}
}
else if (!strcmp (name, "ecdsa"))
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;