mirror of
git://git.gnupg.org/gnupg.git
synced 2024-11-09 21:28:51 +01:00
gpg: Implement card_store_subkey again.
* g10/call-agent.h (agent_keytocard): New. * g10/call-agent.c (agent_keytocard): New. * g10/card-util.c (replace_existing_key_p): Returns 1 when replace. (card_generate_subkey): Check return value of replace_existing_key_p. (card_store_subkey): Implement again using agent_keytocard.
This commit is contained in:
parent
30f8a3c873
commit
b90506ea22
@ -599,6 +599,30 @@ agent_learn (struct agent_card_info_s *info)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
agent_keytocard (const char *hexgrip, int keyno, int force,
|
||||||
|
const char *serialno, const char *timestamp)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
|
||||||
|
snprintf (line, DIM(line)-1, "KEYTOCARD %s%s %s OPENPGP.%d %s",
|
||||||
|
force?"--force ": "", hexgrip, serialno, keyno, timestamp);
|
||||||
|
line[DIM(line)-1] = 0;
|
||||||
|
|
||||||
|
rc = start_agent (NULL, 1);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* Call the agent to retrieve a data object. This function returns
|
/* Call the agent to retrieve a data object. This function returns
|
||||||
the data in the same structure as used by the learn command. It is
|
the data in the same structure as used by the learn command. It is
|
||||||
allowed to update such a structure using this commmand. */
|
allowed to update such a structure using this commmand. */
|
||||||
|
@ -81,6 +81,10 @@ int agent_learn (struct agent_card_info_s *info);
|
|||||||
/* Update INFO with the attribute NAME. */
|
/* Update INFO with the attribute NAME. */
|
||||||
int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
|
int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
|
||||||
|
|
||||||
|
/* Send the KEYTOCARD command. */
|
||||||
|
int agent_keytocard (const char *hexgrip, int keyno, int force,
|
||||||
|
const char *serialno, const char *timestamp);
|
||||||
|
|
||||||
/* Send a SETATTR command to the SCdaemon. */
|
/* Send a SETATTR command to the SCdaemon. */
|
||||||
int agent_scd_setattr (const char *name,
|
int agent_scd_setattr (const char *name,
|
||||||
const unsigned char *value, size_t valuelen,
|
const unsigned char *value, size_t valuelen,
|
||||||
|
212
g10/card-util.c
212
g10/card-util.c
@ -1264,6 +1264,7 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno)
|
|||||||
if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key",
|
if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key",
|
||||||
_("Replace existing key? (y/N) ")))
|
_("Replace existing key? (y/N) ")))
|
||||||
return -1;
|
return -1;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1484,7 +1485,7 @@ card_generate_subkey (KBNODE pub_keyblock)
|
|||||||
tty_printf(_("Invalid selection.\n"));
|
tty_printf(_("Invalid selection.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (replace_existing_key_p (&info, keyno))
|
if (replace_existing_key_p (&info, keyno) < 0)
|
||||||
{
|
{
|
||||||
err = gpg_error (GPG_ERR_CANCELED);
|
err = gpg_error (GPG_ERR_CANCELED);
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -1531,152 +1532,99 @@ card_generate_subkey (KBNODE pub_keyblock)
|
|||||||
int
|
int
|
||||||
card_store_subkey (KBNODE node, int use)
|
card_store_subkey (KBNODE node, int use)
|
||||||
{
|
{
|
||||||
log_info ("FIXME: card_store_subkey has not yet been implemented\n");
|
struct agent_card_info_s info;
|
||||||
/* struct agent_card_info_s info; */
|
int okay = 0;
|
||||||
/* int okay = 0; */
|
unsigned int nbits;
|
||||||
/* int rc; */
|
int allow_keyno[3];
|
||||||
/* int keyno, i; */
|
int keyno;
|
||||||
/* PKT_secret_key *copied_sk = NULL; */
|
PKT_public_key *pk;
|
||||||
/* PKT_secret_key *sk; */
|
gpg_error_t err;
|
||||||
/* size_t n; */
|
char *hexgrip;
|
||||||
/* const char *s; */
|
int rc;
|
||||||
/* int allow_keyno[3]; */
|
gnupg_isotime_t timebuf;
|
||||||
/* unsigned int nbits; */
|
|
||||||
|
|
||||||
|
assert (node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||||
|
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
|
||||||
|
|
||||||
/* assert (node->pkt->pkttype == PKT_SECRET_KEY */
|
pk = node->pkt->pkt.public_key;
|
||||||
/* || node->pkt->pkttype == PKT_SECRET_SUBKEY); */
|
|
||||||
/* sk = node->pkt->pkt.secret_key; */
|
|
||||||
|
|
||||||
/* if (get_info_for_key_operation (&info)) */
|
if (get_info_for_key_operation (&info))
|
||||||
/* return 0; */
|
return 0;
|
||||||
|
|
||||||
/* if (!info.extcap.ki) */
|
if (!info.extcap.ki)
|
||||||
/* { */
|
{
|
||||||
/* tty_printf ("The card does not support the import of keys\n"); */
|
tty_printf ("The card does not support the import of keys\n");
|
||||||
/* tty_printf ("\n"); */
|
tty_printf ("\n");
|
||||||
/* goto leave; */
|
goto leave;
|
||||||
/* } */
|
}
|
||||||
|
|
||||||
/* show_card_key_info (&info); */
|
nbits = nbits_from_pk (pk);
|
||||||
|
|
||||||
/* nbits = nbits_from_sk (sk); */
|
if (!is_RSA (pk->pubkey_algo) || (!info.is_v2 && nbits != 1024) )
|
||||||
|
{
|
||||||
|
tty_printf ("You may only store a 1024 bit RSA key on the card\n");
|
||||||
|
tty_printf ("\n");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
/* if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) */
|
allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG)));
|
||||||
/* { */
|
allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
|
||||||
/* tty_printf ("You may only store a 1024 bit RSA key on the card\n"); */
|
allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
|
||||||
/* tty_printf ("\n"); */
|
|
||||||
/* goto leave; */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); */
|
tty_printf (_("Please select where to store the key:\n"));
|
||||||
/* allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); */
|
|
||||||
/* allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))); */
|
|
||||||
|
|
||||||
/* tty_printf (_("Please select where to store the key:\n")); */
|
if (allow_keyno[0])
|
||||||
|
tty_printf (_(" (1) Signature key\n"));
|
||||||
|
if (allow_keyno[1])
|
||||||
|
tty_printf (_(" (2) Encryption key\n"));
|
||||||
|
if (allow_keyno[2])
|
||||||
|
tty_printf (_(" (3) Authentication key\n"));
|
||||||
|
|
||||||
/* if (allow_keyno[0]) */
|
for (;;)
|
||||||
/* tty_printf (_(" (1) Signature key\n")); */
|
{
|
||||||
/* if (allow_keyno[1]) */
|
char *answer = cpr_get ("cardedit.genkeys.storekeytype",
|
||||||
/* tty_printf (_(" (2) Encryption key\n")); */
|
_("Your selection? "));
|
||||||
/* if (allow_keyno[2]) */
|
cpr_kill_prompt();
|
||||||
/* tty_printf (_(" (3) Authentication key\n")); */
|
if (*answer == CONTROL_D || !*answer)
|
||||||
|
{
|
||||||
|
xfree (answer);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
keyno = *answer? atoi(answer): 0;
|
||||||
|
xfree(answer);
|
||||||
|
if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1])
|
||||||
|
{
|
||||||
|
if (info.is_v2 && !info.extcap.aac
|
||||||
|
&& info.key_attr[keyno-1].nbits != nbits)
|
||||||
|
{
|
||||||
|
tty_printf ("Key does not match the card's capability.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break; /* Okay. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tty_printf(_("Invalid selection.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
/* for (;;) */
|
if ((rc = replace_existing_key_p (&info, keyno)) < 0)
|
||||||
/* { */
|
goto leave;
|
||||||
/* char *answer = cpr_get ("cardedit.genkeys.storekeytype", */
|
|
||||||
/* _("Your selection? ")); */
|
|
||||||
/* cpr_kill_prompt(); */
|
|
||||||
/* if (*answer == CONTROL_D || !*answer) */
|
|
||||||
/* { */
|
|
||||||
/* xfree (answer); */
|
|
||||||
/* goto leave; */
|
|
||||||
/* } */
|
|
||||||
/* keyno = *answer? atoi(answer): 0; */
|
|
||||||
/* xfree(answer); */
|
|
||||||
/* if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) */
|
|
||||||
/* { */
|
|
||||||
/* if (info.is_v2 && !info.extcap.aac */
|
|
||||||
/* && info.key_attr[keyno-1].nbits != nbits) */
|
|
||||||
/* { */
|
|
||||||
/* tty_printf ("Key does not match the card's capability.\n"); */
|
|
||||||
/* } */
|
|
||||||
/* else */
|
|
||||||
/* break; /\* Okay. *\/ */
|
|
||||||
/* } */
|
|
||||||
/* else */
|
|
||||||
/* tty_printf(_("Invalid selection.\n")); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* if (replace_existing_key_p (&info, keyno)) */
|
err = hexkeygrip_from_pk (pk, &hexgrip);
|
||||||
/* goto leave; */
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
/* /\* Unprotect key. *\/ */
|
epoch2isotime (timebuf, (time_t)pk->timestamp);
|
||||||
/* switch (is_secret_key_protected (sk) ) */
|
agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf);
|
||||||
/* { */
|
|
||||||
/* case 0: /\* Not protected. *\/ */
|
|
||||||
/* break; */
|
|
||||||
/* case -1: */
|
|
||||||
/* log_error (_("unknown key protection algorithm\n")); */
|
|
||||||
/* goto leave; */
|
|
||||||
/* default: */
|
|
||||||
/* if (sk->protect.s2k.mode == 1001) */
|
|
||||||
/* { */
|
|
||||||
/* log_error (_("secret parts of key are not available\n")); */
|
|
||||||
/* goto leave; */
|
|
||||||
/* } */
|
|
||||||
/* if (sk->protect.s2k.mode == 1002) */
|
|
||||||
/* { */
|
|
||||||
/* log_error (_("secret key already stored on a card\n")); */
|
|
||||||
/* goto leave; */
|
|
||||||
/* } */
|
|
||||||
/* /\* We better copy the key before we unprotect it. *\/ */
|
|
||||||
/* copied_sk = sk = copy_secret_key (NULL, sk); */
|
|
||||||
/* rc = 0/\*check_secret_key (sk, 0)*\/; */
|
|
||||||
/* if (rc) */
|
|
||||||
/* goto leave; */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* #warning code save_unprotected_key_to_card */
|
if (rc)
|
||||||
/* /\* rc = save_unprotected_key_to_card (sk, keyno); *\/ */
|
log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
|
||||||
/* /\* if (rc) *\/ */
|
else
|
||||||
/* /\* { *\/ */
|
okay = 1;
|
||||||
/* /\* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); *\/ */
|
xfree (hexgrip);
|
||||||
/* /\* goto leave; *\/ */
|
|
||||||
/* /\* } *\/ */
|
|
||||||
|
|
||||||
/* /\* Get back to the maybe protected original secret key. *\/ */
|
leave:
|
||||||
/* if (copied_sk) */
|
agent_release_card_info (&info);
|
||||||
/* { */
|
return okay;
|
||||||
/* free_secret_key (copied_sk); */
|
|
||||||
/* copied_sk = NULL; */
|
|
||||||
/* } */
|
|
||||||
/* sk = node->pkt->pkt.secret_key; */
|
|
||||||
|
|
||||||
/* /\* Get rid of the secret key parameters and store the serial numer. *\/ */
|
|
||||||
/* n = pubkey_get_nskey (sk->pubkey_algo); */
|
|
||||||
/* for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) */
|
|
||||||
/* { */
|
|
||||||
/* gcry_mpi_release (sk->skey[i]); */
|
|
||||||
/* sk->skey[i] = NULL; */
|
|
||||||
/* } */
|
|
||||||
/* i = pubkey_get_npkey (sk->pubkey_algo); */
|
|
||||||
/* sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); */
|
|
||||||
/* sk->is_protected = 1; */
|
|
||||||
/* sk->protect.s2k.mode = 1002; */
|
|
||||||
/* s = info.serialno; */
|
|
||||||
/* for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; */
|
|
||||||
/* sk->protect.ivlen++, s += 2) */
|
|
||||||
/* sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); */
|
|
||||||
|
|
||||||
/* okay = 1; */
|
|
||||||
|
|
||||||
/* leave: */
|
|
||||||
/* if (copied_sk) */
|
|
||||||
/* free_secret_key (copied_sk); */
|
|
||||||
/* agent_release_card_info (&info); */
|
|
||||||
/* return okay; */
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user