Smartcard related updates
authorWerner Koch <wk@gnupg.org>
Wed, 17 Nov 2010 13:21:24 +0000 (13:21 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 17 Nov 2010 13:21:24 +0000 (13:21 +0000)
14 files changed:
ChangeLog
configure.ac
doc/DETAILS
g10/ChangeLog
g10/call-agent.c
g10/card-util.c
g10/gpg.c
g10/keyedit.c
g10/keygen.c
g10/keylist.c
g10/main.h
g10/misc.c
scd/ChangeLog
scd/apdu.c

index 49724a9..4b00b1e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
index 0bb69d2..1fa73e0 100644 (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. */
index 1b6a6d4..2e1d92b 100644 (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
index 5a3febc..7f3db32 100644 (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
index f691baf..9528e14 100644 (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":"", 
index 12b2293..966a320 100644 (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; */
index 847220a..4a17b29 100644 (file)
--- 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;
 
index ee41101..1bd1aa6 100644 (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.  */
              {
index e718a83..ec7e7e7 100644 (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;
index de449e0..1dbd09c 100644 (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 */
index b8ef340..b673cf5 100644 (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_keypairconst 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
 
index cbbba9b..b3b73ed 100644 (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;
index 0624ac8..41c64a5 100644 (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.
index f382aea..80c933e 100644 (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