[PATCH] agent: Support of ECC key generation by scd
Arnaud Fontaine
arnaud.fontaine at ssi.gouv.fr
Fri Oct 14 14:23:39 CEST 2016
* g10/call-agent.c: Retrieving data sent by scdaemon when an ECC key
has been generated.
* g10/call-agent.h: Change in agent info structure to hold information
related to an ECC key generated by scdaemon.
* g10/keygen.c: Support of ECC key generation by scd
---
g10/call-agent.c | 26 ++++++++++++++++++++++--
g10/call-agent.h | 14 +++++++++++--
g10/keygen.c | 61
+++++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 90 insertions(+), 11 deletions(-)
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 0fb392c..988c763 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -1049,13 +1049,35 @@ scd_genkey_cb (void *opaque, const char *line)
}
else
rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
+
if (rc)
log_error ("error parsing received key data: %s\n",
gpg_strerror (rc));
else if (*name == 'n' && spacep (name+1))
- parm->cgk->n = a;
+ {
+ parm->cgk->algo = PUBKEY_ALGO_RSA;
+ parm->cgk->rsa.n = a;
+ }
else if (*name == 'e' && spacep (name+1))
- parm->cgk->e = a;
+ {
+ parm->cgk->algo = PUBKEY_ALGO_RSA;
+ parm->cgk->rsa.e = a;
+ }
+ else if (*name == 'q' && spacep (name+1))
+ {
+ parm->cgk->algo = PUBKEY_ALGO_ECDSA;
+ parm->cgk->ecc.q = a;
+ }
+ else if (*name == 'c' && spacep (name+1))
+ {
+ parm->cgk->algo = PUBKEY_ALGO_ECDSA;
+ parm->cgk->ecc.curve_oid = a;
+ }
+ else if (*name == 'f' && spacep (name+1))
+ {
+ parm->cgk->algo = PUBKEY_ALGO_ECDH;
+ parm->cgk->ecc.kdf = a;
+ }
else
{
log_info ("unknown parameter name in received key data\n");
diff --git a/g10/call-agent.h b/g10/call-agent.h
index d85a6fd..6440be6 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -72,8 +72,18 @@ struct agent_card_genkey_s {
char fprvalid;
char fpr[20];
u32 created_at;
- gcry_mpi_t n;
- gcry_mpi_t e;
+ int algo;
+ union {
+ struct {
+ gcry_mpi_t n;
+ gcry_mpi_t e;
+ } rsa;
+ struct {
+ gcry_mpi_t curve_oid;
+ gcry_mpi_t kdf; /* if algo is ECDH only */
+ gcry_mpi_t q;
+ } ecc;
+ };
};
diff --git a/g10/keygen.c b/g10/keygen.c
index 9cf314d..0b07677 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -4901,12 +4901,29 @@ gen_card_key (int algo, int keyno, int
is_primary, kbnode_t pub_root,
* rc = agent_scd_genkey (&info, keyno, 1);
* }
*/
- if (!err && (!info.n || !info.e))
+ if (!err && (info.algo == PUBKEY_ALGO_RSA) && (!info.rsa.n ||
!info.rsa.e))
{
log_error ("communication error with SCD\n");
- gcry_mpi_release (info.n);
- gcry_mpi_release (info.e);
- err = gpg_error (GPG_ERR_GENERAL);
+ gcry_mpi_release (info.rsa.n);
+ gcry_mpi_release (info.rsa.e);
+ err = gpg_error (GPG_ERR_GENERAL);
+ }
+ if (!err && (info.algo == PUBKEY_ALGO_ECDSA)
+ && (!info.ecc.curve_oid || !info.ecc.q))
+ {
+ log_error ("communication error with SCD\n");
+ gcry_mpi_release (info.ecc.curve_oid);
+ gcry_mpi_release (info.ecc.q);
+ err = gpg_error (GPG_ERR_GENERAL);
+ }
+ if (!err && (info.algo == PUBKEY_ALGO_ECDH)
+ && (!info.ecc.curve_oid || !info.ecc.kdf || !info.ecc.q))
+ {
+ log_error ("communication error with SCD\n");
+ gcry_mpi_release (info.ecc.curve_oid);
+ gcry_mpi_release (info.ecc.kdf);
+ gcry_mpi_release (info.ecc.q);
+ err = gpg_error (GPG_ERR_GENERAL);
}
if (err)
{
@@ -4937,9 +4954,39 @@ gen_card_key (int algo, int keyno, int
is_primary, kbnode_t pub_root,
pk->version = 4;
if (expireval)
pk->expiredate = pk->timestamp + expireval;
- pk->pubkey_algo = algo;
- pk->pkey[0] = info.n;
- pk->pkey[1] = info.e;
+ pk->pubkey_algo = info.algo;
+ if (info.algo == PUBKEY_ALGO_RSA)
+ {
+ pk->pkey[0] = info.rsa.n;
+ pk->pkey[1] = info.rsa.e;
+ }
+ if (info.algo == PUBKEY_ALGO_ECDH || info.algo == PUBKEY_ALGO_ECDSA)
+ {
+ unsigned char *buf = NULL;
+ size_t buflen = 0;
+
+ err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buf, &buflen,
info.ecc.curve_oid);
+ if (err)
+ {
+ log_error("Failed to convert EC curve OID");
+ return err;
+ }
+ pk->pkey[0] = gcry_mpi_set_opaque_copy (NULL, buf, buflen * 8);
+ pk->pkey[1] = info.ecc.q;
+ xfree (buf);
+
+ if (info.algo == PUBKEY_ALGO_ECDH)
+ {
+ err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buf, &buflen,
info.ecc.kdf);
+ if (err)
+ {
+ log_error("Failed to convert ECDH KDF parameters");
+ return err;
+ }
+ pk->pkey[2] = gcry_mpi_set_opaque_copy (NULL, buf, buflen * 8);
+ xfree (buf);
+ }
+ }
pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
pkt->pkt.public_key = pk;
--
2.9.3
More information about the Gnupg-devel
mailing list