aboutsummaryrefslogtreecommitdiffstats
path: root/g10/card-util.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/card-util.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/g10/card-util.c b/g10/card-util.c
index 597faba6d..194bd83e2 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -828,6 +828,120 @@ generate_card_keys (const char *serialno)
}
}
+
+/* This fucntion is used by the key edit menu to generate an arbitrary
+ subkey. */
+int
+card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
+{
+ struct agent_card_info_s info;
+ int okay = 0;
+ int forced_chv1 = 0;
+ int rc;
+ int keyno;
+
+ memset (&info, 0, sizeof info);
+ rc = agent_scd_getattr ("SERIALNO", &info);
+ if (rc || !info.serialno || strncmp (info.serialno, "D27600012401", 12)
+ || strlen (info.serialno) != 32 )
+ {
+ log_error (_("cannot generate key: %s\n"),
+ rc ? gpg_strerror (rc) : _("not an OpenPGP card"));
+ goto leave;
+ }
+ rc = agent_scd_getattr ("KEY-FPR", &info);
+ if (!rc)
+ rc = agent_scd_getattr ("CHV-STATUS", &info);
+ if (rc)
+ {
+ log_error ("error getting current key info: %s\n", gpg_strerror (rc));
+ goto leave;
+ }
+
+ tty_fprintf (NULL, "Signature key ....:");
+ print_sha1_fpr (NULL, info.fpr1valid? info.fpr1:NULL);
+ tty_fprintf (NULL, "Encryption key....:");
+ print_sha1_fpr (NULL, info.fpr2valid? info.fpr2:NULL);
+ tty_fprintf (NULL, "Authentication key:");
+ print_sha1_fpr (NULL, info.fpr3valid? info.fpr3:NULL);
+ tty_printf ("\n");
+
+ tty_printf (_("Please select the type of key to generate:\n"));
+
+ tty_printf (_(" (1) Signature key\n"));
+ tty_printf (_(" (2) Encryption key\n"));
+ tty_printf (_(" (3) Authentication key\n"));
+
+ for (;;)
+ {
+ char *answer = cpr_get ("cardedit.genkeys.subkeytype",
+ _("Your selection? "));
+ cpr_kill_prompt();
+ if (*answer == CONTROL_D)
+ {
+ xfree (answer);
+ goto leave;
+ }
+ keyno = *answer? atoi(answer): 0;
+ xfree(answer);
+ if (keyno >= 1 && keyno <= 3)
+ break; /* Okay. */
+ tty_printf(_("Invalid selection.\n"));
+ }
+
+ if ((keyno == 1 && info.fpr1valid)
+ || (keyno == 2 && info.fpr2valid)
+ || (keyno == 3 && info.fpr3valid))
+ {
+ tty_printf ("\n");
+ log_info ("WARNING: such a key has already been stored on the card!\n");
+ tty_printf ("\n");
+ if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key",
+ _("Replace existing key? ")))
+ goto leave;
+ }
+
+ forced_chv1 = !info.chv1_cached;
+ if (forced_chv1)
+ { /* Switch of the forced mode so that during key generation we
+ don't get bothered with PIN queries for each
+ self-signature. */
+ rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1);
+ if (rc)
+ {
+ log_error ("error clearing forced signature PIN flag: %s\n",
+ gpg_strerror (rc));
+ forced_chv1 = 0;
+ goto leave;
+ }
+ }
+
+ /* Check the PIN now, so that we won't get asked later for each
+ binding signature. */
+ rc = agent_scd_checkpin (info.serialno);
+ if (rc)
+ log_error ("error checking the PIN: %s\n", gpg_strerror (rc));
+ else
+ okay = generate_card_subkeypair (pub_keyblock, sec_keyblock,
+ keyno, info.serialno);
+
+ leave:
+ agent_release_card_info (&info);
+ if (forced_chv1)
+ { /* Switch back to forced state. */
+ rc = agent_scd_setattr ("CHV-STATUS-1", "", 1);
+ if (rc)
+ {
+ log_error ("error setting forced signature PIN flag: %s\n",
+ gpg_strerror (rc));
+ return okay;
+ }
+ }
+ return okay;
+}
+
+
+
/* Menu to edit all user changeable values on an OpenPGP card. Only
Key creation is not handled here. */
void