* keygen.c (gen_card_key): Add optional argument to return a pointer
[gnupg.git] / g10 / keygen.c
index d2348c0..d240856 100644 (file)
@@ -1,6 +1,6 @@
 /* keygen.c - generate a key pair
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- *               2005 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ *               2006 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -122,6 +122,7 @@ static void do_generate_keypair( struct para_data_s *para,
 static int  write_keyblock( IOBUF out, KBNODE node );
 static int gen_card_key (int algo, int keyno, int is_primary,
                          KBNODE pub_root, KBNODE sec_root,
+                        PKT_secret_key **ret_sk,
                          u32 expireval, struct para_data_s *para);
 static int gen_card_key_with_backup (int algo, int keyno, int is_primary,
                                      KBNODE pub_root, KBNODE sec_root,
@@ -221,7 +222,7 @@ keygen_add_key_expire( PKT_signature *sig, void *opaque )
         if(pk->expiredate > pk->timestamp)
          u= pk->expiredate - pk->timestamp;
        else
-         u= 0;
+         u= 1;
 
        buf[0] = (u >> 24) & 0xff;
        buf[1] = (u >> 16) & 0xff;
@@ -530,8 +531,8 @@ PKT_user_id *keygen_get_std_prefs(void)
   uid->prefs[j].type=PREFTYPE_NONE;
   uid->prefs[j].value=0;
 
-  uid->mdc_feature=mdc_available;
-  uid->ks_modify=ks_modify;
+  uid->flags.mdc=mdc_available;
+  uid->flags.ks_modify=ks_modify;
 
   return uid;
 }
@@ -690,6 +691,55 @@ keygen_add_keyserver_url(PKT_signature *sig, void *opaque)
 }
 
 int
+keygen_add_notations(PKT_signature *sig,void *opaque)
+{
+  struct notation *notation;
+
+  /* We always start clean */
+  delete_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION);
+  delete_sig_subpkt(sig->unhashed,SIGSUBPKT_NOTATION);
+  sig->flags.notation=0;
+
+  for(notation=opaque;notation;notation=notation->next)
+    if(!notation->flags.ignore)
+      {
+       unsigned char *buf;
+       unsigned int n1,n2;
+
+       n1=strlen(notation->name);
+       if(notation->altvalue)
+         n2=strlen(notation->altvalue);
+       else if(notation->bdat)
+         n2=notation->blen;
+       else
+         n2=strlen(notation->value);
+
+       buf = xmalloc( 8 + n1 + n2 );
+
+       /* human readable or not */
+       buf[0] = notation->bdat?0:0x80;
+       buf[1] = buf[2] = buf[3] = 0;
+       buf[4] = n1 >> 8;
+       buf[5] = n1;
+       buf[6] = n2 >> 8;
+       buf[7] = n2;
+       memcpy(buf+8, notation->name, n1 );
+       if(notation->altvalue)
+         memcpy(buf+8+n1, notation->altvalue, n2 );
+       else if(notation->bdat)
+         memcpy(buf+8+n1, notation->bdat, n2 );
+       else
+         memcpy(buf+8+n1, notation->value, n2 );
+       build_sig_subpkt( sig, SIGSUBPKT_NOTATION |
+                         (notation->flags.critical?SIGSUBPKT_FLAG_CRITICAL:0),
+                         buf, 8+n1+n2 );
+       xfree(buf);
+      }
+
+  return 0;
+}
+
+int
 keygen_add_revkey(PKT_signature *sig, void *opaque)
 {
   struct revocation_key *revkey=opaque;
@@ -888,7 +938,6 @@ write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk,
     return rc;
 }
 
