Smartcard related updates

This commit is contained in:
Werner Koch 2010-11-17 13:21:24 +00:00
parent b97aeb03d5
commit 0103a53aa6
14 changed files with 275 additions and 309 deletions

View File

@ -1,3 +1,7 @@
2010-11-17 Werner Koch <wk@g10code.com>
* configure.ac (ENABLE_CARD_SUPPORT): Define.
2010-10-27 Werner Koch <wk@g10code.com>
* acinclude.m4 (GNUPG_TIME_T_UNSIGNED): New.

View File

@ -485,7 +485,7 @@ AH_BOTTOM([
#define HTTP_NO_WSASTARTUP
/* We always include support for the OpenPGP card. */
/* Disabled for now ENABLE_CARD_SUPPORT 1 */
#define ENABLE_CARD_SUPPORT 1
/* We explicitly need to disable PTH's soft mapping as Debian
currently enables it by default for no reason. */

View File

@ -817,7 +817,8 @@ The format of this file is as follows:
The filename is used until a new filename is used (at commit points)
and all keys are written to that file. If a new filename is given,
this file is created (and overwrites an existing one).
Both control statements must be given.
GnuPG < 2.1: Both control statements must be given.
GnuPG >= 2.1: "%secring" is now a no-op.
%ask-passphrase
Enable a mode where the command "passphrase" is ignored and
instead the usual passphrase dialog is used. This does not

View File

@ -1,3 +1,24 @@
2010-11-17 Werner Koch <wk@g10code.com>
* keyedit.c (find_pk_from_sknode): Remove.
* misc.c (get_signature_count): Call agent.
* keygen.c (gen_card_key): Rework. Remove arg PARA.
(generate_keypair): Change arg BACKUP_ENCRYPTION_DIR to the flag
CARD_BACKUP_KEY.
(pBACKUPENCDIR): Change to pCARDBACKUPKEY.
(struct output_control_s): Remove struct SEC. Remove all usages
of it.
(gen_card_key_with_backup): Remove arg BACKUP_DIR.
* call-agent.c (agent_scd_genkey): Remove extra memset.
2010-11-16 Werner Koch <wk@g10code.com>
* keygen.c (generate_card_subkeypair): Remove arg SEC_KEYBLOCK and
change to return an error code. Rework for removed secring code.
* card-util.c (card_generate_subkey): Remove arg SEC_KEYBLOCK.
Return an error code instead of a success flag. Change caller.
2010-10-29 David Shaw <dshaw@jabberwocky.com>
* pkclist.c (select_algo_from_prefs): Make sure the scores can't

View File

@ -771,10 +771,9 @@ scd_genkey_cb (void *opaque, const char *line)
}
/* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
this implementation. If CREATEDATE has been given, it will be
passed to SCDAEMON so that the key can be created with this
timestamp; note the user needs to use the returned timestamp as old
versions of scddaemon don't support this option. */
this implementation. If CREATEDATE is not 0, it will be passed to
SCDAEMON so that the key is created with this timestamp. INFO will
receive information about the generated key. */
int
agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
const char *serialno, u32 createtime)
@ -794,7 +793,6 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
else
*tbuf = 0;
memset (info, 0, sizeof *info);
snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
*tbuf? "--timestamp=":"", tbuf,
force? "--force":"",

View File

