mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-01 16:33:02 +01:00
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:
parent
82cbab906a
commit
980c037bed
118
g10/call-agent.c
118
g10/call-agent.c
@ -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,
|
||||
|
@ -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,
|
||||
|
54
g10/keygen.c
54
g10/keygen.c
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user