Use macros for iobuf ioctls.
[gnupg.git] / g10 / keygen.c
index 3b5bb44..9d5d39d 100644 (file)
@@ -1,6 +1,6 @@
 /* keygen.c - generate a key pair
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- *               2006, 2007 Free Software Foundation, Inc.
+ *               2006, 2007, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include "keyserver-internal.h"
 #include "call-agent.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
+   is inside the bounds enforced by ask_keysize and gen_xxx.  */
+#define DEFAULT_STD_ALGO    GCRY_PK_RSA
+#define DEFAULT_STD_KEYSIZE 2048
+
 
 #define MAX_PREFS 30 
 
@@ -301,7 +307,7 @@ keygen_set_std_prefs (const char *string,int personal)
     byte sym[MAX_PREFS], hash[MAX_PREFS], zip[MAX_PREFS];
     int nsym=0, nhash=0, nzip=0, val, rc=0;
     int mdc=1, modify=0; /* mdc defaults on, modify defaults off. */
-    char dummy_string[45+1]; /* Enough for 15 items. */
+    char dummy_string[20*4+1]; /* Enough for 20 items. */
 
     if (!string || !ascii_strcasecmp (string, "default"))
       {
@@ -345,15 +351,29 @@ keygen_set_std_prefs (const char *string,int personal)
            if ( !openpgp_cipher_test_algo (CIPHER_ALGO_IDEA) )
              strcat(dummy_string,"S1 ");
 
-           /* SHA-1 */
-           strcat(dummy_string,"H2 ");
 
-           if (!openpgp_md_test_algo(DIGEST_ALGO_SHA256))
-             strcat(dummy_string,"H8 ");
+            /* The default hash algo order is:
+                 SHA-256, SHA-1, SHA-384, SHA-512, SHA-224.
+               Ordering SHA-1 before SHA-384 might be viewed as a bit
+               strange; it is done because we expect that soon enough
+               SHA-3 will be available and at that point there should
+               be no more need for SHA-384 etc.  Anyway this order is
+               just a default and can easily be changed by a config
+               option.  */
+           if (!openpgp_md_test_algo (DIGEST_ALGO_SHA256))
+             strcat (dummy_string, "H8 ");
+
+           strcat (dummy_string, "H2 "); /* SHA-1 */
+
+           if (!openpgp_md_test_algo (DIGEST_ALGO_SHA384))
+             strcat (dummy_string, "H9 ");
+
+           if (!openpgp_md_test_algo (DIGEST_ALGO_SHA512))
+             strcat (dummy_string, "H10 ");
+
+           if (!openpgp_md_test_algo (DIGEST_ALGO_SHA224))
+             strcat (dummy_string, "H11 ");
 
-           /* RIPEMD160 */
-           if (!openpgp_md_test_algo(DIGEST_ALGO_RMD160))
-              strcat(dummy_string,"H3 ");
 
            /* ZLIB */
            strcat(dummy_string,"Z2 ");
@@ -507,7 +527,8 @@ keygen_set_std_prefs (const char *string,int personal)
 
 /* Return a fake user ID containing the preferences.  Caller must
    free. */
-PKT_user_id *keygen_get_std_prefs(void)
+PKT_user_id *
+keygen_get_std_prefs(void)
 {
   int i,j=0;
   PKT_user_id *uid=xmalloc_clear(sizeof(PKT_user_id));
@@ -1280,6 +1301,14 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
       log_info(_("keysize rounded up to %u bits\n"), nbits );
     }
 
+  /* To comply with FIPS rules we round up to the next value unless in
+     expert mode.  */
+  if (!opt.expert && nbits > 1024 && (nbits % 1024))
+    {
+      nbits = ((nbits + 1023) / 1024) * 1024;
+      log_info(_("keysize rounded up to %u bits\n"), nbits );
+    }
+
   /*
     Figure out a q size based on the key size.  FIPS 180-3 says:
  
@@ -1291,11 +1320,11 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
     2048/256 is an odd pair since there is also a 2048/224 and
     3072/256.  Matching sizes is not a very exact science.
       
-    We'll do 256 qbits for nbits over 2048, 224 for nbits over 1024
+    We'll do 256 qbits for nbits over 2047, 224 for nbits over 1024
     but less than 2048, and 160 for 1024 (DSA1).
   */
  
-  if (nbits > 2048)
+  if (nbits > 2047)
     qbits = 256;
   else if ( nbits > 1024)
     qbits = 224;
@@ -1403,6 +1432,9 @@ gen_rsa (int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
 
   assert (is_RSA(algo));
 
+  if (!nbits)
+    nbits = DEFAULT_STD_KEYSIZE;
+
   if (nbits < 1024) 
     {
       nbits = 1024;
@@ -1736,13 +1768,13 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
 }
 
 
-/* Ask for the key size.  ALGO is the algorithjm.  If PRIMARY_KEYSIZE
+/* Ask for the key size.  ALGO is the algorithm.  If PRIMARY_KEYSIZE
    is not 0, the function asks for the size of the encryption
    subkey. */
 static unsigned
 ask_keysize (int algo, unsigned int primary_keysize)
 {
-  unsigned int nbits, min, def=2048, max=4096;
+  unsigned int nbits, min, def = DEFAULT_STD_KEYSIZE, max=4096;
   int for_subkey = !!primary_keysize;
   int autocomp = 0;
 
@@ -1994,8 +2026,28 @@ ask_expiredate()
 }
 
 
+
+static PKT_user_id *
+uid_from_string (const char *string)
+{
+  size_t n;
+  PKT_user_id *uid;
+
+  n = strlen (string);
+  uid = xmalloc_clear (sizeof *uid + n);
+  uid->len = n;
+  strcpy (uid->name, string);
+  uid->ref = 1;
+  return uid;
+}
+
+
+/* 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
+   ID.  */
 static char *
-ask_user_id( int mode )
+ask_user_id (int mode, KBNODE keyblock)
 {
     char *answer;
     char *aname, *acomment, *amail, *uid;
@@ -2111,14 +2163,29 @@ ask_user_id( int mode )
        }
 
        tty_printf(_("You selected this USER-ID:\n    \"%s\"\n\n"), uid);
-       /* fixme: add a warning if this user-id already exists */
+
        if( !*amail && !opt.allow_freeform_uid
            && (strchr( aname, '@' ) || strchr( acomment, '@'))) {
            fail = 1;
-           tty_printf(_("Please don't put the email address "
-                         "into the real name or the comment\n") );
+            tty_printf(_("Please don't put the email address "
+                         "into the real name or the comment\n") );
        }
 
+        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);
+          }
+
        for(;;) {
             /* TRANSLATORS: These are the allowed answers in
                lower and uppercase.  Below you will find the matching
@@ -2136,7 +2203,7 @@ ask_user_id( int mode )
            if( strlen(ansstr) != 10 )
                BUG();
            if( cpr_enabled() ) {
-               answer = xstrdup(ansstr+6);
+                answer = xstrdup (ansstr + (fail?8:6));
                answer[1] = 0;
            }
            else {
@@ -2273,25 +2340,18 @@ do_create (int algo, unsigned int nbits, KBNODE pub_root, KBNODE sec_root,
 }
 
 
-/****************
- * Generate a new user id packet, or return NULL if canceled
- */
+/* 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.  */
 PKT_user_id *
-generate_user_id()
+generate_user_id (KBNODE keyblock)
 {
-    PKT_user_id *uid;
-    char *p;
-    size_t n;
-
-    p = ask_user_id( 1 );
-    if( !p )
-       return NULL;
-    n = strlen(p);
-    uid = xmalloc_clear( sizeof *uid + n );
-    uid->len = n;
-    strcpy(uid->name, p);
-    uid->ref = 1;
-    return uid;
+  char *p;
+  
+  p = ask_user_id (1, keyblock);
+  if (!p)
+    return NULL;  /* Canceled. */
+  return uid_from_string (p);
 }
 
 
@@ -2329,22 +2389,37 @@ get_parameter_value( struct para_data_s *para, enum para_name key )
 }
 
 static int
