gpg: When evaluating trust reg exps, treat tofu+pgp like pgp.
[gnupg.git] / g10 / keygen.c
index 6143269..85bbe13 100644 (file)
@@ -1,4 +1,4 @@
-/* keygen.c - generate a key pair
+/* keygen.c - Generate a key pair
  * Copyright (C) 1998-2007, 2009-2011  Free Software Foundation, Inc.
  * Copyright (C) 2014, 2015  Werner Koch
  *
@@ -43,6 +43,9 @@
 #include "call-agent.h"
 #include "pkglue.h"
 #include "../common/shareddefs.h"
+#include "host2net.h"
+#include "mbox-util.h"
+
 
 /* The default algorithms.  If you change them remember to change them
    also in gpg.c:gpgconf_list.  You should also check that the value
@@ -132,7 +135,7 @@ static byte zip_prefs[MAX_PREFS];
 static int nzip_prefs;
 static int mdc_available,ks_modify;
 
-static void do_generate_keypair( struct para_data_s *para,
+static void do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
                                 struct output_control_s *outctrl, int card );
 static int write_keyblock (iobuf_t out, kbnode_t node);
 static gpg_error_t gen_card_key (int algo, int keyno, int is_primary,
@@ -845,10 +848,7 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk,
                }
              else if (buf[1] == 255)
                {
-                 pktlen  = buf[2] << 24;
-                 pktlen |= buf[3] << 16;
-                 pktlen |= buf[4] << 8;
-                 pktlen |= buf[5];
+                  pktlen = buf32_to_size_t (buf+2);
                  buf += 6;
                }
              else
@@ -865,7 +865,7 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk,
                  break;
 
                case 2:
-                 pktlen  = buf[mark++] << 24;
+                 pktlen  = (size_t)buf[mark++] << 24;
                  pktlen |= buf[mark++] << 16;
 
                case 1:
@@ -1520,6 +1520,13 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
        (((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
          && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
         " transient-key" : ""));
+  else if (algo == PUBKEY_ALGO_ECDH && !strcmp (curve, "Curve25519"))
+    keyparms = xtryasprintf
+      ("(genkey(ecc(curve %zu:%s)(flags djb-tweak comp%s)))",
+       strlen (curve), curve,
+       (((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
+         && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
+        " transient-key" : ""));
   else
     keyparms = xtryasprintf
       ("(genkey(ecc(curve %zu:%s)(flags nocomp%s)))",
@@ -1820,7 +1827,7 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
           char **r_keygrip)
 {
   char *keygrip = NULL;
-  char *answer;
+  char *answer = NULL;
   int algo;
   int dummy_algo;
 
@@ -1875,84 +1882,86 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
     {
       *r_usage = 0;
       *r_subkey_algo = 0;
+      xfree (answer);
       answer = cpr_get ("keygen.algo", _("Your selection? "));
       cpr_kill_prompt ();
       algo = *answer? atoi (answer) : 1;
-      xfree(answer);
-      answer = NULL;
-      if (algo == 1 && !addmode)
+      if ((algo == 1 || !strcmp (answer, "rsa+rsa")) && !addmode)
         {
           algo = PUBKEY_ALGO_RSA;
           *r_subkey_algo = PUBKEY_ALGO_RSA;
           break;
        }
-      else if (algo == 2 && !addmode)
+      else if ((algo == 2 || !strcmp (answer, "dsa+elg")) && !addmode)
         {
           algo = PUBKEY_ALGO_DSA;
           *r_subkey_algo = PUBKEY_ALGO_ELGAMAL_E;
           break;
        }
-      else if (algo == 3)
+      else if (algo == 3 || !strcmp (answer, "dsa"))
         {
           algo = PUBKEY_ALGO_DSA;
           *r_usage = PUBKEY_USAGE_SIG;
           break;
        }
-      else if (algo == 4)
+      else if (algo == 4 || !strcmp (answer, "rsa/s"))
         {
           algo = PUBKEY_ALGO_RSA;
           *r_usage = PUBKEY_USAGE_SIG;
           break;
        }
-      else if (algo == 5 && addmode)
+      else if ((algo == 5 || !strcmp (answer, "elg")) && addmode)
         {
           algo = PUBKEY_ALGO_ELGAMAL_E;
           *r_usage = PUBKEY_USAGE_ENC;
           break;
        }
-      else if (algo == 6 && addmode)
+      else if ((algo == 6 || !strcmp (answer, "rsa/e")) && addmode)
         {
           algo = PUBKEY_ALGO_RSA;
           *r_usage = PUBKEY_USAGE_ENC;
           break;
        }
-      else if (algo == 7 && opt.expert)
+      else if ((algo == 7 || !strcmp (answer, "dsa/*")) && opt.expert)
         {
           algo = PUBKEY_ALGO_DSA;
           *r_usage = ask_key_flags (algo, addmode);
           break;
        }
-      else if (algo == 8 && opt.expert)
+      else if ((algo == 8 || !strcmp (answer, "rsa/*")) && opt.expert)
         {
           algo = PUBKEY_ALGO_RSA;
           *r_usage = ask_key_flags (algo, addmode);
           break;
        }
-      else if (algo == 9 && opt.expert && !addmode)
+      else if ((algo == 9 || !strcmp (answer, "ecc+ecc"))
+               && opt.expert && !addmode)
         {
           algo = PUBKEY_ALGO_ECDSA;
           *r_subkey_algo = PUBKEY_ALGO_ECDH;
           break;
        }
-      else if (algo == 10 && opt.expert)
+      else if ((algo == 10 || !strcmp (answer, "ecc/s")) && opt.expert)
         {
           algo = PUBKEY_ALGO_ECDSA;
           *r_usage = PUBKEY_USAGE_SIG;
           break;
        }
-      else if (algo == 11 && opt.expert)
+      else if ((algo == 11 || !strcmp (answer, "ecc/*")) && opt.expert)
         {
           algo = PUBKEY_ALGO_ECDSA;
           *r_usage = ask_key_flags (algo, addmode);
           break;
        }
-      else if (algo == 12 && opt.expert && addmode)
+      else if ((algo == 12 || !strcmp (answer, "ecc/e"))
+               && opt.expert && addmode)
         {
           algo = PUBKEY_ALGO_ECDH;
           *r_usage = PUBKEY_USAGE_ENC;
           break;
        }
-      else if (algo == 13 && opt.expert && r_keygrip)
+      else if ((algo == 13 || !strcmp (answer, "keygrip"))
+               && opt.expert && r_keygrip)
         {
           for (;;)
             {
@@ -1984,8 +1993,10 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
        }
       else
         tty_printf (_("Invalid selection.\n"));
+
     }
 
+  xfree(answer);
   if (r_keygrip)
     *r_keygrip = keygrip;
   return algo;
@@ -2121,7 +2132,7 @@ ask_keysize (int algo, unsigned int primary_keysize)
    function may adjust.  Returns a malloced string with the name of
    the curve.  BOTH tells that gpg creates a primary and subkey. */
 static char *
