[svn] GnuPG - r5312 - trunk/g10

svn author wk cvs at cvs.gnupg.org
Tue Apr 20 19:57:51 CEST 2010


Author: wk
Date: 2010-04-20 19:57:50 +0200 (Tue, 20 Apr 2010)
New Revision: 5312

Modified:
   trunk/g10/ChangeLog
   trunk/g10/call-agent.c
   trunk/g10/call-agent.h
   trunk/g10/card-util.c
   trunk/g10/export.c
   trunk/g10/getkey.c
   trunk/g10/gpg.h
   trunk/g10/gpgv.c
   trunk/g10/keydb.h
   trunk/g10/keyedit.c
   trunk/g10/keygen.c
   trunk/g10/keyid.c
   trunk/g10/keylist.c
   trunk/g10/main.h
   trunk/g10/packet.h
   trunk/g10/pkglue.c
   trunk/g10/pkglue.h
   trunk/g10/pubkey-enc.c
   trunk/g10/revoke.c
   trunk/g10/seckey-cert.c
   trunk/g10/seskey.c
   trunk/g10/sig-check.c
   trunk/g10/sign.c
Log:
Generating an OpenPGP key cia gpg-agent basically works.


[The diff below has been truncated]

Modified: trunk/g10/ChangeLog
===================================================================
--- trunk/g10/ChangeLog	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/ChangeLog	2010-04-20 17:57:50 UTC (rev 5312)
@@ -1,3 +1,38 @@
+2010-04-20  Werner Koch  <wk at g10code.com>
+
+	* keylist.c (list_keyblock_colon): Print the keygrip.
+
+	* sign.c (do_sign): Call the agent to create the signature.
+	(mpi_from_sexp): New.
+	* keyid.c (keygrip_from_pk, hexkeygrip_from_pk): New.
+	* call-agent.c (agent_pksign): New.
+	* pkglue.c (pk_sign): Remove.
+
+	* keygen.c (generate_keypair): Do not ask for a passphrase.
+
+2010-04-15  Werner Koch  <wk at g10code.com>
+
+	* keygen.c (gen_dsa, gen_elg, gen_rsa): Remove args SEC_ROOT, DEK,
+	S2K and RET_SK.  Change to use the gpg-agent based key generation.
+	Factor common code out to ...
+	(common_gen): New.
+	(do_create): Remove args SEC_ROOT, DEK, S2K and RET_SK.
+	(do_generate_keypair, write_selfsigs, write_direct_sig)
+	(write_keybinding, make_backsig): Adjust for above changes.
+	(generate_subkeypair): Remove arg SEC_KEYBLOCK.
+	(genhelp_protect, genhelp_factors): Remove.
+	(get_parameter_dek, get_parameter_s2k): Remove.
+
+	* call-agent.c (start_agent): Add dummy arg CTRL.
+	(agent_havekey, keyinfo_status_cb, agent_get_keyinfo)
+	(agent_genkey): New.
+
+	* seckey-cert.c (check_secret_key): Remove
+	(is_secret_key_protected): Take a public key as arg.
+	(protect_secret_key): Remove.
+
+	* seskey.c (encode_md_value): Remove SK arg.
+
 2010-04-14  Werner Koch  <wk at g10code.com>
 
 	* cpr.c (myread) [W32CE]: Do not use raise.

Modified: trunk/g10/call-agent.c
===================================================================
--- trunk/g10/call-agent.c	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/call-agent.c	2010-04-20 17:57:50 UTC (rev 5312)
@@ -1,6 +1,6 @@
 /* call-agent.c - Divert GPG operations to the agent.
- * Copyright (C) 2001, 2002, 2003, 2006, 2007, 
- *               2008, 2009 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
+ *               2010 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -69,14 +69,15 @@
   size_t keydatalen;
 };
 
-struct genkey_parm_s 
+struct genkey_parm_s
 {
+  ctrl_t ctrl;
   assuan_context_t ctx;
-  const char *sexp;
-  size_t sexplen;
+  const char *keyparms;
 };
 
 
+
 static gpg_error_t learn_status_cb (void *opaque, const char *line);
 
 
@@ -107,10 +108,12 @@
 /* Try to connect to the agent via socket or fork it off and work by
    pipes.  Handle the server's initial greeting */
 static int