-get_parameter_algo( struct para_data_s *para, enum para_name key )
+get_parameter_algo( struct para_data_s *para, enum para_name key, 
+                    int *r_default)
 {
-    int i;
-    struct para_data_s *r = get_parameter( para, key );
-    if( !r )
-       return -1;
-    if( digitp( r->u.value ) )
-       i = atoi( r->u.value );
-    else if ( !strcmp ( r->u.value, "ELG-E")
-              || !strcmp ( r->u.value, "ELG") )
-        i = GCRY_PK_ELG_E;
-    else
-        i = gcry_pk_map_name (r->u.value);
-    if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S)
-      i = 0; /* we don't want to allow generation of these algorithms */
-    return i;
+  int i;
+  struct para_data_s *r = get_parameter( para, key );
+
+  if (r_default)
+    *r_default = 0;
+
+  if (!r)
+    return -1;
+
+  if (!ascii_strcasecmp (r->u.value, "default"))
+    {
+      /* Note: If you change this default algo, remember to change it
+         also in gpg.c:gpgconf_list.  */
+      i = DEFAULT_STD_ALGO;
+      if (r_default)
+        *r_default = 1;
+    }
+  else if (digitp (r->u.value))
+    i = atoi( r->u.value );
+  else if (!strcmp (r->u.value, "ELG-E")
+           || !strcmp (r->u.value, "ELG"))
+    i = GCRY_PK_ELG_E;
+  else
+    i = gcry_pk_map_name (r->u.value);
+
+  if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S)
+    i = 0; /* we don't want to allow generation of these algorithms */
+  return i;
 }
 
 /* 
@@ -2488,13 +2563,15 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
   const char *s1, *s2, *s3;
   size_t n;
   char *p;
-  int have_user_id=0,err,algo;
+  int is_default = 0;
+  int have_user_id = 0;
+  int err, algo;
 
   /* Check that we have all required parameters. */
   r = get_parameter( para, pKEYTYPE );
   if(r)
     {
-      algo=get_parameter_algo(para,pKEYTYPE);
+      algo = get_parameter_algo (para, pKEYTYPE, &is_default);
       if (openpgp_pk_test_algo2 (algo, PUBKEY_USAGE_SIG))
        {
          log_error ("%s:%d: invalid algorithm\n", fname, r->lnr );
@@ -2510,10 +2587,13 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
   err = parse_parameter_usage (fname, para, pKEYUSAGE);
   if (!err)
     {
-      /* Default to algo capabilities if key-usage is not provided */
+      /* Default to algo capabilities if key-usage is not provided and
+         no default algorithm has been requested.  */
       r = xmalloc_clear(sizeof(*r));
       r->key = pKEYUSAGE;
-      r->u.usage = openpgp_pk_algo_usage(algo);
+      r->u.usage = (is_default
+                    ? (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG)
+                    : openpgp_pk_algo_usage(algo));
       r->next = para;
       para = r;
     }
@@ -2530,10 +2610,11 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
         }
     }
 
