summaryrefslogtreecommitdiffstats
path: root/agent/cvt-openpgp.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2014-09-02 11:22:07 +0200
committerWerner Koch <wk@gnupg.org>2014-09-02 11:22:07 +0200
commitafe85582ddc2ebc285728bf6417f8929fd0b3281 (patch)
tree856a9d8a9f7606742f1db3b8938e7d14df66b86e /agent/cvt-openpgp.c
parentgpg: Fix export of ecc secret keys by adjusting check ordering. (diff)
downloadgnupg2-afe85582ddc2ebc285728bf6417f8929fd0b3281.tar.xz
gnupg2-afe85582ddc2ebc285728bf6417f8929fd0b3281.zip
agent: Fix import of OpenPGP EdDSA keys.
* agent/cvt-openpgp.c (get_keygrip): Special case EdDSA. (convert_secret_key): Ditto. (convert_transfer_key): Ditto. (apply_protection): Handle opaque MPIs. (do_unprotect): Check FLAG_OPAQUE instead of FLAG_USER1 before unpacking an opaque mpi. -- The key transfer protocol between gpg and gpg-agent uses gcrypt algorithm numbers which merge all ECC algorithms into one. Thus it is not possible to use the algorithm number to determine the EdDSA algorithm. We need to known that because Libgcrypt requires the "eddsa" flag with the curve "Ed25519" to actually use the Ed25519 signature specification. The last fix is for correctness; the first case won't be used anyway.
Diffstat (limited to 'agent/cvt-openpgp.c')
-rw-r--r--agent/cvt-openpgp.c84
1 files changed, 66 insertions, 18 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"))