-start_agent (int for_card)
+start_agent (ctrl_t ctrl, int for_card)
 {
   int rc;
 
+  (void)ctrl;  /* Not yet used.  */
+
   /* Fixme: We need a context for each thread or serialize the access
      to the agent. */
   if (agent_ctx)
@@ -486,7 +489,7 @@
 {
   int rc;
 
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (rc)
     return rc;
 
@@ -531,7 +534,7 @@
     return gpg_error (GPG_ERR_TOO_LARGE);
   stpcpy (stpcpy (line, "SCD GETATTR "), name); 
 
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (rc)
     return rc;
 
@@ -581,7 +584,7 @@
     }
   *p = 0;
 
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (!rc)
     {
       rc = assuan_transact (agent_ctx, line, NULL, NULL, 
@@ -623,7 +626,7 @@
   char line[ASSUAN_LINELENGTH];
   struct writecert_parm_s parms;
 
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (rc)
     return rc;
 
@@ -673,7 +676,7 @@
 
   (void)serialno;
 
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (rc)
     return rc;
 
@@ -762,7 +765,7 @@
 
   (void)serialno;
 
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (rc)
     return rc;
 
@@ -909,7 +912,7 @@
   *r_buf = NULL;
   *r_buflen = 0;
 
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
       || gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
     rc = 0; /* We check later.  */
@@ -972,7 +975,7 @@
   size_t len;
 
   *r_buf = NULL;
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
       || gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
     rc = 0; /* We check later.  */
@@ -1029,7 +1032,7 @@
   size_t len;
 
   *r_buf = NULL;
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (rc)
     return rc;
 
@@ -1077,7 +1080,7 @@
     reset = "--reset";
   chvno %= 100;
 
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (rc)
     return rc;
 
@@ -1099,7 +1102,7 @@
   int rc;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent (1);
+  rc = start_agent (NULL, 1);
   if (rc)
     return rc;
 
@@ -1146,7 +1149,7 @@
 
   *r_passphrase = NULL;
 
-  rc = start_agent (0);
+  rc = start_agent (NULL, 0);
   if (rc)
     return rc;
 
@@ -1217,7 +1220,7 @@
   if (!cache_id || !*cache_id)
     return 0;
 
-  rc = start_agent (0);
+  rc = start_agent (NULL, 0);
   if (rc)
     return rc;
 
@@ -1237,7 +1240,7 @@
   char *tmp;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent (0);
+  rc = start_agent (NULL, 0);
   if (rc)
     return rc;
 
@@ -1264,7 +1267,7 @@
 
   *r_count = 0;
 
-  err = start_agent (0);
+  err = start_agent (NULL, 0);
   if (err)
     return err;
 
@@ -1289,3 +1292,291 @@
   return err;
 }
 
+
+
+/* Ask the agent whether a secret key with the given keygrip is
+   known.  */
+gpg_error_t
+agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
+{
+  gpg_error_t err;
+  char line[ASSUAN_LINELENGTH];
+
+  err = start_agent (ctrl, 0);
+  if (err)
+    return err;
+
+  if (!hexkeygrip || strlen (hexkeygrip) != 40)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
+  line[DIM(line)-1] = 0;
+
+  err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+  return err;
+}
+
+
+
+static gpg_error_t
+keyinfo_status_cb (void *opaque, const char *line)
+{
+  char **serialno = opaque;
+  const char *s, *s2;
+
+  if (!strncmp (line, "KEYINFO ", 8) && !*serialno)
+    {
+      s = strchr (line+8, ' ');
+      if (s && s[1] == 'T' && s[2] == ' ' && s[3])
+        {
+          s += 3;
+          s2 = strchr (s, ' ');
+          if ( s2 > s )
+            {
+              *serialno = xtrymalloc ((s2 - s)+1);
+              if (*serialno)
+                {
+                  memcpy (*serialno, s, s2 - s);
+                  (*serialno)[s2 - s] = 0;
+                }
+            }
+        }
+    }
+  return 0;
+}
+
+
+/* Return the serial number for a secret key.  If the returned serial
+   number is NULL, the key is not stored on a smartcard.  Caller needs
+   to free R_SERIALNO.  */
+gpg_error_t
+agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
+{
+  gpg_error_t err;
+  char line[ASSUAN_LINELENGTH];
+  char *serialno = NULL;
+
+  *r_serialno = NULL;
+
+  err = start_agent (ctrl, 0);
+  if (err)
+    return err;
+
+  if (!hexkeygrip || strlen (hexkeygrip) != 40)
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  snprintf (line, DIM(line)-1, "KEYINFO %s", hexkeygrip);
+  line[DIM(line)-1] = 0;
+
+  err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
+                         keyinfo_status_cb, &serialno);
+  if (!err && serialno)
+    {
+      /* Sanity check for bad characters.  */
+      if (strpbrk (serialno, ":\n\r"))
+        err = GPG_ERR_INV_VALUE;
+    }
+  if (err)
+    xfree (serialno);
+  else
+    *r_serialno = serialno;
+  return err;
+}
+
+
+
+/* Handle a KEYPARMS inquiry.  Note, we only send the data,
+   assuan_transact takes care of flushing and writing the end */
+static gpg_error_t
+inq_genkey_parms (void *opaque, const char *line)
+{
+  struct genkey_parm_s *parm = opaque; 
+  gpg_error_t err;
+
+  if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8]))
+    {
+      err = assuan_send_data (parm->ctx,
+                              parm->keyparms, strlen (parm->keyparms));
+    }
+  else
+    err = default_inq_cb (parm->ctrl, line);
+
+  return err; 
+}
+
+
+/* Call the agent to generate a new key.  KEYPARMS is the usual
+   S-expression giving the parameters of the key.  gpg-agent passes it
+   gcry_pk_genkey.  */
+gpg_error_t
+agent_genkey (ctrl_t ctrl, const char *keyparms, gcry_sexp_t *r_pubkey)
+{
+  gpg_error_t err;
+  struct genkey_parm_s gk_parm;
+  membuf_t data;
+  size_t len;
+  unsigned char *buf;
+
+  *r_pubkey = NULL;
+  err = start_agent (ctrl, 0);
+  if (err)
+    return err;
+
+  err = assuan_transact (agent_ctx, "RESET", 
+                         NULL, NULL, NULL, NULL, NULL, NULL);
+  if (err)
+    return err;
+
+  init_membuf (&data, 1024);
+  gk_parm.ctrl     = ctrl;
+  gk_parm.ctx      = agent_ctx;
+  gk_parm.keyparms = keyparms;
+  err = assuan_transact (agent_ctx, "GENKEY",
+                         membuf_data_cb, &data, 
+                         inq_genkey_parms, &gk_parm, NULL, NULL);
+  if (err)
+    {
+      xfree (get_membuf (&data, &len));
+      return err;
+    }
+  
+  buf = get_membuf (&data, &len);
+  if (!buf)
+    err = gpg_error_from_syserror ();
+  else
+    {
+      err = gcry_sexp_sscan (r_pubkey, NULL, buf, len);
+      xfree (buf);
+    }
+  return err;
+}
+
+
+
+
+/* FIXME: Call the agent to read the public key part for a given keygrip.  If
+   FROMCARD is true, the key is directly read from the current
+   smartcard. In this case HEXKEYGRIP should be the keyID
+   (e.g. OPENPGP.3). */
+/* int */
+/* agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip, */
+/*                ksba_sexp_t *r_pubkey) */
+/* { */
+/*   int rc; */
+/*   membuf_t data; */
+/*   size_t len; */
+/*   unsigned char *buf; */
+/*   char line[ASSUAN_LINELENGTH]; */
+
+/*   *r_pubkey = NULL; */
+/*   rc = start_agent (ctrl); */
+/*   if (rc) */
+/*     return rc; */
+
+/*   rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL); */
+/*   if (rc) */
+/*     return rc; */
+
+/*   snprintf (line, DIM(line)-1, "%sREADKEY %s", */
+/*             fromcard? "SCD ":"", hexkeygrip); */
+/*   line[DIM(line)-1] = 0; */
+
+/*   init_membuf (&data, 1024); */
+/*   rc = assuan_transact (agent_ctx, line, */
+/*                         membuf_data_cb, &data,  */
+/*                         default_inq_cb, ctrl, NULL, NULL); */
+/*   if (rc) */
+/*     { */
+/*       xfree (get_membuf (&data, &len)); */
+/*       return rc; */
+/*     } */
+/*   buf = get_membuf (&data, &len); */
+/*   if (!buf) */
+/*     return gpg_error (GPG_ERR_ENOMEM); */
+/*   if (!gcry_sexp_canon_len (buf, len, NULL, NULL)) */
+/*     { */
+/*       xfree (buf); */
+/*       return gpg_error (GPG_ERR_INV_SEXP); */
+/*     } */
+/*   *r_pubkey = buf; */
+/*   return 0; */
+/* } */
+
+
+
+/* Call the agent to do a sign operation using the key identified by
+   the hex string KEYGRIP.  DESC is a description of the key to be
+   displayed if the agent needs to ask for the PIN.  DIGEST and
+   DIGESTLEN is the hash value to sign and DIGESTALGO the algorithm id
+   used to compute the digest.  */
+gpg_error_t
+agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
+              unsigned char *digest, size_t digestlen, int digestalgo,
+              gcry_sexp_t *r_sigval)
+{
+  gpg_error_t err;
+  int i;
+  char *p, line[ASSUAN_LINELENGTH];
+  membuf_t data;
+
+  *r_sigval = NULL;
+  err = start_agent (ctrl, 0);
+  if (err)
+    return err;
+
+  if (digestlen*2 + 50 > DIM(line))
+    return gpg_error (GPG_ERR_GENERAL);
+
+  err = assuan_transact (agent_ctx, "RESET",
+                         NULL, NULL, NULL, NULL, NULL, NULL);
+  if (err)
+    return err;
+
+  snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
+  line[DIM(line)-1] = 0;
+  err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+  if (err)
+    return err;
+
+  if (desc)
+    {
+      snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
+      line[DIM(line)-1] = 0;
+      err = assuan_transact (agent_ctx, line,
+                            NULL, NULL, NULL, NULL, NULL, NULL);
+      if (err)
+        return err;
+    }
+
+  snprintf (line, sizeof line, "SETHASH %d ", digestalgo);
+  p = line + strlen (line);
+  for (i=0; i < digestlen ; i++, p += 2 )
+    sprintf (p, "%02X", digest[i]);
+  err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+  if (err)
+    return err;
+
+  init_membuf (&data, 1024);
+  err = assuan_transact (agent_ctx, "PKSIGN",
+                        membuf_data_cb, &data, default_inq_cb, ctrl,
+                        NULL, NULL);
+  if (err)
+    xfree (get_membuf (&data, NULL));
+  else
+    {
+      unsigned char *buf;
+      size_t len;
+
+      buf = get_membuf (&data, &len);
+      if (!buf)
+        err = gpg_error_from_syserror ();
+      else
+        {
+          err = gcry_sexp_sscan (r_sigval, NULL, buf, len);
+          xfree (buf);
+        }
+    }
+  return err;
+}
+
+

