1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-05-24 16:43:28 +02:00

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.
This commit is contained in:
Werner Koch 2014-09-02 11:22:07 +02:00
parent 4054d86abc
commit afe85582dd

View File

@ -81,9 +81,16 @@ get_keygrip (int pubkey_algo, const char *curve, gcry_mpi_t *pkey,
break; break;
case GCRY_PK_ECC: case GCRY_PK_ECC:
err = gcry_sexp_build (&s_pkey, NULL, if (!curve)
"(public-key(ecc(curve %s)(q%m)))", err = gpg_error (GPG_ERR_BAD_SECKEY);
curve, pkey[0]); 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; break;
default: default:
@ -139,6 +146,15 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
case GCRY_PK_ECC: case GCRY_PK_ECC:
if (!curve) if (!curve)
err = gpg_error (GPG_ERR_BAD_SECKEY); 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 else
err = gcry_sexp_build (&s_skey, NULL, err = gcry_sexp_build (&s_skey, NULL,
"(private-key(ecc(curve%s)(q%m)(d%m)))", "(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; break;
case GCRY_PK_ECC: case GCRY_PK_ECC:
err = gcry_sexp_build if (!curve)
(&s_skey, NULL, err = gpg_error (GPG_ERR_BAD_SECKEY);
"(protected-private-key(ecc(curve%s)(q%m)" else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
"(protected openpgp-native%S)))", {
curve, skey[0], transfer_key); /* 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; break;
default: default:
@ -373,7 +402,7 @@ do_unprotect (const char *passphrase,
if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1)) if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
return gpg_error (GPG_ERR_BAD_SECKEY); 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; unsigned int nbits;
const unsigned char *buffer; 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. */ ndata = 20; /* Space for the SHA-1 checksum. */
for (i = npkey, j = 0; i < nskey; i++, j++ ) for (i = npkey, j = 0; i < nskey; i++, j++ )
{ {
err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j, narr+j, array[i]); if (gcry_mpi_get_flag (array[i], GCRYMPI_FLAG_OPAQUE))
if (err)
{ {
err = gpg_error_from_syserror (); const void *s;
for (i = 0; i < j; i++) unsigned int n;
xfree (bufarr[i]);
return err; 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]; 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); assert (iob.len < sizeof iobbuf -1);
iobbuf[iob.len] = 0; iobbuf[iob.len] = 0;
err = gcry_sexp_build (&curve, NULL, "(curve %s)", iobbuf); err = gcry_sexp_build (&curve, NULL, "(curve %s)", iobbuf);
gcry_log_debugsxp ("at 1", curve);
} }
} }
else if (!strcmp (name, "ecdsa")) else if (!strcmp (name, "ecdsa"))