-ask_curve (int *algo, int both)
+ask_curve (int *algo, int *subkey_algo)
 {
   struct {
     const char *name;
@@ -2172,7 +2183,7 @@ ask_curve (int *algo, int both)
         continue;
       if (!gcry_pk_get_curve (keyparms, 0, NULL))
         continue;
-      if (both && curves[idx].fix_curve)
+      if (subkey_algo && curves[idx].fix_curve)
         {
           /* Both Curve 25519 keys are to be created.  Check that
              Libgcrypt also supports the real Curve25519.  */
@@ -2237,6 +2248,11 @@ ask_curve (int *algo, int both)
           if ((*algo == PUBKEY_ALGO_ECDSA || *algo == PUBKEY_ALGO_EDDSA)
               && curves[idx].fix_curve)
             {
+              if (subkey_algo && *subkey_algo == PUBKEY_ALGO_ECDSA)
+                {
+                  *subkey_algo = PUBKEY_ALGO_EDDSA;
+                  result = xstrdup ("Ed25519");
+                }
               *algo = PUBKEY_ALGO_EDDSA;
               result = xstrdup ("Ed25519");
             }
@@ -2442,6 +2458,24 @@ uid_from_string (const char *string)
 }
 
 
+/* Return true if the user id UID already exists in the keyblock.  */
+static int
+uid_already_in_keyblock (kbnode_t keyblock, const char *uid)
+{
+  PKT_user_id *uidpkt = uid_from_string (uid);
+  kbnode_t node;
+  int result = 0;
+
+  for (node=keyblock; node && !result; node=node->next)
+    if (!is_deleted_kbnode (node)
+        && node->pkt->pkttype == PKT_USER_ID
+        && !cmp_user_ids (uidpkt, node->pkt->pkt.user_id))
+      result = 1;
+  free_user_id (uidpkt);
+  return result;
+}
+
+
 /* Ask for a user ID.  With a MODE of 1 an extra help prompt is
    printed for use during a new key creation.  If KEYBLOCK is not NULL
    the function prevents the creation of an already existing user
@@ -2579,17 +2613,11 @@ ask_user_id (int mode, int full, KBNODE keyblock)
 
         if (!fail && keyblock)
           {
-            PKT_user_id *uidpkt = uid_from_string (uid);
-            KBNODE node;
-
-            for (node=keyblock; node && !fail; node=node->next)
-              if (!is_deleted_kbnode (node)
-                  && node->pkt->pkttype == PKT_USER_ID
-                  && !cmp_user_ids (uidpkt, node->pkt->pkt.user_id))
-               fail = 1;
-            if (fail)
-              tty_printf (_("Such a user ID already exists on this key!\n"));
-            free_user_id (uidpkt);
+            if (uid_already_in_keyblock (keyblock, uid))
+              {
+                tty_printf (_("Such a user ID already exists on this key!\n"));
+                fail = 1;
+              }
           }
 
        for(;;) {
@@ -2763,16 +2791,32 @@ do_create (int algo, unsigned int nbits, const char *curve, KBNODE pub_root,
 
 /* Generate a new user id packet or return NULL if canceled.  If
    KEYBLOCK is not NULL the function prevents the creation of an
-   already existing user ID.  */
+   already existing user ID.  If UIDSTR is not NULL the user is not
+   asked but UIDSTR is used to create the user id packet; if the user
+   id already exists NULL is returned.  UIDSTR is expected to be utf-8
+   encoded and should have already been checked for a valid length
+   etc.  */
 PKT_user_id *
-generate_user_id (KBNODE keyblock)
+generate_user_id (KBNODE keyblock, const char *uidstr)
 {
+  PKT_user_id *uid;
   char *p;
 
-  p = ask_user_id (1, 1, keyblock);
-  if (!p)
-    return NULL;  /* Canceled. */
-  return uid_from_string (p);
+  if (uidstr)
+    {
+      if (uid_already_in_keyblock (keyblock, uidstr))
+        return NULL;  /* Already exists.  */
+      uid = uid_from_string (uidstr);
+    }
+  else
+    {
+      p = ask_user_id (1, 1, keyblock);
+      if (!p)
+        return NULL;  /* Canceled. */
+      uid = uid_from_string (p);
+      xfree (p);
+    }
+  return uid;
 }
 
 
@@ -2826,7 +2870,7 @@ static const char *
 get_parameter_passphrase (struct para_data_s *para)
 {
   struct para_data_s *r = get_parameter (para, pPASSPHRASE);
-  return r->u.value;
+  return r ? r->u.value : NULL;
 }
 
 
@@ -2992,7 +3036,7 @@ get_parameter_revkey( struct para_data_s *para, enum para_name key )
 }
 
 static int
-proc_parameter_file( struct para_data_s *para, const char *fname,
+proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
                      struct output_control_s *outctrl, int card )
 {
   struct para_data_s *r;
@@ -3178,7 +3222,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
       append_to_parameter (para, r);
     }
 
-  do_generate_keypair( para, outctrl, card );
+  do_generate_keypair (ctrl, para, outctrl, card );
   return 0;
 }
 
