1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

* 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.
This commit is contained in:
Werner Koch 2004-09-20 18:38:39 +00:00
parent 5576f6ef6c
commit 9d17a635c9
12 changed files with 356 additions and 14 deletions

6
NEWS
View File

@ -9,6 +9,12 @@ Noteworthy changes in version 1.3.7
Use the option --disable-card-support to build without support
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
access.

6
TODO
View File

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

View File

@ -1,3 +1,7 @@
2004-09-20 Werner Koch <wk@g10code.com>
* gpg.sgml: Document -K.
2004-09-16 David Shaw <dshaw@jabberwocky.com>
* DETAILS: Document the 'spk' signature subpacket record. Add

View File

@ -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
@ -409,6 +409,11 @@ Revoke a user id.</para></listitem></varlistentry>
<term>addkey</term>
<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>

View File

@ -1,5 +1,16 @@
2004-09-20 Werner Koch <wk@g10code.com>
* 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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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