+  is_default = 0;
   r = get_parameter( para, pSUBKEYTYPE );
   if(r)
     {
-      algo = get_parameter_algo (para, pSUBKEYTYPE);
+      algo = get_parameter_algo (para, pSUBKEYTYPE, &is_default);
       if (openpgp_pk_test_algo (algo))
        {
          log_error ("%s:%d: invalid algorithm\n", fname, r->lnr );
@@ -2547,7 +2628,9 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
             provided */
          r = xmalloc_clear (sizeof(*r));
          r->key = pSUBKEYUSAGE;
-         r->u.usage = openpgp_pk_algo_usage (algo);
+         r->u.usage = (is_default
+                        ? PUBKEY_USAGE_ENC
+                        : openpgp_pk_algo_usage (algo));
          r->next = para;
          para = r;
        }
@@ -2794,7 +2877,7 @@ read_parameter_file( const char *fname )
       log_error (_("can't open `%s': %s\n"), fname, strerror(errno) );
       return;
     }
-    iobuf_ioctl (fp, 3, 1, NULL); /* No file caching. */
+    iobuf_ioctl (fp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
 
     lnr = 0;
     err = NULL;
@@ -2935,9 +3018,11 @@ read_parameter_file( const char *fname )
 
         /* Must invalidate that ugly cache to actually close it.  */
         if (outctrl.pub.fname)
-          iobuf_ioctl (NULL, 2, 0, (char*)outctrl.pub.fname);
+          iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 
+                       0, (char*)outctrl.pub.fname);
         if (outctrl.sec.fname)
-          iobuf_ioctl (NULL, 2, 0, (char*)outctrl.sec.fname);
+          iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
+                       0, (char*)outctrl.sec.fname);
 
        xfree( outctrl.pub.fname );
        xfree( outctrl.pub.newfname );
@@ -3100,7 +3185,7 @@ generate_keypair (const char *fname, const char *card_serialno,
           nbits = 0;
         }
 
-      nbits = ask_keysize (algo, nbits);
+      nbits = ask_keysize (both? subkey_algo : algo, nbits);
       r = xmalloc_clear( sizeof *r + 20 );
       r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
       sprintf( r->u.value, "%u", nbits);
@@ -3120,7 +3205,7 @@ generate_keypair (const char *fname, const char *card_serialno,
   r->next = para;
   para = r;
 
-  uid = ask_user_id(0);
+  uid = ask_user_id (0, NULL);
   if( !uid ) 
     {
       log_error(_("Key generation canceled.\n"));
@@ -3294,7 +3379,8 @@ do_generate_keypair (struct para_data_s *para,
           iobuf_close(outctrl->pub.stream);
           outctrl->pub.stream = NULL;
           if (outctrl->pub.fname)
-            iobuf_ioctl (NULL, 2, 0, (char*)outctrl->pub.fname);
+            iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
+                         0, (char*)outctrl->pub.fname);
           xfree( outctrl->pub.fname );
           outctrl->pub.fname =  outctrl->pub.newfname;
           outctrl->pub.newfname = NULL;
@@ -3325,7 +3411,8 @@ do_generate_keypair (struct para_data_s *para,
           iobuf_close(outctrl->sec.stream);
           outctrl->sec.stream = NULL;
           if (outctrl->sec.fname)
-            iobuf_ioctl (NULL, 2, 0, (char*)outctrl->sec.fname);
+            iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
+                         0, (char*)outctrl->sec.fname);
           xfree( outctrl->sec.fname );
           outctrl->sec.fname =  outctrl->sec.newfname;
           outctrl->sec.newfname = NULL;
@@ -3377,9 +3464,18 @@ do_generate_keypair (struct para_data_s *para,
   if (!timestamp)
     timestamp = make_timestamp ();
 
+  /* Note that, depending on the backend (i.e. the used scdaemon
+     version), the card key generation may update TIMESTAMP for each
+     key.  Thus we need to pass TIMESTAMP to all signing function to
+     make sure that the binding signature is done using the timestamp
+     of the corresponding (sub)key and not that of the primary key.
+     An alternative implementation could tell the signing function the
+     node of the subkey but that is more work than just to pass the
+     current timestamp.  */
+
   if (!card)
     {
-      rc = do_create (get_parameter_algo( para, pKEYTYPE ),
+      rc = do_create (get_parameter_algo( para, pKEYTYPE, NULL ),
                       get_parameter_uint( para, pKEYLENGTH ),
                       pub_root, sec_root,
                       get_parameter_dek( para, pPASSPHRASE_DEK ),
@@ -3390,8 +3486,6 @@ do_generate_keypair (struct para_data_s *para,
     }
   else
     {
-      /* Note, that depending on the backend, the card key generation
-         may update TIMESTAMP.  */
       rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root, NULL,
                          &timestamp,
                          get_parameter_u32 (para, pKEYEXPIRE), para);
@@ -3427,8 +3521,6 @@ do_generate_keypair (struct para_data_s *para,
 
   if (!rc && card && get_parameter (para, pAUTHKEYTYPE))
     {
-      /* Note, that depending on the backend, the card key generation
-         may update TIMESTAMP.  */
       rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, NULL,
                          &timestamp,
                          get_parameter_u32 (para, pKEYEXPIRE), para);
@@ -3445,7 +3537,7 @@ do_generate_keypair (struct para_data_s *para,
     {
       if (!card)
         {
-          rc = do_create( get_parameter_algo( para, pSUBKEYTYPE ),
+          rc = do_create( get_parameter_algo( para, pSUBKEYTYPE, NULL ),
                           get_parameter_uint( para, pSUBKEYLENGTH ),
                           pub_root, sec_root,
                           get_parameter_dek( para, pPASSPHRASE_DEK ),
@@ -3470,8 +3562,6 @@ do_generate_keypair (struct para_data_s *para,
             }
           else
             {
-              /* Note, that depending on the backend, the card key
-                 generation may update TIMESTAMP.  */
               rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root,
                                  NULL,
                                  &timestamp,
@@ -3556,7 +3646,8 @@ do_generate_keypair (struct para_data_s *para,
           int no_enc_rsa;
           PKT_public_key *pk;
 
-          no_enc_rsa = (get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_RSA
+          no_enc_rsa = ((get_parameter_algo (para, pKEYTYPE, NULL)
+                         == PUBKEY_ALGO_RSA)
                         && get_parameter_uint (para, pKEYUSAGE)
                         && !((get_parameter_uint (para, pKEYUSAGE)
                               & PUBKEY_USAGE_ENC)) );
@@ -3578,7 +3669,7 @@ do_generate_keypair (struct para_data_s *para,
             
           
           if (!opt.batch
-              && (get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_DSA
+              && (get_parameter_algo (para, pKEYTYPE, NULL) == PUBKEY_ALGO_DSA
                   || no_enc_rsa )
               && !get_parameter (para, pSUBKEYTYPE) )
             {
@@ -3596,7 +3687,7 @@ do_generate_keypair (struct para_data_s *para,
         log_error ("key generation failed: %s\n", g10_errstr(rc) );
       else
         tty_printf (_("Key generation failed: %s\n"), g10_errstr(rc) );
-      write_status_error (card? "card_key_generate":"key_generate", rc);
+      write_status_errcode (card? "card_key_generate":"key_generate", rc);
       print_status_key_not_created ( get_parameter_value (para, pHANDLE) );
     }
   else
@@ -4029,7 +4120,7 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary,
       log_error (_("storing key onto card failed: %s\n"), g10_errstr (rc));
       free_secret_key (sk_unprotected);
       free_secret_key (sk_protected);
-      write_status_error ("save_key_to_card", rc);
+      write_status_errcode ("save_key_to_card", rc);
       return rc;
     }
 
@@ -4100,7 +4191,7 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary,
         char *fprbuf, *p;
        
         iobuf_close (fp);
-        iobuf_ioctl (NULL, 2, 0, (char*)fname);
+        iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname);
         log_info (_("NOTE: backup of card key saved to `%s'\n"), fname);
 
         fingerprint_from_sk (sk, array, &n);