Modified: trunk/g10/call-agent.h
===================================================================
--- trunk/g10/call-agent.h	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/call-agent.h	2010-04-20 17:57:50 UTC (rev 5312)
@@ -140,6 +140,24 @@
 /* Return the S2K iteration count as computed by gpg-agent.  */
 gpg_error_t agent_get_s2k_count (unsigned long *r_count);
 
+/* Check whether a secret key with HEXKEYGRIP is available.  */
+gpg_error_t agent_havekey (ctrl_t ctrl, const char *hexkeygrip);
 
+/* Return infos about the secret key with HEXKEYGRIP.  */
+gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
+                               char **r_serialno);
+
+/* Generate a new key.  */
+gpg_error_t agent_genkey (ctrl_t ctrl, const char *keyparms,
+                          gcry_sexp_t *r_pubkey);
+
+/* Create a sigtnature.  */
+gpg_error_t agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
+                          unsigned char *digest, size_t digestlen,
+                          int digestalgo,
+                          gcry_sexp_t *r_sigval);
+
+
+
 #endif /*GNUPG_G10_CALL_AGENT_H*/
 

Modified: trunk/g10/card-util.c
===================================================================
--- trunk/g10/card-util.c	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/card-util.c	2010-04-20 17:57:50 UTC (rev 5312)
@@ -1495,8 +1495,8 @@
          the serialnumber and thus it won't harm.  */
     }
 
-  okay = generate_card_subkeypair (pub_keyblock, sec_keyblock,
-                                   keyno, info.serialno);
+  /* xxx = generate_card_subkeypair (pub_keyblock, sec_keyblock, */
+  /*                                  keyno, info.serialno); */
 
  leave:
   agent_release_card_info (&info);
@@ -1612,17 +1612,18 @@
 	}
       /* We better copy the key before we unprotect it.  */
       copied_sk = sk = copy_secret_key (NULL, sk);
-      rc = check_secret_key (sk, 0);
+      rc = 0/*check_secret_key (sk, 0)*/;
       if (rc)
         goto leave;
     }
 
-  rc = save_unprotected_key_to_card (sk, keyno);
-  if (rc)
-    {
-      log_error (_("error writing key to card: %s\n"), gpg_strerror (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)

Modified: trunk/g10/export.c
===================================================================
--- trunk/g10/export.c	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/export.c	2010-04-20 17:57:50 UTC (rev 5312)
@@ -550,7 +550,7 @@
                       ; /* Card key stub. */
                     else 
                       {
-                        rc = check_secret_key( sk, 0 );
+                        /* rc = check_secret_key( sk, 0 ); */
                       }
                     break;
                   }

Modified: trunk/g10/getkey.c
===================================================================
--- trunk/g10/getkey.c	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/getkey.c	2010-04-20 17:57:50 UTC (rev 5312)
@@ -526,7 +526,7 @@
     {
       /* Check the secret key (this may prompt for a passprase to
        * unlock the secret key.  */
-      rc = check_secret_key (sk, 0);
+      /* rc = check_secret_key (sk, 0); */
     }
 
   return rc;
@@ -1111,8 +1111,8 @@
 
   free_strlist (namelist);
 
-  if (!rc && unprotect)
-    rc = check_secret_key (sk, 0);
+  /* if (!rc && unprotect) */
+  /*   rc = check_secret_key (sk, 0); */
 
   return rc;
 }

