g10: smartcard keygen change.

* g10/call-agent.c (scd_genkey_cb_append_savedbytes): Remove.
(scd_genkey_cb): Only handle KEY-CREATED-AT and PROGRESS.
(agent_scd_genkey): Remove INFO argument.  CREATETIME is now in/out
argument.
(agent_readkey): Use READKEY --card instead of SCD READKEY.
* g10/keygen.c (gen_card_key): Use READKEY --card command of the agent
to retrieve public key information from card and let the agent make
a file for private key with shadow info.
--

This change removes gpg's KEY-DATA handling for SCD GENKEY.  Information
with KEY-DATA is simply not used.  Instead, it is read by READKEY --card
command of gpg-agent.  This can consolidate public key handling in a
single method by READKEY.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2016-10-20 13:30:47 +09:00
parent 82cbab906a
commit 980c037bed
3 changed files with 45 additions and 137 deletions

View File

@ -103,13 +103,6 @@ struct cache_nonce_parm_s
};
struct scd_genkey_parm_s
{
struct agent_card_genkey_s *cgk;
char *savedbytes; /* Malloced space to save key parameter chunks. */
};
static gpg_error_t learn_status_cb (void *opaque, const char *line);
@ -979,133 +972,50 @@ agent_scd_writekey (int keyno, const char *serialno,
static gpg_error_t
scd_genkey_cb_append_savedbytes (struct scd_genkey_parm_s *parm,
const char *line)
{
gpg_error_t err = 0;
char *p;
if (!parm->savedbytes)
{
parm->savedbytes = xtrystrdup (line);
if (!parm->savedbytes)
err = gpg_error_from_syserror ();
}
else
{
p = xtrymalloc (strlen (parm->savedbytes) + strlen (line) + 1);
if (!p)
err = gpg_error_from_syserror ();
else
{
strcpy (stpcpy (p, parm->savedbytes), line);
xfree (parm->savedbytes);
parm->savedbytes = p;
}
}
return err;
}
/* Status callback for the SCD GENKEY command. */
static gpg_error_t
scd_genkey_cb (void *opaque, const char *line)
{
struct scd_genkey_parm_s *parm = opaque;
u32 *createtime = opaque;
const char *keyword = line;
int keywordlen;
gpg_error_t rc = 0;
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
;
while (spacep (line))
line++;
if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
{
parm->cgk->fprvalid = unhexify_fpr (line, parm->cgk->fpr);
}
else if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
{
gcry_mpi_t a;
const char *name = line;
while (*line && !spacep (line))
line++;
while (spacep (line))
line++;
if (*name == '-' && spacep (name+1))
rc = scd_genkey_cb_append_savedbytes (parm, line);
else
{
if (parm->savedbytes)
{
rc = scd_genkey_cb_append_savedbytes (parm, line);
if (!rc)
rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX,
parm->savedbytes, 0, NULL);
}
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;
else if (*name == 'e' && spacep (name+1))
parm->cgk->e = a;
else
{
log_info ("unknown parameter name in received key data\n");
gcry_mpi_release (a);
rc = gpg_error (GPG_ERR_INV_PARAMETER);
}
xfree (parm->savedbytes);
parm->savedbytes = NULL;
}
}
else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
{
parm->cgk->created_at = (u32)strtoul (line, NULL, 10);
*createtime = (u32)strtoul (line, NULL, 10);
}
else if (keywordlen == 8 && !memcmp (keyword, "PROGRESS", keywordlen))
{
write_status_text (STATUS_PROGRESS, line);
}
return rc;
return 0;
}
/* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
this implementation. If CREATEDATE is not 0, it will be passed to
SCDAEMON so that the key is created with this timestamp. INFO will
receive information about the generated key. */
/* Send a GENKEY command to the SCdaemon. If CREATETIME is not 0, it
will be passed to SCDAEMON so that the key is created with this
timestamp. On success, creation time is stored back to CREATETIME. */
int
agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
const char *serialno, u32 createtime)
agent_scd_genkey (int keyno, int force, u32 *createtime)
{
int rc;
char line[ASSUAN_LINELENGTH];
gnupg_isotime_t tbuf;
struct scd_genkey_parm_s parms;
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
(void)serialno;
memset (&parms, 0, sizeof parms);
parms.cgk = info;
rc = start_agent (NULL, 1);
if (rc)
return rc;
if (createtime)
epoch2isotime (tbuf, createtime);
if (*createtime)
epoch2isotime (tbuf, *createtime);
else
*tbuf = 0;
@ -1116,12 +1026,9 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
line[DIM(line)-1] = 0;
dfltparm.ctx = agent_ctx;
memset (info, 0, sizeof *info);
rc = assuan_transact (agent_ctx, line,
NULL, NULL, default_inq_cb, &dfltparm,
scd_genkey_cb, &parms);
xfree (parms.savedbytes);
scd_genkey_cb, createtime);
status_sc_op_failure (rc);
return rc;
@ -1854,7 +1761,8 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
if (err)
return err;
snprintf (line, DIM(line)-1, "%sREADKEY %s", fromcard? "SCD ":"", hexkeygrip);
snprintf (line, DIM(line)-1, "READKEY %s%s", fromcard? "--card ":"",
hexkeygrip);
init_membuf (&data, 1024);
err = assuan_transact (agent_ctx, line,

View File

@ -68,13 +68,6 @@ struct agent_card_info_s
unsigned int status_indicator;
};
struct agent_card_genkey_s {
char fprvalid;
char fpr[20];
u32 created_at;
gcry_mpi_t n;
gcry_mpi_t e;
};
/* Release the card info structure. */
@ -107,8 +100,7 @@ int agent_scd_writekey (int keyno, const char *serialno,
const unsigned char *keydata, size_t keydatalen);
/* Send a GENKEY command to the SCdaemon. */
int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
const char *serialno, u32 createtime);
int agent_scd_genkey (int keyno, int force, u32 *createtime);
/* Send a READKEY command to the SCdaemon. */
int agent_scd_readcert (const char *certidstr,

View File

@ -4870,9 +4870,14 @@ gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
{
#ifdef ENABLE_CARD_SUPPORT
gpg_error_t err;
struct agent_card_genkey_s info;
PACKET *pkt;
PKT_public_key *pk;
char keyid[10];
unsigned char *public;
gcry_sexp_t s_key;
snprintf (keyid, DIM(keyid)-1, "OPENPGP.%d", keyno);
keyid[DIM(keyid)-1] = 0;
if (algo != PUBKEY_ALGO_RSA)
return gpg_error (GPG_ERR_PUBKEY_ALGO);
@ -4888,7 +4893,7 @@ gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
}
/* Note: SCD knows the serialnumber, thus there is no point in passing it. */
err = agent_scd_genkey (&info, keyno, 1, NULL, *timestamp);
err = agent_scd_genkey (keyno, 1, timestamp);
/* The code below is not used because we force creation of
* the a card key (3rd arg).
* if (gpg_err_code (rc) == GPG_ERR_EEXIST)
@ -4898,16 +4903,9 @@ gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
* tty_printf ("\n");
* if ( cpr_get_answer_is_yes( "keygen.card.replace_key",
* _("Replace existing key? ")))
* rc = agent_scd_genkey (&info, keyno, 1);
* rc = agent_scd_genkey (keyno, 1, timestamp);
* }
*/
if (!err && (!info.n || !info.e))
{
log_error ("communication error with SCD\n");
gcry_mpi_release (info.n);
gcry_mpi_release (info.e);
err = gpg_error (GPG_ERR_GENERAL);
}
if (err)
{
log_error ("key generation failed: %s\n", gpg_strerror (err));
@ -4916,30 +4914,40 @@ gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
return err;
}
/* Send the learn command so that the agent creates a shadow key for
/* Send the READKEY command so that the agent creates a shadow key for
card key. We need to do that now so that we are able to create
the self-signatures. */
err = agent_scd_learn (NULL, 0);
err = agent_readkey (NULL, 1, keyid, &public);
if (err)
return err;
err = gcry_sexp_sscan (&s_key, NULL, public,
gcry_sexp_canon_len (public, 0, NULL, NULL));
xfree (public);
if (err)
return err;
if (algo == PUBKEY_ALGO_RSA)
err = key_from_sexp (pk->pkey, s_key, "public-key", "ne");
else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA
|| algo == PUBKEY_ALGO_ECDH )
err = ecckey_from_sexp (pk->pkey, s_key, algo);
else
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
gcry_sexp_release (s_key);
if (err)
{
/* Oops: Card removed during generation. */
log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (err));
xfree (pkt);
xfree (pk);
log_error ("key_from_sexp failed: %s\n", gpg_strerror (err) );
free_public_key (pk);
return err;
}
if (*timestamp != info.created_at)
log_info ("NOTE: the key does not use the suggested creation date\n");
*timestamp = info.created_at;
pk->timestamp = info.created_at;
pk->timestamp = *timestamp;
pk->version = 4;
if (expireval)
pk->expiredate = pk->timestamp + expireval;
pk->pubkey_algo = algo;
pk->pkey[0] = info.n;
pk->pkey[1] = info.e;
pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
pkt->pkt.public_key = pk;