-/* sub_sk is currently unused (reserved for backsigs) */
 static int
 write_keybinding( KBNODE root, KBNODE pub_root,
                  PKT_secret_key *pri_sk, PKT_secret_key *sub_sk,
@@ -1040,30 +1089,65 @@ gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
     PKT_public_key *pk;
     MPI skey[5];
     MPI *factors;
+    unsigned int qbits;
 
-    if( nbits > 1024 || nbits < 512 ) {
+    if( nbits < 512 || (!opt.flags.dsa2 && nbits > 1024))
+      {
        nbits = 1024;
        log_info(_("keysize invalid; using %u bits\n"), nbits );
-    }
+      }
+    else if(nbits>3072)
+      {
+       nbits = 3072;
+       log_info(_("keysize invalid; using %u bits\n"), nbits );
+      }
 
-    if( (nbits % 64) ) {
+    if(nbits % 64)
+      {
        nbits = ((nbits + 63) / 64) * 64;
        log_info(_("keysize rounded up to %u bits\n"), nbits );
-    }
+      }
 
-    rc = pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors );
-    if( rc ) {
-       log_error("pubkey_generate failed: %s\n", g10_errstr(rc) );
+    /*
+      Figure out a q size based on the key size.  FIPS 180-3 says:
+
+      L = 1024, N = 160
+      L = 2048, N = 224
+      L = 2048, N = 256
+      L = 3072, N = 256
+
+      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
+      but less than 2048, and 160 for 1024 (DSA1).
+    */
+
+    if(nbits>2048)
+      qbits=256;
+    else if(nbits>1024)
+      qbits=224;
+    else
+      qbits=160;
+
+    if(qbits!=160)
+      log_info("WARNING: some OpenPGP programs can't"
+              " handle a DSA key with this digest size\n");
+
+    rc = dsa2_generate( PUBKEY_ALGO_DSA, nbits, qbits, skey, &factors );
+    if( rc )
+      {
+       log_error("dsa2_generate failed: %s\n", g10_errstr(rc) );
        return rc;
-    }
+      }
 
     sk = xmalloc_clear( sizeof *sk );
     pk = xmalloc_clear( sizeof *pk );
     sk->timestamp = pk->timestamp = make_timestamp();
     sk->version = pk->version = 4;
-    if( expireval ) {
-       sk->expiredate = pk->expiredate = sk->timestamp + expireval;
-    }
+    if( expireval )
+      sk->expiredate = pk->expiredate = sk->timestamp + expireval;
+
     sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA;
                       pk->pkey[0] = mpi_copy( skey[0] );
                       pk->pkey[1] = mpi_copy( skey[1] );
@@ -1413,10 +1497,10 @@ ask_keysize( int algo )
   switch(algo)
     {
     case PUBKEY_ALGO_DSA:
-      if(opt.expert)
+      if(opt.flags.dsa2)
        {
          def=1024;
-         max=1024;
+         max=3072;
        }
       else
        {
@@ -1955,7 +2039,7 @@ parse_parameter_usage (const char *fname,
         }
     }
     r->u.usage = use;
-    return 0;
+    return 1;
 }
 
 static int