@ -581,29 +581,31 @@ card_status (estream_t fp, char *serialno, size_t serialnobuflen)
if ( thefpr && !fpr_is_ff (thefpr)
&& !get_pubkey_byfprint (pk, thefpr, 20))
{
KBNODE keyblock = NULL;
print_pubkey_info (fp, pk);
#if GNUPG_MAJOR_VERSION == 1
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
print_card_key_info (fp, keyblock);
else if ( !get_keyblock_byfprint (&keyblock, thefpr, 20) )
{
release_kbnode (keyblock);
keyblock = NULL;
if (!auto_create_card_key_stub (info.serialno,
info.fpr1valid? info.fpr1:NULL,
info.fpr2valid? info.fpr2:NULL,
info.fpr3valid? info.fpr3:NULL))
{
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
print_card_key_info (fp, keyblock);
}
}
release_kbnode (keyblock);
{
kbnode_t keyblock = NULL;
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
print_card_key_info (fp, keyblock);
else if ( !get_keyblock_byfprint (&keyblock, thefpr, 20) )
{
release_kbnode (keyblock);
keyblock = NULL;
if (!auto_create_card_key_stub (info.serialno,
info.fpr1valid? info.fpr1:NULL,
info.fpr2valid? info.fpr2:NULL,
info.fpr3valid? info.fpr3:NULL))
{
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
print_card_key_info (fp, keyblock);
}
}
release_kbnode (keyblock);
}
#endif /* GNUPG_MAJOR_VERSION == 1 */
}
else
@ -1431,7 +1433,7 @@ generate_card_keys (void)
the serialnumber and thus it won't harm. */
}
generate_keypair (NULL, info.serialno, want_backup? opt.homedir:NULL);
generate_keypair (NULL, info.serialno, want_backup);
leave:
agent_release_card_info (&info);
@ -1441,17 +1443,18 @@ generate_card_keys (void)
/* This function is used by the key edit menu to generate an arbitrary
subkey. */
int
card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
gpg_error_t
card_generate_subkey (KBNODE pub_keyblock)
{
gpg_error_t err;
struct agent_card_info_s info;
int okay = 0;
int forced_chv1 = 0;
int keyno;
if (get_info_for_key_operation (&info))
return 0;
err = get_info_for_key_operation (&info);
if (err)
return err;
show_card_key_info (&info);
tty_printf (_("Please select the type of key to generate:\n"));
@ -1468,6 +1471,7 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
if (*answer == CONTROL_D)
{
xfree (answer);
err = gpg_error (GPG_ERR_CANCELED);
goto leave;
}
keyno = *answer? atoi(answer): 0;
@ -1476,40 +1480,44 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
break; /* Okay. */
tty_printf(_("Invalid selection.\n"));
}
if (replace_existing_key_p (&info, keyno))
{
err = gpg_error (GPG_ERR_CANCELED);
goto leave;
}
err = check_pin_for_key_operation (&info, &forced_chv1);
if (err)
goto leave;
if (check_pin_for_key_operation (&info, &forced_chv1))
goto leave;
/* If the cards features changeable key attributes, we ask for the
key size. */
if (info.is_v2 && info.extcap.aac)
{
unsigned int nbits;
ask_again:
nbits = ask_card_keysize (keyno-1, info.key_attr[keyno-1].nbits);
if (nbits && do_change_keysize (keyno-1, nbits))
{
/* Error: Better read the default key size again. */
agent_release_card_info (&info);
if (get_info_for_key_operation (&info))
err = get_info_for_key_operation (&info);
if (err)
goto leave;
goto ask_again;
}
/* Note that INFO has not be synced. However we will only use
the serialnumber and thus it won't harm. */
}
/* xxx = generate_card_subkeypair (pub_keyblock, sec_keyblock, */
/* keyno, info.serialno); */
err = generate_card_subkeypair (pub_keyblock, keyno, info.serialno);
leave:
agent_release_card_info (&info);
restore_forced_chv1 (&forced_chv1);
return okay;
return err;
}
@ -1520,6 +1528,7 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
int
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; */
/* int okay = 0; */
/* int rc; */

View File

@ -3705,12 +3705,12 @@ main (int argc, char **argv)
if( opt.batch ) {
if( argc > 1 )
wrong_args("--gen-key [parameterfile]");
generate_keypair( argc? *argv : NULL, NULL, NULL );
generate_keypair (argc? *argv : NULL, NULL, 0);
}
else {
if( argc )
wrong_args("--gen-key");
generate_keypair(NULL, NULL, NULL);
generate_keypair (NULL, NULL, 0);
}
break;

View File

