aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2004-09-20 18:38:39 +0000
committerWerner Koch <[email protected]>2004-09-20 18:38:39 +0000
commit9d17a635c977a209bee78203e3cfb85a9cb09fc6 (patch)
tree9fdd7a23c8193693c305a5f1716f02b170fc2899
parent* cardglue.c (open_card): Use shutdown code if possible. (diff)
downloadgnupg-9d17a635c977a209bee78203e3cfb85a9cb09fc6.tar.gz
gnupg-9d17a635c977a209bee78203e3cfb85a9cb09fc6.zip
* gpg.sgml: Document -K.
* g10.c: Make -K an alias for --list-secret-keys. * keylist.c (print_card_serialno): New. Taken from gnupg 1.9.11. (list_keyblock_print): Make use of it. * keyedit.c (show_key_with_all_names): Print the card S/N. * keyedit.c (keyedit_menu): New command ADDCARDKEY. * card-util.c (card_generate_subkey): New. * keygen.c (generate_card_subkeypair): New. (gen_card_key): New arg IS_PRIMARY; changed all callers. * cardglue.c (open_card): Use shutdown code if possible. (check_card_serialno): Ditto.
Diffstat (limited to '')
-rw-r--r--NEWS8
-rw-r--r--TODO6
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/gpg.sgml7
-rw-r--r--g10/ChangeLog11
-rw-r--r--g10/card-util.c114
-rw-r--r--g10/cardglue.c4
-rw-r--r--g10/g10.c2
-rw-r--r--g10/keyedit.c35
-rw-r--r--g10/keygen.c130
-rw-r--r--g10/keylist.c44
-rw-r--r--g10/main.h5
12 files changed, 356 insertions, 14 deletions
diff --git a/NEWS b/NEWS
index db07c2469..da633dbe2 100644
--- a/NEWS
+++ b/NEWS
@@ -7,7 +7,13 @@ Noteworthy changes in version 1.3.7
* Support for the OpenPGP smartcard is now enabled by default.
Use the option --disable-card-support to build without support
- for smartcards.
+ for smartcards.
+
+ * New command "addcardkey" in the key edit menu to add subkeys to
+ a smartcard. The serial number of the card is show in secret
+ key listings.
+
+ * -K may now be used as an alias for --list-secret-keys.
* HTTP Basic authentication is now supported for all HKP and HTTP
keyserver functions, either through a proxy or via direct
diff --git a/TODO b/TODO
index d51ce1b84..486926232 100644
--- a/TODO
+++ b/TODO
@@ -113,6 +113,12 @@
* Add the NEWSIG status.
+ * When generating a key onh the card we should try to also set the
+ display name or provide the display name as a default in the key
+ generation. The problem however is that the display name must be
+ given with an indication of the surname and the usable characters
+ are also restricted.
+
Things we won't do
------------------
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 47332c320..deb9a7730 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2004-09-20 Werner Koch <[email protected]>
+
+ * gpg.sgml: Document -K.
+
2004-09-16 David Shaw <[email protected]>
* DETAILS: Document the 'spk' signature subpacket record. Add
diff --git a/doc/gpg.sgml b/doc/gpg.sgml
index f74bd43e0..f5bb0695f 100644
--- a/doc/gpg.sgml
+++ b/doc/gpg.sgml
@@ -252,7 +252,7 @@ scripts and other programs.
<varlistentry>
-<term>--list-secret-keys &OptParmNames;</term>
+<term>-K, --list-secret-keys &OptParmNames;</term>
<listitem><para>
List all keys from the secret keyrings, or just the ones given on the
command line. A '#' after the letters 'sec' means that the secret key
@@ -410,6 +410,11 @@ Revoke a user id.</para></listitem></varlistentry>
<listitem><para>
Add a subkey to this key.</para></listitem></varlistentry>
<varlistentry>
+ <term>addcardkey</term>
+ <listitem><para>
+Generate a key on a card and add it
+to this key.</para></listitem></varlistentry>
+ <varlistentry>
<term>delkey</term>
<listitem><para>
Remove a subkey.</para></listitem></varlistentry>
diff --git a/g10/ChangeLog b/g10/ChangeLog
index b4871247d..0b8837316 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,5 +1,16 @@
2004-09-20 Werner Koch <[email protected]>
+ * g10.c: Make -K an alias for --list-secret-keys.
+
+ * keylist.c (print_card_serialno): New. Taken from gnupg 1.9.11.
+ (list_keyblock_print): Make use of it.
+ * keyedit.c (show_key_with_all_names): Print the card S/N.
+
+ * keyedit.c (keyedit_menu): New command ADDCARDKEY.
+ * card-util.c (card_generate_subkey): New.
+ * keygen.c (generate_card_subkeypair): New.
+ (gen_card_key): New arg IS_PRIMARY; changed all callers.
+
* cardglue.c (open_card): Use shutdown code if possible.
(check_card_serialno): Ditto.
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
diff --git a/g10/cardglue.c b/g10/cardglue.c
index 5faa41bad..cff025cb3 100644
--- a/g10/cardglue.c
+++ b/g10/cardglue.c
@@ -812,8 +812,8 @@ agent_scd_change_pin (int chvno)
pin_cb, NULL);
}
-/* Perform a CHECKPIN operation. SERIALNO should be the seriial
- number of the card - optioanlly followed by the fingerprint;
+/* Perform a CHECKPIN operation. SERIALNO should be the serial
+ number of the card - optionally followed by the fingerprint;
however the fingerprint is ignored here. */
int
agent_scd_checkpin (const char *serialnobuf)
diff --git a/g10/g10.c b/g10/g10.c
index 3fd6c9aad..66692f79e 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -80,6 +80,7 @@ enum cmd_and_opt_values
oVerbose = 'v',
oCompress = 'z',
oSetNotation = 'N',
+ aListSecretKeys = 'K',
oBatch = 500,
oMaxOutput,
oSigNotation,
@@ -114,7 +115,6 @@ enum cmd_and_opt_values
aVerifyFiles,
aListKeys,
aListSigs,
- aListSecretKeys,
aSendKeys,
aRecvKeys,
aSearchKeys,
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 288d8ba1c..014f3a8c0 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -1191,6 +1191,7 @@ keyedit_menu( const char *username, STRLIST locusr,
cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF,
cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST,
+ cmdADDCARDKEY,
cmdNOP };
static struct { const char *name;
enum cmdids id;
@@ -1223,6 +1224,7 @@ keyedit_menu( const char *username, STRLIST locusr,
/* delphoto is really deluid in disguise */
{ N_("delphoto"), cmdDELUID , 0,1, NULL },
{ N_("addkey") , cmdADDKEY , 1,1, N_("add a secondary key") },
+ { N_("addcardkey"), cmdADDCARDKEY , 1,1, N_("add a key to a smartcard") },
{ N_("delkey") , cmdDELKEY , 0,1, N_("delete a secondary key") },
{ N_("addrevoker"),cmdADDREVOKER,1,1, N_("add a revocation key") },
{ N_("delsig") , cmdDELSIG , 0,1, N_("delete signatures") },
@@ -1530,6 +1532,16 @@ keyedit_menu( const char *username, STRLIST locusr,
}
break;
+#ifdef ENABLE_CARD_SUPPORT
+ case cmdADDCARDKEY:
+ if (card_generate_subkey (keyblock, sec_keyblock)) {
+ redisplay = 1;
+ sec_modified = modified = 1;
+ merge_keys_and_selfsig( sec_keyblock );
+ merge_keys_and_selfsig( keyblock );
+ }
+ break;
+#endif /* ENABLE_CARD_SUPPORT */
case cmdDELKEY: {
int n1;
@@ -2210,6 +2222,27 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
tty_printf(" ");
tty_printf(_("expires: %s"),expirestr_from_sk(sk));
tty_printf("\n");
+ if (sk->is_protected && sk->protect.s2k.mode == 1002)
+ {
+ tty_printf(" ");
+ tty_printf(_("card-no: "));
+ if (sk->protect.ivlen == 16
+ && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6))
+ { /* This is an OpenPGP card. */
+ for (i=8; i < 14; i++)
+ {
+ if (i == 10)
+ tty_printf (" ");
+ tty_printf ("%02X", sk->protect.iv[i]);
+ }
+ }
+ else
+ { /* Something is wrong: Print all. */
+ for (i=0; i < sk->protect.ivlen; i++)
+ tty_printf ("%02X", sk->protect.iv[i]);
+ }
+ tty_printf ("\n");
+ }
}
else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE
&& node->pkt->pkt.signature->sig_class == 0x28 ) {
@@ -2555,7 +2588,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
/****************
- * Remove all selceted userids from the keyrings
+ * Remove all selected userids from the keyrings
*/
static void
menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
diff --git a/g10/keygen.c b/g10/keygen.c
index 6bf1c0cbd..44cfc00ec 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -117,7 +117,8 @@ static int mdc_available,ks_modify;
static void do_generate_keypair( struct para_data_s *para,
struct output_control_s *outctrl, int card );
static int write_keyblock( IOBUF out, KBNODE node );
-static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
+static int gen_card_key (int algo, int keyno, int is_primary,
+ KBNODE pub_root, KBNODE sec_root,
u32 expireval, struct para_data_s *para);
static void
@@ -2481,7 +2482,7 @@ do_generate_keypair( struct para_data_s *para,
}
else
{
- rc = gen_card_key (PUBKEY_ALGO_RSA, 1, pub_root, sec_root,
+ rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root,
get_parameter_u32 (para, pKEYEXPIRE), para);
if (!rc)
{
@@ -2523,7 +2524,7 @@ do_generate_keypair( struct para_data_s *para,
}
else
{
- rc = gen_card_key (PUBKEY_ALGO_RSA, 2, pub_root, sec_root,
+ rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root,
get_parameter_u32 (para, pKEYEXPIRE), para);
}
@@ -2538,7 +2539,7 @@ do_generate_keypair( struct para_data_s *para,
if (card && get_parameter (para, pAUTHKEYTYPE))
{
- rc = gen_card_key (PUBKEY_ALGO_RSA, 3, pub_root, sec_root,
+ rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root,
get_parameter_u32 (para, pKEYEXPIRE), para);
if (!rc)
@@ -2768,6 +2769,120 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
return okay;
}
+
+#ifdef ENABLE_CARD_SUPPORT
+/* Generate a subkey on a card. */
+int
+generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
+ int keyno, const char *serialno)
+{
+ int okay=0, rc=0;
+ KBNODE node;
+ PKT_secret_key *pri_sk = NULL;
+ int algo;
+ unsigned int use;
+ u32 expire;
+ char *passphrase = NULL;
+ u32 cur_time;
+ struct para_data_s *para = NULL;
+
+ assert (keyno >= 1 && keyno <= 3);
+
+ para = xcalloc (1, sizeof *para + strlen (serialno) );
+ para->key = pSERIALNO;
+ strcpy (para->u.value, serialno);
+
+ /* Break out the primary secret key */
+ node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
+ if(!node)
+ {
+ log_error("Oops; secret key not found anymore!\n");
+ goto leave;
+ }
+
+ /* Make a copy of the sk to keep the protected one in the keyblock */
+ pri_sk = copy_secret_key (NULL, node->pkt->pkt.secret_key);
+
+ cur_time = make_timestamp();
+ if (pri_sk->timestamp > cur_time)
+ {
+ ulong d = pri_sk->timestamp - cur_time;
+ log_info (d==1 ? _("key has been created %lu second "
+ "in future (time warp or clock problem)\n")
+ : _("key has been created %lu seconds "
+ "in future (time warp or clock problem)\n"), d );
+ if (!opt.ignore_time_conflict)
+ {
+ rc = G10ERR_TIME_CONFLICT;
+ goto leave;
+ }
+ }
+
+ if (pri_sk->version < 4)
+ {
+ log_info (_("NOTE: creating subkeys for v3 keys "
+ "is not OpenPGP compliant\n"));
+ goto leave;
+ }
+
+ /* Unprotect to get the passphrase. */
+ switch( is_secret_key_protected (pri_sk) )
+ {
+ case -1:
+ rc = G10ERR_PUBKEY_ALGO;
+ break;
+ case 0:
+ tty_printf("This key is not protected.\n");
+ break;
+ default:
+ tty_printf("Key is protected.\n");
+ rc = check_secret_key( pri_sk, 0 );
+ if (!rc)
+ passphrase = get_last_passphrase();
+ break;
+ }
+ if (rc)
+ goto leave;
+
+ algo = PUBKEY_ALGO_RSA;
+ expire = ask_expire_interval (0);
+ if (keyno == 1)
+ use = PUBKEY_USAGE_SIG;
+ else if (keyno == 2)
+ use = PUBKEY_USAGE_ENC;
+ else
+ use = PUBKEY_USAGE_AUTH;
+ if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.cardsub.okay",
+ _("Really create? ") ) )
+ goto leave;
+
+ if (passphrase)
+ set_next_passphrase (passphrase);
+ rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock, expire, para);
+ if (!rc)
+ rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, NULL, use);
+ if (!rc)
+ rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, NULL, use);
+ if (!rc)
+ {
+ okay = 1;
+ write_status_text (STATUS_KEY_CREATED, "S");
+ }
+
+ leave:
+ if (rc)
+ log_error (_("Key generation failed: %s\n"), g10_errstr(rc) );
+ m_free (passphrase);
+ /* Release the copy of the (now unprotected) secret keys. */
+ if (pri_sk)
+ free_secret_key (pri_sk);
+ set_next_passphrase( NULL );
+ release_parameter_list (para);
+ return okay;
+}
+#endif /* !ENABLE_CARD_SUPPORT */
+
+
/****************
* Write a keyblock to an output stream
*/
@@ -2787,7 +2902,8 @@ write_keyblock( IOBUF out, KBNODE node )
static int
-gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
+gen_card_key (int algo, int keyno, int is_primary,
+ KBNODE pub_root, KBNODE sec_root,
u32 expireval, struct para_data_s *para)
{
#ifdef ENABLE_CARD_SUPPORT
@@ -2848,12 +2964,12 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
}
pkt = xcalloc (1,sizeof *pkt);
- pkt->pkttype = keyno == 1 ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
+ pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
pkt->pkt.public_key = pk;
add_kbnode(pub_root, new_kbnode( pkt ));
pkt = xcalloc (1,sizeof *pkt);
- pkt->pkttype = keyno == 1 ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY;
+ pkt->pkttype = is_primary ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY;
pkt->pkt.secret_key = sk;
add_kbnode(sec_root, new_kbnode( pkt ));
diff --git a/g10/keylist.c b/g10/keylist.c
index ce66a1359..cb38026e6 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -41,6 +41,7 @@
static void list_all(int);
static void list_one( STRLIST names, int secret);
+static void print_card_serialno (PKT_secret_key *sk);
struct sig_stats
{
@@ -752,6 +753,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
if( !any ) {
if( fpr )
print_fingerprint( pk, sk, 0 );
+ print_card_serialno (sk);
if( opt.with_key_data )
print_key_data( pk );
any = 1;
@@ -805,6 +807,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
putchar('\n');
if( fpr )
print_fingerprint( pk, sk, 0 ); /* of the main key */
+ print_card_serialno (sk);
any = 1;
}
@@ -817,7 +820,10 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
printf(_(" [expires: %s]"), expirestr_from_sk( sk2 ) );
putchar('\n');
if( fpr > 1 )
- print_fingerprint( NULL, sk2, 0 );
+ {
+ print_fingerprint( NULL, sk2, 0 );
+ print_card_serialno (sk2);
+ }
}
else if( opt.list_sigs
&& node->pkt->pkttype == PKT_SIGNATURE
@@ -861,6 +867,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
putchar('\n');
if( fpr )
print_fingerprint( pk, sk, 0 );
+ print_card_serialno (sk);
any=1;
}
@@ -1475,6 +1482,41 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
tty_printf ("\n");
}
+/* Print the serial number of an OpenPGP card if available. */
+static void
+print_card_serialno (PKT_secret_key *sk)
+{
+ int i;
+
+ if (!sk)
+ return;
+ if (!sk->is_protected || sk->protect.s2k.mode != 1002)
+ return; /* Not a card. */
+ if (opt.with_colons)
+ return; /* Handled elesewhere. */
+
+ fputs (_(" Card serial no. ="), stdout);
+ putchar (' ');
+ if (sk->protect.ivlen == 16
+ && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) )
+ { /* This is an OpenPGP card. Just print the relevant part. */
+ for (i=8; i < 14; i++)
+ {
+ if (i == 10)
+ putchar (' ');
+ printf ("%02X", sk->protect.iv[i]);
+ }
+ }
+ else
+ { /* Something is wrong: Print all. */
+ for (i=0; i < sk->protect.ivlen; i++)
+ printf ("%02X", sk->protect.iv[i]);
+ }
+ putchar ('\n');
+}
+
+
+
void set_attrib_fd(int fd)
{
static int last_fd=-1;
diff --git a/g10/main.h b/g10/main.h
index d86931e8c..c84a059e3 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -162,6 +162,10 @@ int keygen_upd_std_prefs( PKT_signature *sig, void *opaque );
int keygen_add_keyserver_url(PKT_signature *sig, void *opaque);
int keygen_add_revkey(PKT_signature *sig, void *opaque);
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
+#ifdef ENABLE_CARD_SUPPORT
+int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
+ int keyno, const char *serialno);
+#endif
/*-- openfile.c --*/
int overwrite_filep( const char *fname );
@@ -257,6 +261,7 @@ void unblock_all_signals(void);
void change_pin (int no);
void card_status (FILE *fp, char *serialno, size_t serialnobuflen);
void card_edit (STRLIST commands);
+int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock);
#endif
#endif /*G10_MAIN_H*/