Modified: trunk/g10/gpg.h
===================================================================
--- trunk/g10/gpg.h	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/gpg.h	2010-04-20 17:57:50 UTC (rev 5312)
@@ -108,7 +108,7 @@
 #define G10ERR_RENAME_FILE     GPG_ERR_RENAME_FILE      
 #define G10ERR_RESOURCE_LIMIT  GPG_ERR_RESOURCE_LIMIT   
 #define G10ERR_SIG_CLASS       GPG_ERR_SIG_CLASS        
-#define G10ERR_TIME_CONFLICT   GPG_ERR_TIME_CONFLICT    
+#define G10ERR_TIME_CONFLICT   GPG_ERR_TIME_CONFLICT 
 #define G10ERR_TRUSTDB         GPG_ERR_TRUSTDB          
 #define G10ERR_UNEXPECTED      GPG_ERR_UNEXPECTED       
 #define G10ERR_UNKNOWN_PACKET  GPG_ERR_UNKNOWN_PACKET   

Modified: trunk/g10/gpgv.c
===================================================================
--- trunk/g10/gpgv.c	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/gpgv.c	2010-04-20 17:57:50 UTC (rev 5312)
@@ -399,9 +399,9 @@
  * We don't use secret keys, but getkey.c links to this
  */
 int
-check_secret_key (PKT_secret_key *sk, int n)
+check_secret_key (PKT_public_key *pk, int n)
 {
-  (void)sk;
+  (void)pk;
   (void)n;
   return G10ERR_GENERAL;
 }

Modified: trunk/g10/keydb.h
===================================================================
--- trunk/g10/keydb.h	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/keydb.h	2010-04-20 17:57:50 UTC (rev 5312)
@@ -286,7 +286,10 @@
 byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
 char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
                                 PKT_secret_key *sk);
+gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array);
+gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);
 
+
 /*-- kbnode.c --*/
 KBNODE new_kbnode( PACKET *pkt );
 KBNODE clone_kbnode( KBNODE node );

Modified: trunk/g10/keyedit.c
===================================================================
--- trunk/g10/keyedit.c	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/keyedit.c	2010-04-20 17:57:50 UTC (rev 5312)
@@ -1164,9 +1164,9 @@
             keyid_from_sk (sk, keyid);
             passphrase_clear_cache (keyid, NULL, 0);
 
-	    rc = check_secret_key( sk, 0 );
-	    if( !rc )
-		passphrase = get_last_passphrase();
+	    /* rc = check_secret_key( sk, 0 ); */
+	    /* if( !rc ) */
+	    /*     passphrase = get_last_passphrase(); */
 	}
 	break;
     }
@@ -1179,9 +1179,9 @@
                    && (subsk->protect.s2k.mode == 1001 
                        || subsk->protect.s2k.mode == 1002))) {
                 set_next_passphrase( passphrase );
-                rc = check_secret_key( subsk, 0 );
-                if( !rc && !passphrase )
-                    passphrase = get_last_passphrase();
+                /* rc = check_secret_key( subsk, 0 ); */
+                /* if( !rc && !passphrase ) */
+                /*     passphrase = get_last_passphrase(); */
             }
 	}
     }
@@ -1227,7 +1227,9 @@
 		if( !no_primary_secrets ) {
 		    sk->protect.algo = dek->algo;
 		    sk->protect.s2k = *s2k;
-		    rc = protect_secret_key( sk, dek );
+#warning fixme
+                    rc = 0;
+		    /* rc = protect_secret_key( sk, dek ); */
 		}
 		for(node=keyblock; !rc && node; node = node->next ) {
 		    if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
@@ -1237,7 +1239,9 @@
                                    || subsk->protect.s2k.mode == 1002))) {
                             subsk->protect.algo = dek->algo;
                             subsk->protect.s2k = *s2k;
-                            rc = protect_secret_key( subsk, dek );
+#warning fixme
+                            rc = 0;
+                            /* rc = protect_secret_key( subsk, dek ); */
                         }
 		    }
 		}
@@ -1892,12 +1896,13 @@
 	    break;
 
 	  case cmdADDKEY:
-	    if( generate_subkeypair( keyblock, sec_keyblock ) ) {
+	    if (!generate_subkeypair (keyblock))
+              {
 		redisplay = 1;
 		sec_modified = modified = 1;
 		merge_keys_and_selfsig( sec_keyblock );
 		merge_keys_and_selfsig( keyblock );
-	    }
+              }
 	    break;
 
 #ifdef ENABLE_CARD_SUPPORT
@@ -2018,8 +2023,8 @@
                     if (sk->protect.s2k.mode == 1002)
                       tty_printf (_("Secret parts of key"
                                     " are stored on-card.\n"));
-                    else
-                      check_secret_key (sk, 0);
+                    /* else */
+                    /*   check_secret_key (sk, 0); */
                   }
               }
             else /* Store it.  */

Modified: trunk/g10/keygen.c
===================================================================
--- trunk/g10/keygen.c	2010-04-20 13:47:12 UTC (rev 5311)
+++ trunk/g10/keygen.c	2010-04-20 17:57:50 UTC (rev 5312)
@@ -132,15 +132,12 @@
 
 static void do_generate_keypair( struct para_data_s *para,
 				 struct output_control_s *outctrl, int card );
-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 *timestamp,
-                         u32 expireval, struct para_data_s *para);
+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 int gen_card_key_with_backup (int algo, int keyno, int is_primary,
-                                     KBNODE pub_root, KBNODE sec_root,
-                                     u32 timestamp,
+                                     kbnode_t pub_root, u32 timestamp,
                                      u32 expireval, struct para_data_s *para,
                                      const char *backup_dir);
 
@@ -227,43 +224,46 @@
 
 
 int
-keygen_add_key_expire( PKT_signature *sig, void *opaque )
+keygen_add_key_expire (PKT_signature *sig, void *opaque)
 {
-    PKT_public_key *pk = opaque;
-    byte buf[8];
-    u32  u;
-
-    if( pk->expiredate ) {
-        if(pk->expiredate > pk->timestamp)
-	  u= pk->expiredate - pk->timestamp;
-	else
-	  u= 1;
-
-	buf[0] = (u >> 24) & 0xff;
-	buf[1] = (u >> 16) & 0xff;
-	buf[2] = (u >>	8) & 0xff;
-	buf[3] = u & 0xff;
-	build_sig_subpkt( sig, SIGSUBPKT_KEY_EXPIRE, buf, 4 );
+  PKT_public_key *pk = opaque;
+  byte buf[8];
+  u32  u;
+  
+  if (pk->expiredate)
+    {
+      if (pk->expiredate > pk->timestamp)
+        u = pk->expiredate - pk->timestamp;
+      else
+        u = 1;
+      
+      buf[0] = (u >> 24) & 0xff;
+      buf[1] = (u >> 16) & 0xff;
+      buf[2] = (u >>	8) & 0xff;
+      buf[3] = u & 0xff;
+      build_sig_subpkt (sig, SIGSUBPKT_KEY_EXPIRE, buf, 4);
     }
-    else
-      {
-	/* Make sure we don't leave a key expiration subpacket lying
-	   around */
-	delete_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE);
-      }
+  else
+    {
+      /* Make sure we don't leave a key expiration subpacket lying
+         around */
+      delete_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE);
+    }
 