@ -108,35 +108,6 @@ struct sign_attrib
};
#ifdef ENABLE_CARD_SUPPORT
/* Given a node SEC_NODE with a secret key or subkey, locate the
corresponding public key from pub_keyblock. */
static PKT_public_key *
find_pk_from_sknode (KBNODE pub_keyblock, KBNODE sec_node)
{
KBNODE node = pub_keyblock;
PKT_secret_key *sk;
PKT_public_key *pk;
#warning: This is not anymore needed.
if (sec_node->pkt->pkttype == PKT_SECRET_KEY
&& node->pkt->pkttype == PKT_PUBLIC_KEY)
return node->pkt->pkt.public_key;
if (sec_node->pkt->pkttype != PKT_SECRET_SUBKEY)
return NULL;
sk = sec_node->pkt->pkt.secret_key;
for (; node; node = node->next)
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
pk = node->pkt->pkt.public_key;
if (pk->keyid[0] == sk->keyid[0] && pk->keyid[1] == sk->keyid[1])
return pk;
}
return NULL;
}
#endif /* ENABLE_CARD_SUPPORT */
/* TODO: Fix duplicated code between here and the check-sigs/list-sigs
code in keylist.c. */
@ -1833,7 +1804,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
#ifdef ENABLE_CARD_SUPPORT
case cmdADDCARDKEY:
if (card_generate_subkey (keyblock))
if (!card_generate_subkey (keyblock))
{
redisplay = 1;
modified = 1;
@ -1868,7 +1839,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
}
if (node)
{
PKT_public_key *xxpk = find_pk_from_sknode (keyblock, node);
PKT_public_key *xxpk = node->pkt->pkt.public_key;
if (card_store_subkey (node, xxpk ? xxpk->pubkey_usage : 0))
{
redisplay = 1;
@ -1934,25 +1905,25 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
if (cmd == cmdCHECKBKUPKEY)
{
PKT_secret_key *sk = node->pkt->pkt.secret_key;
switch (is_secret_key_protected (sk))
{
case 0: /* Not protected. */
tty_printf (_("This key is not protected.\n"));
break;
case -1:
log_error (_("unknown key protection algorithm\n"));
break;
default:
if (sk->protect.s2k.mode == 1001)
tty_printf (_("Secret parts of key"
" are not available.\n"));
if (sk->protect.s2k.mode == 1002)
tty_printf (_("Secret parts of key"
" are stored on-card.\n"));
/* PKT_public_key *sk = node->pkt->pkt.secret_key; */
/* switch (is_secret_key_protected (sk)) */
/* { */
/* case 0: /\* Not protected. *\/ */
/* tty_printf (_("This key is not protected.\n")); */
/* break; */
/* case -1: */
/* log_error (_("unknown key protection algorithm\n")); */
/* break; */
/* default: */
/* if (sk->protect.s2k.mode == 1001) */
/* tty_printf (_("Secret parts of key" */
/* " are not available.\n")); */
/* if (sk->protect.s2k.mode == 1002) */
/* tty_printf (_("Secret parts of key" */
/* " are stored on-card.\n")); */
/* else */
/* check_secret_key (sk, 0); */
}
/* } */
}
else /* Store it. */
{

View File

@ -78,7 +78,7 @@ enum para_name {
pPASSPHRASE_DEK,
pPASSPHRASE_S2K,
pSERIALNO,
pBACKUPENCDIR,
pCARDBACKUPKEY,
pHANDLE,
pKEYSERVER
};
@ -98,24 +98,19 @@ struct para_data_s {
} u;
};
struct output_control_s {
int lnr;
int dryrun;
int ask_passphrase;
unsigned int keygen_flags;
int use_files;
struct {
char *fname;
char *newfname;
IOBUF stream;
armor_filter_context_t *afx;
} pub;
struct {
char *fname;
char *newfname;
IOBUF stream;
armor_filter_context_t *afx;
} sec;
struct output_control_s
{
int lnr;
int dryrun;
int ask_passphrase;
unsigned int keygen_flags;
int use_files;
struct {
char *fname;
char *newfname;
IOBUF stream;
armor_filter_context_t *afx;
} pub;
};
@ -137,13 +132,12 @@ 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_t out, kbnode_t node);
static int gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
u32 *timestamp, u32 expireval,
struct para_data_s *para);
static gpg_error_t gen_card_key (int algo, int keyno, int is_primary,
kbnode_t pub_root,
u32 *timestamp, u32 expireval);
static int gen_card_key_with_backup (int algo, int keyno, int is_primary,
kbnode_t pub_root, u32 timestamp,
u32 expireval, struct para_data_s *para,
const char *backup_dir);
u32 expireval, struct para_data_s *para);
static void
@ -2217,18 +2211,19 @@ generate_user_id (KBNODE keyblock)
static void
release_parameter_list( struct para_data_s *r )
release_parameter_list (struct para_data_s *r)
{
struct para_data_s *r2;
for( ; r ; r = r2 ) {
r2 = r->next;
if( r->key == pPASSPHRASE_DEK )
xfree( r->u.dek );
else if( r->key == pPASSPHRASE_S2K )
xfree( r->u.s2k );
xfree(r);
struct para_data_s *r2;
for (; r ; r = r2)
{
r2 = r->next;
if (r->key == pPASSPHRASE_DEK)
xfree (r->u.dek);
else if (r->key == pPASSPHRASE_S2K )
xfree (r->u.s2k);
xfree (r);
}
}
@ -2657,11 +2652,6 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
para = r;
}
if( !!outctrl->pub.newfname ^ !!outctrl->sec.newfname ) {
log_error("%s:%d: only one ring name is set\n", fname, outctrl->lnr );
return -1;
}
do_generate_keypair( para, outctrl, card );
return 0;
}
@ -2708,7 +2698,6 @@ read_parameter_file( const char *fname )
memset( &outctrl, 0, sizeof( outctrl ) );
outctrl.pub.afx = new_armor_context ();
outctrl.sec.afx = new_armor_context ();
if( !fname || !*fname)
fname = "-";
@ -2783,13 +2772,7 @@ read_parameter_file( const char *fname )
}
}
else if( !ascii_strcasecmp( keyword, "%secring" ) ) {
if( outctrl.sec.fname && !strcmp( outctrl.sec.fname, value ) )
; /* still the same file - ignore it */
else {
xfree( outctrl.sec.newfname );
outctrl.sec.newfname = xstrdup( value );
outctrl.use_files = 1;
}
/* Ignore this command. */
}
else
log_info("skipping control `%s' (%s)\n", keyword, value );
@ -2865,40 +2848,32 @@ read_parameter_file( const char *fname )
if( outctrl.use_files ) { /* close open streams */
iobuf_close( outctrl.pub.stream );
iobuf_close( outctrl.sec.stream );
/* Must invalidate that ugly cache to actually close it. */
if (outctrl.pub.fname)
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
0, (char*)outctrl.pub.fname);
if (outctrl.sec.fname)
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
0, (char*)outctrl.sec.fname);
xfree( outctrl.pub.fname );
xfree( outctrl.pub.newfname );
xfree( outctrl.sec.fname );
xfree( outctrl.sec.newfname );
}
release_parameter_list( para );
iobuf_close (fp);
release_armor_context (outctrl.pub.afx);
release_armor_context (outctrl.sec.afx);
}
/*
* Generate a keypair (fname is only used in batch mode) If
* CARD_SERIALNO is not NULL the function will create the keys on an
* OpenPGP Card. If BACKUP_ENCRYPTION_DIR has been set and
* CARD_SERIALNO is NOT NULL, the encryption key for the card gets
* generate in software, imported to the card and a backup file
* written to directory given by this argument .
* OpenPGP Card. If CARD_BACKUP_KEY has been set and CARD_SERIALNO is
* NOT NULL, the encryption key for the card is generated on the host,
* imported to the card and a backup file created by gpg-agent.
*/
void
generate_keypair (const char *fname, const char *card_serialno,
const char *backup_encryption_dir)
int card_backup_key)
{
unsigned int nbits;
char *uid = NULL;
@ -2964,11 +2939,11 @@ generate_keypair (const char *fname, const char *card_serialno,
r->next = para;
para = r;
if (backup_encryption_dir)
if (card_backup_key)
{
r = xcalloc (1, sizeof *r + strlen (backup_encryption_dir) );
r->key = pBACKUPENCDIR;
strcpy (r->u.value, backup_encryption_dir);
r = xcalloc (1, sizeof *r + 1);
r->key = pCARDBACKUPKEY;
strcpy (r->u.value, "1");
r->next = para;
para = r;
}
@ -3071,7 +3046,7 @@ generate_keypair (const char *fname, const char *card_serialno,
}
#ifdef ENABLE_CARD_SUPPORT
#if 0 /* not required */
/* Generate a raw key and return it as a secret key packet. The
function will ask for the passphrase and return a protected as well
as an unprotected copy of a new secret key packet. 0 is returned
@ -3270,7 +3245,7 @@ do_generate_keypair (struct para_data_s *para,
else
err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root,
&timestamp,
get_parameter_u32 (para, pKEYEXPIRE), para);
get_parameter_u32 (para, pKEYEXPIRE));
/* Get the pointer to the generated public key packet. */
if (!err)
@ -3301,7 +3276,7 @@ do_generate_keypair (struct para_data_s *para,
{
err = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root,
&timestamp,
get_parameter_u32 (para, pKEYEXPIRE), para);
get_parameter_u32 (para, pKEYEXPIRE));
if (!err)
err = write_keybinding (pub_root, pri_psk, NULL,
PUBKEY_USAGE_AUTH, timestamp, cache_nonce);
@ -3331,23 +3306,20 @@ do_generate_keypair (struct para_data_s *para,
}
else
{
if ((s = get_parameter_value (para, pBACKUPENCDIR)))
if ((s = get_parameter_value (para, pCARDBACKUPKEY)))
{
/* A backup of the encryption key has been requested.
Generate the key in software and import it then to
the card. Write a backup file. */
err = gen_card_key_with_backup (PUBKEY_ALGO_RSA, 2, 0,
pub_root,
timestamp,
get_parameter_u32 (para,
pKEYEXPIRE),
para, s);
err = gen_card_key_with_backup
(PUBKEY_ALGO_RSA, 2, 0, pub_root, timestamp,
get_parameter_u32 (para, pKEYEXPIRE), para);
}
else
{
err = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root,
&timestamp,
get_parameter_u32 (para, pKEYEXPIRE), para);
get_parameter_u32 (para, pKEYEXPIRE));
}
}
@ -3551,81 +3523,65 @@ generate_subkeypair (KBNODE keyblock)
#ifdef ENABLE_CARD_SUPPORT
/* Generate a subkey on a card. */
int
generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
gpg_error_t
generate_card_subkeypair (kbnode_t pub_keyblock,
int keyno, const char *serialno)
{
gpg_error_t err = 0;
int okay = 0;
kbnode_t node;
PKT_secret_key *pri_sk = NULL, *sub_sk;
PKT_public_key *pri_pk = 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 = xtrycalloc (1, sizeof *para + strlen (serialno) );
if (!para)
{
err = gpg_error_from_syserror ();
goto leave;
}
para->key = pSERIALNO;
strcpy (para->u.value, serialno);
/* Break out the primary secret key */
node = find_kbnode (sec_keyblock, PKT_SECRET_KEY);
node = find_kbnode (pub_keyblock, PKT_PUBLIC_KEY);
if (!node)
{
log_error("Oops; secret key not found anymore!\n");
log_error ("Oops; publkic key lost!\n");
err = gpg_error (GPG_ERR_INTERNAL);
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);
pri_pk = node->pkt->pkt.public_key;
cur_time = make_timestamp();
if (pri_sk->timestamp > cur_time)
if (pri_pk->timestamp > cur_time)
{
ulong d = pri_sk->timestamp - cur_time;
ulong d = pri_pk->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)
{
err = G10ERR_TIME_CONFLICT;
err = gpg_error (GPG_ERR_TIME_CONFLICT);
goto leave;
}
}
if (pri_sk->version < 4)
if (pri_pk->version < 4)
{
log_info (_("NOTE: creating subkeys for v3 keys "
"is not OpenPGP compliant\n"));
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
goto leave;
}
/* Unprotect to get the passphrase. */
switch( is_secret_key_protected (pri_sk) )
{
case -1:
err = G10ERR_PUBKEY_ALGO;
break;
case 0:
tty_printf("This key is not protected.\n");
break;
default:
tty_printf("Key is protected.\n");
err = check_secret_key( pri_sk, 0 );
if (!err)
passphrase = get_last_passphrase();
break;
}
if (err)
goto leave;
algo = PUBKEY_ALGO_RSA;
expire = ask_expire_interval (0,NULL);
expire = ask_expire_interval (0, NULL);
if (keyno == 1)
use = PUBKEY_USAGE_SIG;
else if (keyno == 2)
@ -3634,40 +3590,37 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
use = PUBKEY_USAGE_AUTH;
if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.cardsub.okay",
_("Really create? (y/N) ")))
goto leave;
if (passphrase)
set_next_passphrase (passphrase);
{
err = gpg_error (GPG_ERR_CANCELED);
goto leave;
}
/* Note, that depending on the backend, the card key generation may
update CUR_TIME. */
err = gen_card_key (algo, keyno, 0, pub_keyblock, &cur_time, expire, para);
if (!err)
err = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk,
use, cur_time);
if (!err)
err = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk,
use, cur_time);
err = gen_card_key (algo, keyno, 0, pub_keyblock, &cur_time, expire);
/* Get the pointer to the generated public subkey packet. */
if (!err)
{
okay = 1;
write_status_text (STATUS_KEY_CREATED, "S");
PKT_public_key *sub_pk = NULL;
for (node = pub_keyblock; node; node = node->next)
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
sub_pk = node->pkt->pkt.public_key;
assert (sub_pk);
err = write_keybinding (pub_keyblock, pri_pk, sub_pk,
use, cur_time, NULL);
}
leave:
if (err)
log_error (_("Key generation failed: %s\n"), g10_errstr(err) );
xfree (passphrase);
/* Release the copy of the (now unprotected) secret keys. */
if (pri_sk)
free_secret_key (pri_sk);
set_next_passphrase( NULL );
else
write_status_text (STATUS_KEY_CREATED, "S");
release_parameter_list (para);
return okay;
return err;
}
#endif /* !ENABLE_CARD_SUPPORT */
/*
* Write a keyblock to an output stream
*/
@ -3693,83 +3646,73 @@ write_keyblock( IOBUF out, KBNODE node )
/* Note that timestamp is an in/out arg. */
static int
gen_card_key (int algo, int keyno, int is_primary, KBNODE pub_root,
u32 *timestamp, u32 expireval, struct para_data_s *para)
static gpg_error_t
gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
u32 *timestamp, u32 expireval)
{
#ifdef ENABLE_CARD_SUPPORT
int rc;
const char *s;
gpg_error_t err;
struct agent_card_genkey_s info;
PACKET *pkt;
PKT_secret_key *sk;
PKT_public_key *pk;
assert (algo == PUBKEY_ALGO_RSA);
/* Fixme: We don't have the serialnumber available, thus passing NULL. */
rc = agent_scd_genkey (&info, keyno, 1, NULL, *timestamp);
/* if (gpg_err_code (rc) == GPG_ERR_EEXIST) */
/* { */
/* tty_printf ("\n"); */
/* log_error ("WARNING: key does already exists!\n"); */
/* tty_printf ("\n"); */
/* if ( cpr_get_answer_is_yes( "keygen.card.replace_key", */
/* _("Replace existing key? "))) */
/* rc = agent_scd_genkey (&info, keyno, 1); */
/* } */
if (algo != PUBKEY_ALGO_RSA)
return gpg_error (GPG_ERR_PUBKEY_ALGO);
if (rc)
pk = xtrycalloc (1, sizeof *pk );
if (!pk)
return gpg_error_from_syserror ();
pkt = xtrycalloc (1, sizeof *pkt);
if (!pkt)
{
log_error ("key generation failed: %s\n", gpg_strerror (rc));
return rc;
xfree (pk);
return gpg_error_from_syserror ();
}
if ( !info.n || !info.e )
/* Note: SCD knows the serialnumber, thus there is no point in passing it. */
err = agent_scd_genkey (&info, keyno, 1, NULL, *timestamp);
/* The code below is not used because we force creation of
* the a card key (3rd arg).
* if (gpg_err_code (rc) == GPG_ERR_EEXIST)
* {
* tty_printf ("\n");
* log_error ("WARNING: key does already exists!\n");
* tty_printf ("\n");
* if ( cpr_get_answer_is_yes( "keygen.card.replace_key",
* _("Replace existing key? ")))
* rc = agent_scd_genkey (&info, keyno, 1);
* }
*/
if (!err && (!info.n || !info.e))
{
log_error ("communication error with SCD\n");
gcry_mpi_release (info.n);
gcry_mpi_release (info.e);
return gpg_error (GPG_ERR_GENERAL);
err = gpg_error (GPG_ERR_GENERAL);
}
if (err)
{
log_error ("key generation failed: %s\n", gpg_strerror (err));
xfree (pkt);
xfree (pk);
return err;
}
if (*timestamp != info.created_at)
log_info ("Note that the key does not use the suggested creation date\n");
log_info ("NOTE: the key does not use the suggested creation date\n");
*timestamp = info.created_at;
pk = xcalloc (1, sizeof *pk );
sk = xcalloc (1, sizeof *sk );
sk->timestamp = pk->timestamp = info.created_at;
sk->version = pk->version = 4;
pk->timestamp = info.created_at;
pk->version = 4;
if (expireval)
sk->expiredate = pk->expiredate = pk->timestamp + expireval;
sk->pubkey_algo = pk->pubkey_algo = algo;
pk->expiredate = pk->timestamp + expireval;
pk->pubkey_algo = algo;
pk->pkey[0] = info.n;
pk->pkey[1] = info.e;
sk->skey[0] = gcry_mpi_copy (pk->pkey[0]);
sk->skey[1] = gcry_mpi_copy (pk->pkey[1]);
sk->skey[2] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8);
sk->is_protected = 1;
sk->protect.s2k.mode = 1002;
s = get_parameter_value (para, pSERIALNO);
if (s)
{
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);
}
if( ret_sk )
*ret_sk = sk;
pkt = xcalloc (1,sizeof *pkt);
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 = is_primary ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY;
pkt->pkt.secret_key = sk;
add_kbnode(sec_root, new_kbnode( pkt ));
add_kbnode (pub_root, new_kbnode (pkt));
return 0;
#else
@ -3782,10 +3725,9 @@ gen_card_key (int algo, int keyno, int is_primary, KBNODE pub_root,
static int
gen_card_key_with_backup (int algo, int keyno, int is_primary,
KBNODE pub_root, u32 timestamp,
u32 expireval, struct para_data_s *para,
const char *backup_dir)
u32 expireval, struct para_data_s *para)
{
#ifdef ENABLE_CARD_SUPPORT
#if 0 /* FIXME: Move this to gpg-agent. */
int rc;
const char *s;
PACKET *pkt;
@ -3947,9 +3889,9 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary,
}
#ifdef ENABLE_CARD_SUPPORT
#if 0
int
save_unprotected_key_to_card (PKT_secret_key *sk, int keyno)
save_unprotected_key_to_card (PKT_public_key *sk, int keyno)
{
int rc;
unsigned char *rsa_n = NULL;

View File

@ -182,8 +182,7 @@ print_card_key_info (estream_t fp, kbnode_t keyblock)
{
/* KBNODE node; */
/* int i; */
log_debug ("Fixme: Needs to be adjusted to gpg-agent\n");
#warning Fixme: Needs to be adjusted to gpg-agent
/* for (node = keyblock; node; node = node->next) */
/* { */
/* if (node->pkt->pkttype == PKT_SECRET_KEY */

View File

@ -231,8 +231,8 @@ void show_basic_key_info (KBNODE keyblock);
u32 parse_expire_string(const char *string);
u32 ask_expire_interval(int object,const char *def_expire);
u32 ask_expiredate(void);
void generate_keypair( const char *fname, const char *card_serialno,
const char *backup_encryption_dir );
void generate_keypair (const char *fname, const char *card_serialno,
int card_backup_key);
int keygen_set_std_prefs (const char *string,int personal);
PKT_user_id *keygen_get_std_prefs (void);
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
@ -246,9 +246,9 @@ gpg_error_t make_backsig (PKT_signature *sig, PKT_public_key *pk,
u32 timestamp, const char *cache_nonce);
gpg_error_t generate_subkeypair (kbnode_t pub_keyblock);
#ifdef ENABLE_CARD_SUPPORT
int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
int keyno, const char *serialno);
int save_unprotected_key_to_card (PKT_secret_key *sk, int keyno);
gpg_error_t generate_card_subkeypair (kbnode_t pub_keyblock,
int keyno, const char *serialno);
int save_unprotected_key_to_card (PKT_public_key *sk, int keyno);
#endif
/*-- openfile.c --*/
@ -348,7 +348,7 @@ int gpg_server (ctrl_t);
void change_pin (int no, int allow_admin);
void card_status (estream_t fp, char *serialno, size_t serialnobuflen);
void card_edit (ctrl_t ctrl, strlist_t commands);
int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock);
gpg_error_t card_generate_subkey (KBNODE pub_keyblock);
int card_store_subkey (KBNODE node, int use);
#endif

