Extend algo selection menu.
[gnupg.git] / g10 / card-util.c
index dd255a0..966a320 100644 (file)
@@ -58,6 +58,7 @@ write_sc_op_status (gpg_error_t err)
       break;
 #if GNUPG_MAJOR_VERSION != 1
     case GPG_ERR_CANCELED:
+    case GPG_ERR_FULLY_CANCELED:
       write_status_text (STATUS_SC_OP_FAILURE, "1");
       break;
     case GPG_ERR_BAD_PIN:
@@ -207,6 +208,9 @@ get_manufacturer (unsigned int no)
     case 0x0005: return "ZeitControl";
 
     case 0x002A: return "Magrathea";
+
+    case 0xF517: return "FSIJ";
+
       /* 0x00000 and 0xFFFF are defined as test cards per spec,
          0xFFF00 to 0xFFFE are assigned for use with randomly created
          serial numbers.  */
@@ -577,28 +581,32 @@ 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 ( !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);
+#if GNUPG_MAJOR_VERSION == 1
+          {
+            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
         tty_fprintf (fp, "[none]\n");
@@ -716,7 +724,7 @@ change_url (void)
 /* Fetch the key from the URL given on the card or try to get it from
    the default keyserver.  */
 static int
-fetch_url(void)
+fetch_url (ctrl_t ctrl)
 {
   int rc;
   struct agent_card_info_s info;
@@ -746,13 +754,13 @@ fetch_url(void)
                 event, the fpr/keyid is not meaningful for straight
                 HTTP fetches, but using it allows the card to point
                 to HKP and LDAP servers as well. */
-             rc=keyserver_import_fprint(info.fpr1,20,spec);
+             rc = keyserver_import_fprint (ctrl, info.fpr1, 20, spec);
              free_keyserver_spec(spec);
            }
        }
       else if (info.fpr1valid)
        {
-          rc = keyserver_import_fprint (info.fpr1, 20, opt.keyserver);
+          rc = keyserver_import_fprint (ctrl, info.fpr1, 20, opt.keyserver);
        }
     }
 
@@ -1360,6 +1368,8 @@ generate_card_keys (void)
     {
       char *answer;
 
+      /* FIXME: Should be something like cpr_get_bool so that a status
+         GET_BOOL will be emitted.  */
       answer = cpr_get ("cardedit.genkeys.backup_enc",
                         _("Make off-card backup of encryption key? (Y/n) "));
 
@@ -1423,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);
@@ -1433,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"));
@@ -1460,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;
@@ -1468,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;
 }
 
 
