1
0
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:
NIIBE Yutaka 2013-02-06 14:01:23 +09:00
parent 30f8a3c873
commit b90506ea22
3 changed files with 108 additions and 132 deletions

View File

@ -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. */

View File

@ -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,

View File

@ -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;
} }