-    return 0;
+  return 0;
 }
 
+
 static int
 keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque)
 {
-    struct opaque_data_usage_and_pk *oduap = opaque;
-
-    do_add_key_flags (sig, oduap->usage);
-    return keygen_add_key_expire (sig, oduap->pk);
+  struct opaque_data_usage_and_pk *oduap = opaque;
+  
+  do_add_key_flags (sig, oduap->usage);
+  return keygen_add_key_expire (sig, oduap->pk);
 }
 
+
 static int
 set_one_pref (int val, int type, const char *item, byte *buf, int *nbuf)
 {
@@ -697,19 +697,18 @@
 /****************
  * Add preference to the self signature packet.
  * This is only called for packets with version > 3.
-
  */
 int
-keygen_add_std_prefs( PKT_signature *sig, void *opaque )
+keygen_add_std_prefs (PKT_signature *sig, void *opaque)
 {
-    PKT_public_key *pk = opaque;
-
-    do_add_key_flags (sig, pk->pubkey_usage);
-    keygen_add_key_expire( sig, opaque );
-    keygen_upd_std_prefs (sig, opaque);
-    keygen_add_keyserver_url(sig,NULL);
-
-    return 0;
+  PKT_public_key *pk = opaque;
+  
+  do_add_key_flags (sig, pk->pubkey_usage);
+  keygen_add_key_expire (sig, opaque );
+  keygen_upd_std_prefs (sig, opaque);
+  keygen_add_keyserver_url (sig,NULL);
+  
+  return 0;
 }
 
 int
@@ -778,23 +777,23 @@
 }
 
 int
-keygen_add_revkey(PKT_signature *sig, void *opaque)
+keygen_add_revkey (PKT_signature *sig, void *opaque)
 {
-  struct revocation_key *revkey=opaque;
+  struct revocation_key *revkey = opaque;
   byte buf[2+MAX_FINGERPRINT_LEN];
 
-  buf[0]=revkey->class;
-  buf[1]=revkey->algid;
-  memcpy(&buf[2],revkey->fpr,MAX_FINGERPRINT_LEN);
+  buf[0] = revkey->class;
+  buf[1] = revkey->algid;
+  memcpy (&buf[2], revkey->fpr, MAX_FINGERPRINT_LEN);
 
-  build_sig_subpkt(sig,SIGSUBPKT_REV_KEY,buf,2+MAX_FINGERPRINT_LEN);
+  build_sig_subpkt (sig, SIGSUBPKT_REV_KEY, buf, 2+MAX_FINGERPRINT_LEN);
 
-  /* All sigs with revocation keys set are nonrevocable */
-  sig->flags.revocable=0;
+  /* All sigs with revocation keys set are nonrevocable.  */
+  sig->flags.revocable = 0;
   buf[0] = 0;
-  build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 );
+  build_sig_subpkt (sig, SIGSUBPKT_REVOCABLE, buf, 1);
 
-  parse_revkeys(sig);
+  parse_revkeys (sig);
 
   return 0;
 }
@@ -803,115 +802,118 @@
 
 /* Create a back-signature.  If TIMESTAMP is not NULL, use it for the
    signature creation time.  */
-int
-make_backsig (PKT_signature *sig,PKT_public_key *pk,
-              PKT_public_key *sub_pk,PKT_secret_key *sub_sk,
+gpg_error_t
+make_backsig (PKT_signature *sig, PKT_public_key *pk,
+              PKT_public_key *sub_pk, PKT_public_key *sub_psk,
               u32 timestamp)
 {
+  gpg_error_t err;
   PKT_signature *backsig;
-  int rc;
 
-  cache_public_key(sub_pk);
+  cache_public_key (sub_pk);
 
-  rc = make_keysig_packet (&backsig, pk, NULL, sub_pk, sub_sk, 0x19,
-                           0, 0, timestamp, 0, NULL, NULL);
-  if(rc)
-    log_error("make_keysig_packet failed for backsig: %s\n",g10_errstr(rc));
+  err = make_keysig_packet (&backsig, pk, NULL, sub_pk, sub_psk, 0x19,
+                            0, 0, timestamp, 0, NULL, NULL);
+  if (err)
+    log_error ("make_keysig_packet failed for backsig: %s\n", g10_errstr(err));
   else
     {
       /* Get it into a binary packed form. */
-      IOBUF backsig_out=iobuf_temp();
+      IOBUF backsig_out = iobuf_temp();
       PACKET backsig_pkt;
  
-      init_packet(&backsig_pkt);
-      backsig_pkt.pkttype=PKT_SIGNATURE;
-      backsig_pkt.pkt.signature=backsig;
-      rc=build_packet(backsig_out,&backsig_pkt);
-      free_packet(&backsig_pkt);
-      if(rc)
-	log_error("build_packet failed for backsig: %s\n",g10_errstr(rc));
+      init_packet (&backsig_pkt);
+      backsig_pkt.pkttype = PKT_SIGNATURE;
+      backsig_pkt.pkt.signature = backsig;
+      err = build_packet (backsig_out, &backsig_pkt);
+      free_packet (&backsig_pkt);
+      if (err)
+	log_error ("build_packet failed for backsig: %s\n", g10_errstr(err));
       else
 	{
-	  size_t pktlen=0;
-	  byte *buf=iobuf_get_temp_buffer(backsig_out);
+	  size_t pktlen = 0;
+	  byte *buf = iobuf_get_temp_buffer (backsig_out);
  
-	  /* Remove the packet header */
+	  /* Remove the packet header. */
 	  if(buf[0]&0x40)
 	    {
-	      if(buf[1]<192)
+	      if (buf[1] < 192)
 		{
-		  pktlen=buf[1];
-		  buf+=2;
-		}
-	      else if(buf[1]<224)
+		  pktlen = buf[1];
+		  buf += 2; 
+		} 
+	      else if(buf[1] < 224)
 		{
-		  pktlen=(buf[1]-192)*256;
-		  pktlen+=buf[2]+192;
-		  buf+=3;
+		  pktlen = (buf[1]-192)*256;
+		  pktlen += buf[2]+192;
+		  buf += 3;
 		}
-	      else if(buf[1]==255)
+	      else if (buf[1] == 255)
 		{
-		  pktlen =buf[2] << 24;
-		  pktlen|=buf[3] << 16;
-		  pktlen|=buf[4] << 8;
-		  pktlen|=buf[5];
-		  buf+=6;
+		  pktlen  = buf[2] << 24;
+		  pktlen |= buf[3] << 16;
+		  pktlen |= buf[4] << 8;
+		  pktlen |= buf[5];
+		  buf += 6;
 		}
 	      else
-		BUG();
+		BUG ();
 	    }
 	  else
 	    {
-	      int mark=1;
+	      int mark = 1;
  
-	      switch(buf[0]&3)
+	      switch (buf[0]&3)
 		{
 		case 3:
-		  BUG();
+		  BUG ();
 		  break;
  
 		case 2:
-		  pktlen =buf[mark++] << 24;
-		  pktlen|=buf[mark++] << 16;
+		  pktlen  = buf[mark++] << 24;
+		  pktlen |= buf[mark++] << 16;
  
 		case 1:
-		  pktlen|=buf[mark++] << 8;
+		  pktlen |= buf[mark++] << 8;
  
 		case 0:
-		  pktlen|=buf[mark++];
+		  pktlen |= buf[mark++];
 		}
  
-	      buf+=mark;
+	      buf += mark;
 	    }
  
 	  /* Now make the binary blob into a subpacket.  */
-	  build_sig_subpkt(sig,SIGSUBPKT_SIGNATURE,buf,pktlen);
+	  build_sig_subpkt (sig, SIGSUBPKT_SIGNATURE, buf, pktlen);
 
-	  iobuf_close(backsig_out);
+	  iobuf_close (backsig_out);
 	}
     }
- 
-  return rc;
+  
+  return err;
 }
 
 