@@ -1512,150 +1528,152 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
 int 
 card_store_subkey (KBNODE node, int use)
 {
-  struct agent_card_info_s info;
-  int okay = 0;
-  int rc;
-  int keyno, i;
-  PKT_secret_key *copied_sk = NULL;
-  PKT_secret_key *sk;
-  size_t n;
-  const char *s;
-  int allow_keyno[3];
-  unsigned int nbits;
-
-
-  assert (node->pkt->pkttype == PKT_SECRET_KEY
-          || node->pkt->pkttype == PKT_SECRET_SUBKEY);
-  sk = node->pkt->pkt.secret_key;
-
-  if (get_info_for_key_operation (&info))
-    return 0;
-
-  if (!info.extcap.ki)
-    {
-      tty_printf ("The card does not support the import of keys\n");
-      tty_printf ("\n");
-      goto leave;
-    }
-
-  show_card_key_info (&info);
-
-  nbits = nbits_from_sk (sk);
-
-  if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) )
-    {
-      tty_printf ("You may only store a 1024 bit RSA key on the card\n");
-      tty_printf ("\n");
-      goto leave;
-    }
-
-  allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG)));
-  allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
-  allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
-
-  tty_printf (_("Please select where to store the key:\n"));
-
-  if (allow_keyno[0])
-    tty_printf (_("   (1) Signature key\n"));
-  if (allow_keyno[1])
-    tty_printf (_("   (2) Encryption key\n"));
-  if (allow_keyno[2])
-    tty_printf (_("   (3) Authentication key\n"));
-
-  for (;;) 
-    {
-      char *answer = cpr_get ("cardedit.genkeys.storekeytype",
-                              _("Your selection? "));
-      cpr_kill_prompt();
-      if (*answer == CONTROL_D || !*answer)
-        {
-          xfree (answer);
-          goto leave;
-        }
-      keyno = *answer? atoi(answer): 0;
-      xfree(answer);
-      if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1])
-        {
-          if (info.is_v2 && !info.extcap.aac 
-              && info.key_attr[keyno-1].nbits != nbits)
-            {
-              tty_printf ("Key does not match the card's capability.\n");
-            }
-          else
-            break; /* Okay. */
-        }
-      else
-        tty_printf(_("Invalid selection.\n"));
-    }
-
-  if (replace_existing_key_p (&info, keyno))
-    goto leave;
-
-  /* Unprotect key.  */
-  switch (is_secret_key_protected (sk) )
-    {
-    case 0: /* Not protected. */
-      break;
-    case -1:
-      log_error (_("unknown key protection algorithm\n"));
-      goto leave;
-    default:
-      if (sk->protect.s2k.mode == 1001)
-        {
-          log_error (_("secret parts of key are not available\n"));
-          goto leave;
-       }
-      if (sk->protect.s2k.mode == 1002)
-        {
-          log_error (_("secret key already stored on a card\n"));
-          goto leave;
-       }
-      /* We better copy the key before we unprotect it.  */
-      copied_sk = sk = copy_secret_key (NULL, sk);
-      rc = 0/*check_secret_key (sk, 0)*/;
-      if (rc)
-        goto leave;
-    }
-
-#warning code save_unprotected_key_to_card
-  /* rc = save_unprotected_key_to_card (sk, keyno); */
-  /* if (rc) */
-  /*   { */
-  /*     log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); */
-  /*     goto leave; */
-  /*   } */
-
-  /* Get back to the maybe protected original secret key.  */
-  if (copied_sk)
-    {
-      free_secret_key (copied_sk);
-      copied_sk = NULL; 
-    }
-  sk = node->pkt->pkt.secret_key;
-
-  /* Get rid of the secret key parameters and store the serial numer. */
-  n = pubkey_get_nskey (sk->pubkey_algo);
-  for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++)
-    {
-      gcry_mpi_release (sk->skey[i]);
-      sk->skey[i] = NULL;
-    }
-  i = pubkey_get_npkey (sk->pubkey_algo);
-  sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8);
-  sk->is_protected = 1;
-  sk->protect.s2k.mode = 1002;
-  s = info.serialno;
-  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);
-
-  okay = 1;
-
- leave:
-  if (copied_sk)
-    free_secret_key (copied_sk);
-  agent_release_card_info (&info);
-  return okay;
+  log_info ("FIXME: card_store_subkey has not yet been implemented\n");
+/*   struct agent_card_info_s info; */
+/*   int okay = 0; */
+/*   int rc; */
+/*   int keyno, i; */
+/*   PKT_secret_key *copied_sk = NULL; */
+/*   PKT_secret_key *sk; */
+/*   size_t n; */
+/*   const char *s; */
+/*   int allow_keyno[3]; */
+/*   unsigned int nbits; */
+
+
+/*   assert (node->pkt->pkttype == PKT_SECRET_KEY */
+/*           || node->pkt->pkttype == PKT_SECRET_SUBKEY); */
+/*   sk = node->pkt->pkt.secret_key; */
+
+/*   if (get_info_for_key_operation (&info)) */
+/*     return 0; */
+
+/*   if (!info.extcap.ki) */
+/*     { */
+/*       tty_printf ("The card does not support the import of keys\n"); */
+/*       tty_printf ("\n"); */
+/*       goto leave; */
+/*     } */
+
+/*   show_card_key_info (&info); */
+
+/*   nbits = nbits_from_sk (sk); */
+
+/*   if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) */
+/*     { */
+/*       tty_printf ("You may only store a 1024 bit RSA key on the card\n"); */
+/*       tty_printf ("\n"); */
+/*       goto leave; */
+/*     } */
+
+/*   allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); */
+/*   allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); */
+/*   allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))); */
+
+/*   tty_printf (_("Please select where to store the key:\n")); */
+
+/*   if (allow_keyno[0]) */
+/*     tty_printf (_("   (1) Signature key\n")); */
+/*   if (allow_keyno[1]) */
+/*     tty_printf (_("   (2) Encryption key\n")); */
+/*   if (allow_keyno[2]) */
+/*     tty_printf (_("   (3) Authentication key\n")); */
+
+/*   for (;;)  */
+/*     { */
+/*       char *answer = cpr_get ("cardedit.genkeys.storekeytype", */
+/*                               _("Your selection? ")); */
+/*       cpr_kill_prompt(); */
+/*       if (*answer == CONTROL_D || !*answer) */
+/*         { */
+/*           xfree (answer); */
+/*           goto leave; */
+/*         } */
+/*       keyno = *answer? atoi(answer): 0; */
+/*       xfree(answer); */
+/*       if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) */
+/*         { */
+/*           if (info.is_v2 && !info.extcap.aac  */
+/*               && info.key_attr[keyno-1].nbits != nbits) */
+/*             { */
+/*               tty_printf ("Key does not match the card's capability.\n"); */
+/*             } */
+/*           else */
+/*             break; /\* Okay. *\/ */
+/*         } */
+/*       else */
+/*         tty_printf(_("Invalid selection.\n")); */
+/*     } */
+
+/*   if (replace_existing_key_p (&info, keyno)) */
+/*     goto leave; */
+
+/*   /\* Unprotect key.  *\/ */
+/*   switch (is_secret_key_protected (sk) ) */
+/*     { */
+/*     case 0: /\* Not protected. *\/ */
+/*       break; */
+/*     case -1: */
+/*       log_error (_("unknown key protection algorithm\n")); */
+/*       goto leave; */
+/*     default: */
+/*       if (sk->protect.s2k.mode == 1001) */
+/*         { */
+/*           log_error (_("secret parts of key are not available\n")); */
+/*           goto leave; */
+/*     } */
+/*       if (sk->protect.s2k.mode == 1002) */
+/*         { */
+/*           log_error (_("secret key already stored on a card\n")); */
+/*           goto leave; */
+/*     } */
+/*       /\* We better copy the key before we unprotect it.  *\/ */
+/*       copied_sk = sk = copy_secret_key (NULL, sk); */
+/*       rc = 0/\*check_secret_key (sk, 0)*\/; */
+/*       if (rc) */
+/*         goto leave; */
+/*     } */
+
+/* #warning code save_unprotected_key_to_card */
+/*   /\* rc = save_unprotected_key_to_card (sk, keyno); *\/ */
+/*   /\* if (rc) *\/ */
+/*   /\*   { *\/ */
+/*   /\*     log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); *\/ */
+/*   /\*     goto leave; *\/ */
+/*   /\*   } *\/ */
+
+/*   /\* Get back to the maybe protected original secret key.  *\/ */
+/*   if (copied_sk) */
+/*     { */
+/*       free_secret_key (copied_sk); */
+/*       copied_sk = NULL;  */
+/*     } */
+/*   sk = node->pkt->pkt.secret_key; */
+
+/*   /\* Get rid of the secret key parameters and store the serial numer. *\/ */
+/*   n = pubkey_get_nskey (sk->pubkey_algo); */
+/*   for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) */
+/*     { */
+/*       gcry_mpi_release (sk->skey[i]); */
+/*       sk->skey[i] = NULL; */
+/*     } */
+/*   i = pubkey_get_npkey (sk->pubkey_algo); */
+/*   sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); */
+/*   sk->is_protected = 1; */
+/*   sk->protect.s2k.mode = 1002; */
+/*   s = info.serialno; */
+/*   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); */
+
+/*   okay = 1; */
+
+/*  leave: */
+/*   if (copied_sk) */
+/*     free_secret_key (copied_sk); */
+/*   agent_release_card_info (&info); */
+/*   return okay; */
+  return -1;
 }
 
 
@@ -1757,7 +1775,7 @@ card_edit_completion(const char *text, int start, int end)
 /* Menu to edit all user changeable values on an OpenPGP card.  Only
    Key creation is not handled here. */
 void
-card_edit (strlist_t commands)
+card_edit (ctrl_t ctrl, strlist_t commands)
 {
   enum cmdids cmd = cmdNOP;
   int have_commands = !!commands;
@@ -1916,7 +1934,7 @@ card_edit (strlist_t commands)
           break;
 
        case cmdFETCH:
-         fetch_url();
+         fetch_url (ctrl);
          break;
 
         case cmdLOGIN: