diff --git a/ChangeLog b/ChangeLog index 49724a969..4b00b1e32 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-11-17 Werner Koch + + * configure.ac (ENABLE_CARD_SUPPORT): Define. + 2010-10-27 Werner Koch * acinclude.m4 (GNUPG_TIME_T_UNSIGNED): New. diff --git a/configure.ac b/configure.ac index 0bb69d2f3..1fa73e05a 100644 --- a/configure.ac +++ b/configure.ac @@ -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. */ diff --git a/doc/DETAILS b/doc/DETAILS index 1b6a6d4c0..2e1d92bb7 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -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 diff --git a/g10/ChangeLog b/g10/ChangeLog index 5a3febcc6..7f3db32b2 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,24 @@ +2010-11-17 Werner Koch + + * 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 + + * 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 * pkclist.c (select_algo_from_prefs): Make sure the scores can't diff --git a/g10/call-agent.c b/g10/call-agent.c index f691baf68..9528e1427 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -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":"", diff --git a/g10/card-util.c b/g10/card-util.c index 12b229341..966a3202b 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -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; */ diff --git a/g10/gpg.c b/g10/gpg.c index 847220afd..4a17b2905 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -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; diff --git a/g10/keyedit.c b/g10/keyedit.c index ee411016e..1bd1aa6ee 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -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. */ { diff --git a/g10/keygen.c b/g10/keygen.c index e718a83e8..ec7e7e79c 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -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, ×tamp, - 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, ×tamp, - 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, ×tamp, - 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; diff --git a/g10/keylist.c b/g10/keylist.c index de449e073..1dbd09c39 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -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 */ diff --git a/g10/main.h b/g10/main.h index b8ef34020..b673cf559 100644 --- a/g10/main.h +++ b/g10/main.h @@ -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 diff --git a/g10/misc.c b/g10/misc.c index cbbba9bc3..b3b73ed67 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -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; diff --git a/scd/ChangeLog b/scd/ChangeLog index 0624ac837..41c64a5b3 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2010-11-16 Werner Koch + + * 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 * scdaemon.c (create_socket_name): Use TMPDIR. Change callers. diff --git a/scd/apdu.c b/scd/apdu.c index f382aea85..80c933e59 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -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