-static int
-write_direct_sig (KBNODE root, KBNODE pub_root, PKT_secret_key *sk,
-		  struct revocation_key *revkey, u32 timestamp)
+/* Write a direct key signature to the first key in ROOT using the key
+   PSK.  REVKEY is describes the direct key signature and TIMESTAMP is
+   the timestamp to set on the signature.  */
+static gpg_error_t
+write_direct_sig (KBNODE root, PKT_public_key *psk,
+                  struct revocation_key *revkey, u32 timestamp)
 {
+  gpg_error_t err;
   PACKET *pkt;
   PKT_signature *sig;
-  int rc=0;
   KBNODE node;
   PKT_public_key *pk;
 
-  if( opt.verbose )
-    log_info(_("writing direct signature\n"));
+  if (opt.verbose)
+    log_info (_("writing direct signature\n"));
 
   /* Get the pk packet from the pub_tree. */
-  node = find_kbnode( pub_root, PKT_PUBLIC_KEY );
-  if( !node )
-    BUG();
+  node = find_kbnode (root, PKT_PUBLIC_KEY);
+  if (!node)
+    BUG ();
   pk = node->pkt->pkt.public_key;
 
   /* We have to cache the key, so that the verification of the
@@ -919,48 +921,54 @@
   cache_public_key (pk);
 
   /* Make the signature.  */
-  rc = make_keysig_packet (&sig,pk,NULL,NULL,sk,0x1F,
-                           0, 0, timestamp, 0,
-                           keygen_add_revkey, revkey);
-  if( rc )
+  err = make_keysig_packet (&sig, pk, NULL,NULL, psk, 0x1F,
+                            0, 0, timestamp, 0,
+                            keygen_add_revkey, revkey);
+  if (err)
     {
-      log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
-      return rc;
+      log_error ("make_keysig_packet failed: %s\n", g10_errstr (err) );
+      return err;
     }
   
-  pkt = xmalloc_clear( sizeof *pkt );
+  pkt = xmalloc_clear (sizeof *pkt);
   pkt->pkttype = PKT_SIGNATURE;
   pkt->pkt.signature = sig;
-  add_kbnode( root, new_kbnode( pkt ) );
-  return rc;
+  add_kbnode (root, new_kbnode (pkt));
+  return err;
 }
 
 
-static int
-write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk,
-		unsigned int use, u32 timestamp )
+
+/* Write a self-signature to the first user id in ROOT using the key
+   PSK.  USE and TIMESTAMP give the extra data we need for the
+   signature.  */
+static gpg_error_t
+write_selfsigs (KBNODE root, PKT_public_key *psk,
+		unsigned int use, u32 timestamp)
 {
+  gpg_error_t err;
   PACKET *pkt;
   PKT_signature *sig;
   PKT_user_id *uid;
-  int rc=0;
   KBNODE node;
   PKT_public_key *pk;
 
-  if( opt.verbose )
-    log_info(_("writing self signature\n"));
+  if (opt.verbose)
+    log_info (_("writing self signature\n"));
 
   /* Get the uid packet from the list. */
-  node = find_kbnode( pub_root, PKT_USER_ID );
-  if( !node )
+  node = find_kbnode (root, PKT_USER_ID);
+  if (!node)
     BUG(); /* No user id packet in tree.  */
   uid = node->pkt->pkt.user_id;
 
   /* Get the pk packet from the pub_tree. */
-  node = find_kbnode( pub_root, PKT_PUBLIC_KEY );
-  if( !node )
+  node = find_kbnode (root, PKT_PUBLIC_KEY);
+  if (!node)
     BUG();
   pk = node->pkt->pkt.public_key;
+
+  /* The usage has not yet been set - do it now. */
   pk->pubkey_usage = use;
  
   /* We have to cache the key, so that the verification of the
@@ -968,48 +976,45 @@
   cache_public_key (pk);
 
   /* Make the signature.  */
-  rc = make_keysig_packet (&sig, pk, uid, NULL, sk, 0x13,
-                           0, 0, timestamp, 0,
-                           keygen_add_std_prefs, pk);
-  if( rc ) 
+  err = make_keysig_packet (&sig, pk, uid, NULL, psk, 0x13,
+                            0, 0, timestamp, 0,
+                            keygen_add_std_prefs, pk);
+  if (err) 
     {
-      log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
-      return rc;
+      log_error ("make_keysig_packet failed: %s\n", g10_errstr (err));
+      return err;
     }
 
-  pkt = xmalloc_clear( sizeof *pkt );
+  pkt = xmalloc_clear (sizeof *pkt);
   pkt->pkttype = PKT_SIGNATURE;
   pkt->pkt.signature = sig;
-  add_kbnode( sec_root, new_kbnode( pkt ) );
+  add_kbnode (root, new_kbnode (pkt));
 
-  pkt = xmalloc_clear( sizeof *pkt );
-  pkt->pkttype = PKT_SIGNATURE;
-  pkt->pkt.signature = copy_signature(NULL,sig);
-  add_kbnode( pub_root, new_kbnode( pkt ) );
-  return rc;
+  return err;
 }
 
 
 /* Write the key binding signature.  If TIMESTAMP is not NULL use the
-   signature creation times.  */
+   signature creation time.  PRI_PSK is the key use for signing.
+   SUB_PSK is a key used to create a back-signature; that one is only
+   used if USE has the PUBKEY_USAGE_SIG capability.  */
 static int