@@ -3189,7 +3233,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
  * Note, that string parameters are expected to be in UTF-8
  */
 static void
-read_parameter_file( const char *fname )
+read_parameter_file (ctrl_t ctrl, const char *fname )
 {
     static struct { const char *name;
                    enum para_name key;
@@ -3284,7 +3328,7 @@ read_parameter_file( const char *fname )
                 outctrl.keygen_flags |= KEYGEN_FLAG_TRANSIENT_KEY;
            else if( !ascii_strcasecmp( keyword, "%commit" ) ) {
                outctrl.lnr = lnr;
-               if (proc_parameter_file( para, fname, &outctrl, 0 ))
+               if (proc_parameter_file (ctrl, para, fname, &outctrl, 0 ))
                   print_status_key_not_created
                     (get_parameter_value (para, pHANDLE));
                release_parameter_list( para );
@@ -3340,7 +3384,7 @@ read_parameter_file( const char *fname )
 
        if( keywords[i].key == pKEYTYPE && para ) {
            outctrl.lnr = lnr;
-           if (proc_parameter_file( para, fname, &outctrl, 0 ))
+           if (proc_parameter_file (ctrl, para, fname, &outctrl, 0 ))
               print_status_key_not_created
                 (get_parameter_value (para, pHANDLE));
            release_parameter_list( para );
@@ -3370,7 +3414,7 @@ read_parameter_file( const char *fname )
     }
     else if( para ) {
        outctrl.lnr = lnr;
-       if (proc_parameter_file( para, fname, &outctrl, 0 ))
+       if (proc_parameter_file (ctrl, para, fname, &outctrl, 0 ))
           print_status_key_not_created (get_parameter_value (para, pHANDLE));
     }
 
@@ -3435,7 +3479,7 @@ quickgen_set_para (struct para_data_s *para, int for_subkey,
  * Unattended generation of a standard key.
  */
 void
-quick_generate_keypair (const char *uid)
+quick_generate_keypair (ctrl_t ctrl, const char *uid)
 {
   gpg_error_t err;
   struct para_data_s *para = NULL;
@@ -3525,7 +3569,7 @@ quick_generate_keypair (const char *uid)
       para = r;
     }
 
-  proc_parameter_file (para, "[internal]", &outctrl, 0);
+  proc_parameter_file (ctrl, para, "[internal]", &outctrl, 0);
  leave:
   release_parameter_list (para);
 }
@@ -3569,7 +3613,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
 
   if (opt.batch)
     {
-      read_parameter_file( fname );
+      read_parameter_file (ctrl, fname);
       return;
     }
 
@@ -3640,7 +3684,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
               || algo == PUBKEY_ALGO_EDDSA
               || algo == PUBKEY_ALGO_ECDH)
             {
-              curve = ask_curve (&algo, both);
+              curve = ask_curve (&algo, &subkey_algo);
               r = xmalloc_clear( sizeof *r + 20 );
               r->key = pKEYTYPE;
               sprintf( r->u.value, "%d", algo);
@@ -3711,7 +3755,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
               || algo == PUBKEY_ALGO_EDDSA
               || algo == PUBKEY_ALGO_ECDH)
             {
-              curve = ask_curve (&algo, 0);
+              curve = ask_curve (&algo, NULL);
               nbits = 0;
               r = xmalloc_clear (sizeof *r + strlen (curve));
               r->key = pKEYCURVE;
@@ -3797,7 +3841,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
   r->next = para;
   para = r;
 
-  proc_parameter_file (para, "[internal]", &outctrl, !!card_serialno);
+  proc_parameter_file (ctrl, para, "[internal]", &outctrl, !!card_serialno);
   release_parameter_list (para);
 }
 
@@ -3914,7 +3958,7 @@ start_tree(KBNODE *tree)
 
 
 static void
-do_generate_keypair (struct para_data_s *para,
+do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
                     struct output_control_s *outctrl, int card)
 {
   gpg_error_t err;
@@ -4102,7 +4146,7 @@ do_generate_keypair (struct para_data_s *para,
     {
       KEYDB_HANDLE pub_hd = keydb_new ();
 
-      err = keydb_locate_writable (pub_hd, NULL);
+      err = keydb_locate_writable (pub_hd);
       if (err)
         log_error (_("no writable public keyring found: %s\n"),
                    gpg_strerror (err));
@@ -4148,7 +4192,7 @@ do_generate_keypair (struct para_data_s *para,
             {
               tty_printf (_("public and secret key created and signed.\n") );
               tty_printf ("\n");
-              list_keyblock (pub_root, 0, 1, 1, NULL);
+              list_keyblock_direct (ctrl, pub_root, 0, 1, 1);
             }
 
 
@@ -4260,7 +4304,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
   else if (algo == PUBKEY_ALGO_ECDSA
            || algo == PUBKEY_ALGO_EDDSA
            || algo == PUBKEY_ALGO_ECDH)
-    curve = ask_curve (&algo, 0);
+    curve = ask_curve (&algo, NULL);
   else
     nbits = ask_keysize (algo, 0);
 
@@ -4483,7 +4527,7 @@ gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root,
   /* Send the learn command so that the agent creates a shadow key for
      card key.  We need to do that now so that we are able to create
      the self-signatures. */
-  err = agent_scd_learn (NULL);
+  err = agent_scd_learn (NULL, 0);
   if (err)
     {
       /* Oops: Card removed during generation.  */