@@ -2062,14 +2146,14 @@ 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;
+  int have_user_id=0,err,algo;
 
   /* Check that we have all required parameters. */
   r = get_parameter( para, pKEYTYPE );
   if(r)
     {
-      if(check_pubkey_algo2(get_parameter_algo(para,pKEYTYPE),
-                           PUBKEY_USAGE_SIG))
+      algo=get_parameter_algo(para,pKEYTYPE);
+      if(check_pubkey_algo2(algo,PUBKEY_USAGE_SIG))
        {
          log_error("%s:%d: invalid algorithm\n", fname, r->lnr );
          return -1;
@@ -2081,19 +2165,41 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
       return -1;
     }
 
-  if (parse_parameter_usage (fname, para, pKEYUSAGE))
+  err=parse_parameter_usage (fname, para, pKEYUSAGE);
+  if(err==0)
+    {
+      /* Default to algo capabilities if key-usage is not provided */
+      r=xmalloc_clear(sizeof(*r));
+      r->key=pKEYUSAGE;
+      r->u.usage=openpgp_pk_algo_usage(algo);
+      r->next=para;
+      para=r;
+    }
+  else if(err==-1)
     return -1;
 
   r = get_parameter( para, pSUBKEYTYPE );
   if(r)
     {
-      if(check_pubkey_algo( get_parameter_algo( para, pSUBKEYTYPE)))
+      algo=get_parameter_algo( para, pSUBKEYTYPE);
+      if(check_pubkey_algo(algo))
        {
          log_error("%s:%d: invalid algorithm\n", fname, r->lnr );
          return -1;
        }
 
-      if(parse_parameter_usage (fname, para, pSUBKEYUSAGE))
+      err=parse_parameter_usage (fname, para, pSUBKEYUSAGE);
+      if(err==0)
+       {
+         /* Default to algo capabilities if subkey-usage is not
+            provided */
+         r=xmalloc_clear(sizeof(*r));
+         r->key=pSUBKEYUSAGE;
+         r->u.usage=openpgp_pk_algo_usage(algo);
+         r->next=para;
+         para=r;
+       }
+      else if(err==-1)
        return -1;
     }
 
@@ -2503,12 +2609,12 @@ generate_keypair (const char *fname, const char *card_serialno,
           sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA );
           r->next = para;
           para = r;
-          tty_printf(_("DSA keypair will have %u bits.\n"),1024);
-          r = xmalloc_clear( sizeof *r + 20 );
-          r->key = pKEYLENGTH;
-          strcpy( r->u.value, "1024" );
-          r->next = para;
-          para = r;
+         nbits = ask_keysize( PUBKEY_ALGO_DSA );
+         r = xmalloc_clear( sizeof *r + 20 );
+         r->key = pKEYLENGTH;
+         sprintf( r->u.value, "%u", nbits);
+         r->next = para;
+         para = r;
           r = xmalloc_clear( sizeof *r + 20 );
           r->key = pKEYUSAGE;
           strcpy( r->u.value, "sign" );
@@ -2548,7 +2654,7 @@ generate_keypair (const char *fname, const char *card_serialno,
             }
            
         }
-       
+
       nbits = ask_keysize( algo );
       r = xmalloc_clear( sizeof *r + 20 );
       r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
@@ -2802,7 +2908,7 @@ do_generate_keypair( struct para_data_s *para,
       }
     else
       {
-        rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root,
+        rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root, NULL,
                            get_parameter_u32 (para, pKEYEXPIRE), para);
         if (!rc)
           {
@@ -2838,7 +2944,7 @@ do_generate_keypair( struct para_data_s *para,
 
     if (!rc && card && get_parameter (para, pAUTHKEYTYPE))
       {
-        rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root,
+        rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, NULL,
                            get_parameter_u32 (para, pKEYEXPIRE), para);
         
         if (!rc)
@@ -2874,6 +2980,7 @@ do_generate_keypair( struct para_data_s *para,
               }
             else
               rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root,
+                                NULL,
                                  get_parameter_u32 (para, pKEYEXPIRE), para);
           }
 
@@ -3098,7 +3205,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
     }
 
     rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
-                                     dek, s2k, &sub_sk, expire, 1 );
+                   dek, s2k, &sub_sk, expire, 1 );
     if( !rc )
        rc = write_keybinding(pub_keyblock, pub_keyblock, pri_sk, sub_sk, use);
     if( !rc )
@@ -3132,7 +3239,7 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
 {
   int okay=0, rc=0;
   KBNODE node;
-  PKT_secret_key *pri_sk = NULL;
+  PKT_secret_key *pri_sk = NULL, *sub_sk;
   int algo;
   unsigned int use;
   u32 expire;
@@ -3212,11 +3319,12 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
 
   if (passphrase)
     set_next_passphrase (passphrase);
-  rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock, expire, para);
+  rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock,
+                    &sub_sk, expire, para);
   if (!rc)
-    rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, NULL, use);
+    rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk, use);
   if (!rc)
-    rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, NULL, use);
+    rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk, use);
   if (!rc)
     {
       okay = 1;
@@ -3263,7 +3371,7 @@ write_keyblock( IOBUF out, KBNODE node )
 
 static int
 gen_card_key (int algo, int keyno, int is_primary,
-              KBNODE pub_root, KBNODE sec_root,
+              KBNODE pub_root, KBNODE sec_root, PKT_secret_key **ret_sk,
               u32 expireval, struct para_data_s *para)
 {
 #ifdef ENABLE_CARD_SUPPORT
@@ -3324,6 +3432,9 @@ gen_card_key (int algo, int keyno, int is_primary,
         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;