-write_keybinding (KBNODE root, KBNODE pub_root,
-		  PKT_secret_key *pri_sk, PKT_secret_key *sub_sk,
+write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk,
                   unsigned int use, u32 timestamp)
 {
+  gpg_error_t err;
   PACKET *pkt;
   PKT_signature *sig;
-  int rc=0;
   KBNODE node;
   PKT_public_key *pri_pk, *sub_pk;
   struct opaque_data_usage_and_pk oduap;
 
-  if ( opt.verbose )
+  if (opt.verbose)
     log_info(_("writing key binding signature\n"));
 
-  /* Get the pk packet from the pub_tree.  */
-  node = find_kbnode ( pub_root, PKT_PUBLIC_KEY );
-  if ( !node )
+  /* Get the primary pk packet from the tree.  */
+  node = find_kbnode (root, PKT_PUBLIC_KEY);
+  if (!node)
     BUG();
   pri_pk = node->pkt->pkt.public_key;
 
@@ -1019,9 +1024,9 @@
  
   /* Find the last subkey. */
   sub_pk = NULL;
-  for (node=pub_root; node; node = node->next ) 
+  for (node = root; node; node = node->next ) 
     {
-      if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+      if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
         sub_pk = node->pkt->pkt.public_key;
     }
   if (!sub_pk)
@@ -1030,28 +1035,28 @@
   /* Make the signature.  */
   oduap.usage = use;
   oduap.pk = sub_pk;
-  rc = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_sk, 0x18, 
-                           0, 0, timestamp, 0,
-                           keygen_add_key_flags_and_expire, &oduap );
-  if (rc) 
+  err = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_psk, 0x18, 
+                            0, 0, timestamp, 0,
+                            keygen_add_key_flags_and_expire, &oduap);
+  if (err) 
     {
-      log_error ("make_keysig_packet failed: %s\n", g10_errstr(rc) );
-      return rc;
+      log_error ("make_keysig_packet failed: %s\n", g10_errstr (err));
+      return err;
     }
 
   /* Make a backsig.  */
-  if (use&PUBKEY_USAGE_SIG)
+  if (use & PUBKEY_USAGE_SIG)
     {
-      rc = make_backsig (sig, pri_pk, sub_pk, sub_sk, timestamp);
-      if (rc)
-        return rc;
+      err = make_backsig (sig, pri_pk, sub_pk, sub_psk, timestamp);
+      if (err)
+        return err;
     }
   
   pkt = xmalloc_clear ( sizeof *pkt );
   pkt->pkttype = PKT_SIGNATURE;
   pkt->pkt.signature = sig;
   add_kbnode (root, new_kbnode (pkt) );
-  return rc;
+  return err;
 }
 
 
@@ -1106,71 +1111,76 @@
 }
 
 
+
+/* Common code for the key generation fucntion gen_xxx.  */
 static int
-genhelp_protect (DEK *dek, STRING2KEY *s2k, PKT_secret_key *sk)
+common_gen (const char *keyparms, int algo, const char *algoelem,
+            kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey)
 {
-  int rc = 0;
-
-  if (dek)
+  int err;
+  PACKET *pkt;
+  PKT_public_key *pk;
+  gcry_sexp_t s_key;
+  
+  err = agent_genkey (NULL, keyparms, &s_key);
+  if (err)
     {
-      sk->protect.algo = dek->algo;
-      sk->protect.s2k = *s2k;
-      rc = protect_secret_key (sk, dek);
-      if (rc)
-        log_error ("protect_secret_key failed: %s\n", gpg_strerror (rc) );
+      log_error ("agent_genkey failed: %s\n", gpg_strerror (err) );
+      return err;
     }
+  
+  pk = xtrycalloc (1, sizeof *pk);
+  if (!pk)
+    {
+      err = gpg_error_from_syserror ();
+      gcry_sexp_release (s_key);
+      return err;
+    }
 
-  return rc;
-}
+  pk->timestamp = timestamp;
+  pk->version = 4;
+  if (expireval) 
+    pk->expiredate = pk->timestamp + expireval;
+  pk->pubkey_algo = algo;
 
-static void
-genhelp_factors (gcry_sexp_t misc_key_info, KBNODE sec_root)
-{
-  (void)misc_key_info;
-  (void)sec_root;
-#if 0 /* Not used anymore */
-  size_t n;
-  char *buf;
+  err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
+  if (err) 
+    {
+      log_error ("key_from_sexp failed: %s\n", gpg_strerror (err) );
+      gcry_sexp_release (s_key);
+      free_public_key (pk);
+      return err;
+    }
+  gcry_sexp_release (s_key);
   
-  if (misc_key_info)
+  pkt = xtrycalloc (1, sizeof *pkt);
+  if (!pkt)
     {
-      /* DSA: don't know whether it makes sense to have the factors, so for now
-         we store them in the secret keyring (but they are not secret)
-         p = 2 * q * f1 * f2 * ... * fn
-         We store only f1 to f_n-1;  fn can be calculated because p and q
-         are known. */
-      n = gcry_sexp_sprint (misc_key_info, 0, NULL, 0);
-      buf = xmalloc (n+4);
-      strcpy (buf, "#::");
-      n = gcry_sexp_sprint (misc_key_info, 0, buf+3, n);
-      if (n)
-        {
-          n += 3;
-          add_kbnode (sec_root, make_comment_node_from_buffer (buf, n));
-        }
-      xfree (buf);
-      gcry_sexp_release (misc_key_info);
+      err = gpg_error_from_syserror ();
+      free_public_key (pk);
+      return err;
     }
-#endif
+
+  pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY;
+  pkt->pkt.public_key = pk;
+  add_kbnode (pub_root, new_kbnode (pkt));
+
+  return 0;
 }
 
 