View File

@ -548,13 +548,12 @@ static unsigned long
get_signature_count (PKT_public_key *pk)
{
#ifdef ENABLE_CARD_SUPPORT
/* FIXME: Need to call the agent. */
/* if(sk && sk->is_protected && sk->protect.s2k.mode==1002) */
/* { */
/* struct agent_card_info_s info; */
/* if(agent_scd_getattr("SIG-COUNTER",&info)==0) */
/* return info.sig_counter; */
/* } */
struct agent_card_info_s info;
#warning fixme: We should check that the correct card has been inserted
if (!agent_scd_getattr ("SIG-COUNTER",&info))
return info.sig_counter;
else
return 0;
#else
(void)pk;
return 0;

View File

@ -1,3 +1,8 @@
2010-11-16 Werner Koch <wk@g10code.com>
* apdu.c (PCSC_UNKNOWN) [W32]: Fix all these values which don't
match those of libpcsc. Reported by Michael Petig.
2010-10-27 Werner Koch <wk@g10code.com>
* scdaemon.c (create_socket_name): Use TMPDIR. Change callers.

View File

@ -1,5 +1,5 @@
/* apdu.c - ISO 7816 APDU functions and low level I/O
* Copyright (C) 2003, 2004, 2008, 2009 Free Software Foundation, Inc.
* Copyright (C) 2003, 2004, 2008, 2009, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -165,7 +165,11 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn);
#define PCSC_PROTOCOL_T0 1
#define PCSC_PROTOCOL_T1 2
#define PCSC_PROTOCOL_RAW 4
#ifdef HAVE_W32_SYSTEM
# define PCSC_PROTOCOL_RAW 0x00010000 /* The active protocol. */
#else
# define PCSC_PROTOCOL_RAW 4
#endif
#define PCSC_SHARE_EXCLUSIVE 1
#define PCSC_SHARE_SHARED 2
@ -176,13 +180,23 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn);
#define PCSC_UNPOWER_CARD 2
#define PCSC_EJECT_CARD 3
#define PCSC_UNKNOWN 0x0001
#define PCSC_ABSENT 0x0002 /* Card is absent. */
#define PCSC_PRESENT 0x0004 /* Card is present. */
#define PCSC_SWALLOWED 0x0008 /* Card is present and electrical connected. */
#define PCSC_POWERED 0x0010 /* Card is powered. */
#define PCSC_NEGOTIABLE 0x0020 /* Card is awaiting PTS. */
#define PCSC_SPECIFIC 0x0040 /* Card is ready for use. */
#ifdef HAVE_W32_SYSTEM
# define PCSC_UNKNOWN 0x0000 /* The driver is not aware of the status. */
# define PCSC_ABSENT 0x0001 /* Card is absent. */
# define PCSC_PRESENT 0x0002 /* Card is present. */
# define PCSC_SWALLOWED 0x0003 /* Card is present and electrical connected. */
# define PCSC_POWERED 0x0004 /* Card is powered. */
# define PCSC_NEGOTIABLE 0x0005 /* Card is awaiting PTS. */
# define PCSC_SPECIFIC 0x0006 /* Card is ready for use. */
#else
# define PCSC_UNKNOWN 0x0001
# define PCSC_ABSENT 0x0002 /* Card is absent. */
# define PCSC_PRESENT 0x0004 /* Card is present. */
# define PCSC_SWALLOWED 0x0008 /* Card is present and electrical connected. */
# define PCSC_POWERED 0x0010 /* Card is powered. */
# define PCSC_NEGOTIABLE 0x0020 /* Card is awaiting PTS. */
# define PCSC_SPECIFIC 0x0040 /* Card is ready for use. */
#endif
#define PCSC_STATE_UNAWARE 0x0000 /* Want status. */
#define PCSC_STATE_IGNORE 0x0001 /* Ignore this reader. */
@ -195,6 +209,9 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn);
#define PCSC_STATE_EXCLUSIVE 0x0080 /* Exclusive Mode. */
#define PCSC_STATE_INUSE 0x0100 /* Shared mode. */
#define PCSC_STATE_MUTE 0x0200 /* Unresponsive card. */
#ifdef HAVE_W32_SYSTEM
# define PCSC_STATE_UNPOWERED 0x0400 /* Card not powerred up. */
#endif
/* Some PC/SC error codes. */
#define PCSC_E_CANCELLED 0x80100002