-/* Generate an Elgamal encryption key pair. TIMESTAMP is the creatuion
-   time to be put into the key structure.  */
+/*
+ * Generate an Elgamal key.
+ */
 static int
-gen_elg (int algo, unsigned int nbits,
-         KBNODE pub_root, KBNODE sec_root, DEK *dek,
-         STRING2KEY *s2k, PKT_secret_key **ret_sk, 
+gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
          u32 timestamp, u32 expireval, int is_subkey)
 {
-  int rc;
-  PACKET *pkt;
-  PKT_secret_key *sk;
-  PKT_public_key *pk;
-  gcry_sexp_t s_parms, s_key;
-  gcry_sexp_t misc_key_info;
+  int err;
+  char *keyparms;
+  char nbitsstr[35];
   
-  assert( is_ELGAMAL(algo) );
+  assert (is_ELGAMAL (algo));
 
   if (nbits < 512)
     {
@@ -1184,104 +1194,36 @@
       log_info (_("keysize rounded up to %u bits\n"), nbits );
     }
 
-
-  rc = gcry_sexp_build ( &s_parms, NULL,
-                         "(genkey(%s(nbits %d)))",
-                         algo == GCRY_PK_ELG_E ? "openpgp-elg" :
-                         algo == GCRY_PK_ELG	 ? "elg" : "x-oops" ,
-                         (int)nbits);
-  if (rc)
-    log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc));
-  
-  rc = gcry_pk_genkey (&s_key, s_parms);
-  gcry_sexp_release (s_parms);
-  if (rc)
+  snprintf (nbitsstr, sizeof nbitsstr, "%u", nbits);
+  keyparms = xtryasprintf ("(genkey(%s(nbits %zu:%s)))",
+                           algo == GCRY_PK_ELG_E ? "openpgp-elg" :
+                           algo == GCRY_PK_ELG	 ? "elg" : "x-oops" ,
+                           strlen (nbitsstr), nbitsstr);
+  if (!keyparms)
+    err = gpg_error_from_syserror ();
+  else
     {
-      log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) );
-      return rc;
+      err = common_gen (keyparms, algo, "pgy", 
+                        pub_root, timestamp, expireval, is_subkey);
+      xfree (keyparms);
     }
-  
-  sk = xmalloc_clear( sizeof *sk );
-  pk = xmalloc_clear( sizeof *pk );
-  sk->timestamp = pk->timestamp = timestamp;
-  sk->version = pk->version = 4;
-  if (expireval) 
-    {
-      sk->expiredate = pk->expiredate = sk->timestamp + expireval;
-    }
-  sk->pubkey_algo = pk->pubkey_algo = algo;
 
-  rc = key_from_sexp (pk->pkey, s_key, "public-key", "pgy");
-  if (rc) 
-    {
-      log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) );
-      gcry_sexp_release (s_key);
-      free_secret_key (sk);
-      free_public_key (pk);
-      return rc;
-    }
-  rc = key_from_sexp (sk->skey, s_key, "private-key", "pgyx");
-  if (rc)
-    {
-      log_error("key_from_sexp failed: %s\n", gpg_strerror (rc) );
-      gcry_sexp_release (s_key);
-      free_secret_key (sk);
-      free_public_key (pk);
-      return rc;
-    }
-  misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0);
-  gcry_sexp_release (s_key);
-  
-  sk->is_protected = 0;
-  sk->protect.algo = 0;
-
-  sk->csum = checksum_mpi (sk->skey[3]);
-  if (ret_sk) /* Return an unprotected version of the sk.  */
-    *ret_sk = copy_secret_key ( NULL, sk );
-
-  rc = genhelp_protect (dek, s2k, sk);
-  if (rc)
-    {
-      free_public_key (pk);
-      free_secret_key (sk);
-      gcry_sexp_release (misc_key_info);
-      return rc;
-    }
-  
-  pkt = xmalloc_clear (sizeof *pkt);
-  pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY;
-  pkt->pkt.public_key = pk;
-  add_kbnode (pub_root, new_kbnode( pkt ));
-
-  /* Don't know whether it makes sense to have access to the factors,
-     so for now we store them in the secret keyring (but they are not
-     secret).  */
-  pkt = xmalloc_clear (sizeof *pkt);
-  pkt->pkttype = is_subkey ? PKT_SECRET_SUBKEY : PKT_SECRET_KEY;
-  pkt->pkt.secret_key = sk;
-  add_kbnode (sec_root, new_kbnode( pkt ));
-  
-  genhelp_factors (misc_key_info, sec_root);
-  
-  return 0;
+  return err;
 }
 
 
-/****************
- * Generate a DSA key
+/*
+ * Generate an DSA key
  */
-static int
-gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
-         STRING2KEY *s2k, PKT_secret_key **ret_sk, 
+static gpg_error_t
+gen_dsa (unsigned int nbits, KBNODE pub_root, 
          u32 timestamp, u32 expireval, int is_subkey)
 {
-  int rc;
-  PACKET *pkt;
-  PKT_secret_key *sk;
-  PKT_public_key *pk;
-  gcry_sexp_t s_parms, s_key;
-  gcry_sexp_t misc_key_info;
+  int err;
   unsigned int qbits;
+  char *keyparms;
+  char nbitsstr[35];
+  char qbitsstr[35];
 
   if ( nbits < 512) 
     {
@@ -1334,84 +1276,21 @@
     log_info (_("WARNING: some OpenPGP programs can't"
                 " handle a DSA key with this digest size\n"));
 
-  rc = gcry_sexp_build (&s_parms, NULL,
-                        "(genkey(dsa(nbits %d)(qbits %d)))",
-                        (int)nbits, (int)qbits);




More information about the Gnupg-commits mailing list