[git] GnuPG - branch, master, updated. post-nuke-of-trailing-ws-115-g958f29d

by Werner Koch cvs at cvs.gnupg.org
Sun Nov 6 17:52:41 CET 2011


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  958f29d2251a96d09439e591ea3523133930e5e9 (commit)
       via  32118628a0f20f87791755a0a110491ad85e23ad (commit)
      from  7dfcc9f19acfe8f0dc70db8d981b79aac0589cf4 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 958f29d2251a96d09439e591ea3523133930e5e9
Author: Werner Koch <wk at gnupg.org>
Date:   Sun Nov 6 17:01:31 2011 +0100

    Allow creating subkeys using an existing key
    
    This works by specifying the keygrip instead of an algorithm (section
    number 13) and requires that the option -expert has been used.  It
    will be easy to extend this to the primary key.

diff --git a/g10/ChangeLog b/g10/ChangeLog
index 4b5f2f1..8928780 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,15 @@
+2011-11-06  Werner Koch  <wk at g10code.com>
+
+	* card-util.c (generate_card_keys): Add arg CTRL.
+
+	* call-agent.c (agent_readkey): New.
+	* keygen.c (do_create_from_keygrip): New.
+	(ask_algo): Add arg R_KEYGRIP and a prompt to enter it.
+	(generate_subkeypair): Call do_create_from_keygrip if required.
+	(generate_subkeypair): Add arg CTRL.  Change caller.
+	(ask_algo): Add arg CTRL.
+	(generate_keypair): Ditto.
+
 2011-09-23  Werner Koch  <wk at g10code.com>
 
 	* gpgv.c (disable_dotlock): Rename to dotlock_disable.
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 5a10dbd..4451029 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -1,6 +1,6 @@
 /* call-agent.c - Divert GPG operations to the agent.
  * Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
- *               2010 Free Software Foundation, Inc.
+ *               2010, 2011 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -1506,55 +1506,52 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
 }
 
 
-
 
-/* FIXME: Call the agent to read the public key part for a given keygrip.  If
+/* 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; */
-/* } */
+gpg_error_t
+agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
+               unsigned char **r_pubkey)
+{
+  gpg_error_t err;
+  membuf_t data;
+  size_t len;
+  unsigned char *buf;
+  char line[ASSUAN_LINELENGTH];
+
+  *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;
+
+  snprintf (line, DIM(line)-1, "%sREADKEY %s", fromcard? "SCD ":"", hexkeygrip);
+
+  init_membuf (&data, 1024);
+  err = assuan_transact (agent_ctx, line,
+                         membuf_data_cb, &data,
+                         default_inq_cb, NULL, NULL, NULL);
+  if (err)
+    {
+      xfree (get_membuf (&data, &len));
+      return err;
+    }
+  buf = get_membuf (&data, &len);
+  if (!buf)
+    return gpg_error_from_syserror ();
+  if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
+    {
+      xfree (buf);
+      return gpg_error (GPG_ERR_INV_SEXP);
+    }
+  *r_pubkey = buf;
+  return 0;
+}
 
 
 
diff --git a/g10/call-agent.h b/g10/call-agent.h
index 1e7e15a..43de14f 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -148,6 +148,10 @@ gpg_error_t agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
                           const char *keyparms, int no_protection,
                           gcry_sexp_t *r_pubkey);
 
+/* Read a public key.  */
+gpg_error_t agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
+                           unsigned char **r_pubkey);
+
 /* Create a signature.  */
 gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce,
                           const char *hexkeygrip, const char *desc,
diff --git a/g10/card-util.c b/g10/card-util.c
index 9c124bb..14268df 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -1356,7 +1356,7 @@ do_change_keysize (int keyno, unsigned int nbits)
 
 
 static void
-generate_card_keys (void)
+generate_card_keys (ctrl_t ctrl)
 {
   struct agent_card_info_s info;
   int forced_chv1;
@@ -1435,7 +1435,7 @@ generate_card_keys (void)
          the serialnumber and thus it won't harm.  */
     }
 
-  generate_keypair (NULL, info.serialno, want_backup);
+  generate_keypair (ctrl, NULL, info.serialno, want_backup);
 
  leave:
   agent_release_card_info (&info);
@@ -1986,7 +1986,7 @@ card_edit (ctrl_t ctrl, strlist_t commands)
           break;
 
         case cmdGENERATE:
-          generate_card_keys ();
+          generate_card_keys (ctrl);
           break;
 
         case cmdPASSWD:
diff --git a/g10/gpg.c b/g10/gpg.c
index c31a558..aa37a88 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -3709,12 +3709,12 @@ main (int argc, char **argv)
 	if( opt.batch ) {
 	    if( argc > 1 )
 		wrong_args("--gen-key [parameterfile]");
-	    generate_keypair (argc? *argv : NULL, NULL, 0);
+	    generate_keypair (ctrl, argc? *argv : NULL, NULL, 0);
 	}
 	else {
 	    if( argc )
 		wrong_args("--gen-key");
-	    generate_keypair (NULL, NULL, 0);
+	    generate_keypair (ctrl, NULL, NULL, 0);
 	}
 	break;
 
diff --git a/g10/keyedit.c b/g10/keyedit.c
index fd42439..26e05a0 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -1794,7 +1794,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 	  break;
 
 	case cmdADDKEY:
-	  if (!generate_subkeypair (keyblock))
+	  if (!generate_subkeypair (ctrl, keyblock))
 	    {
 	      redisplay = 1;
 	      modified = 1;
diff --git a/g10/keygen.c b/g10/keygen.c
index a5650a8..55048b1 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1254,6 +1254,91 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
 }
 
 
+/* Create a keyblock using the given KEYGRIP.  ALGO is the OpenPGP
+   algorithm of that keygrip.  */
+static int
+do_create_from_keygrip (ctrl_t ctrl, int algo, const char *hexkeygrip,
+                        kbnode_t pub_root, u32 timestamp, u32 expireval,
+                        int is_subkey)
+{
+  int err;
+  PACKET *pkt;
+  PKT_public_key *pk;
+  gcry_sexp_t s_key;
+  const char *algoelem;
+
+  if (hexkeygrip[0] == '&')
+    hexkeygrip++;
+
+  switch (algo)
+    {
+    case PUBKEY_ALGO_RSA:       algoelem = "ne"; break;
+    case PUBKEY_ALGO_DSA:       algoelem = "pqgy"; break;
+    case PUBKEY_ALGO_ELGAMAL_E: algoelem = "pgy"; break;
+    case PUBKEY_ALGO_ECDH:
+    case PUBKEY_ALGO_ECDSA:     algoelem = ""; break;
+    default: return gpg_error (GPG_ERR_INTERNAL);
+    }
+
+
+  /* Ask the agent for the public key matching HEXKEYGRIP.  */
+  {
+    unsigned char *public;
+
+    err = agent_readkey (ctrl, 0, hexkeygrip, &public);
+    if (err)
+      return err;
+    err = gcry_sexp_sscan (&s_key, NULL,
+                           public, gcry_sexp_canon_len (public, 0, NULL, NULL));
+    xfree (public);
+    if (err)
+      return err;
+  }
+
+  /* Build a public key packet.  */
+  pk = xtrycalloc (1, sizeof *pk);
+  if (!pk)
+    {
+      err = gpg_error_from_syserror ();
+      gcry_sexp_release (s_key);
+      return err;
+    }
+
+  pk->timestamp = timestamp;
+  pk->version = 4;
+  if (expireval)
+    pk->expiredate = pk->timestamp + expireval;
+  pk->pubkey_algo = algo;
+
+  if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH)
+    err = ecckey_from_sexp (pk->pkey, s_key, algo);
+  else
+    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);
+
+  pkt = xtrycalloc (1, sizeof *pkt);
+  if (!pkt)
+    {
+      err = gpg_error_from_syserror ();
+      free_public_key (pk);
+      return err;
+    }
+
+  pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY;
+  pkt->pkt.public_key = pk;
+  add_kbnode (pub_root, new_kbnode (pkt));
+
+  return 0;
+}
+
+
 /* Common code for the key generation fucntion gen_xxx.  */
 static int
 common_gen (const char *keyparms, int algo, const char *algoelem,
@@ -1691,14 +1776,53 @@ ask_key_flags(int algo,int subkey)
 }
 
 
+/* Check whether we have a key for the key with HEXGRIP.  Returns 0 if
+   there is no such key or the OpenPGP algo number for the key.  */
+static int
+check_keygrip (ctrl_t ctrl, const char *hexgrip)
+{
+  gpg_error_t err;
+  unsigned char *public;
+  size_t publiclen;
+  int algo;
+
+  if (hexgrip[0] == '&')
+    hexgrip++;
+
+  err = agent_readkey (ctrl, 0, hexgrip, &public);
+  if (err)
+    return 0;
+  publiclen = gcry_sexp_canon_len (public, 0, NULL, NULL);
+
+  get_pk_algo_from_canon_sexp (public, publiclen, &algo);
+  xfree (public);
+
+  switch (algo)
+    {
+    case GCRY_PK_RSA:   return PUBKEY_ALGO_RSA;
+    case GCRY_PK_DSA:   return PUBKEY_ALGO_DSA;
+    case GCRY_PK_ELG_E: return PUBKEY_ALGO_ELGAMAL_E;
+    case GCRY_PK_ECDH:  return PUBKEY_ALGO_ECDH;
+    case GCRY_PK_ECDSA: return PUBKEY_ALGO_ECDSA;
+    default: return 0;
+    }
+}
+
+
+
 /* Ask for an algorithm.  The function returns the algorithm id to
  * create. If ADDMODE is false the function won't show an option to
  * create the primary and subkey combined and won't set R_USAGE
  * either.  If a combined algorithm has been selected, the subkey
- * algorithm is stored at R_SUBKEY_ALGO.  */
+ * algorithm is stored at R_SUBKEY_ALGO.  If R_KEYGRIP is given, the
+ * user has the choice to enter the keygrip of an existing key.  That
+ * keygrip is then stored at this address.  The caller needs to free
+ * it. */
 static int
-ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
+ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
+          char **r_keygrip)
 {
+  char *keygrip = NULL;
   char *answer;
   int algo;
   int dummy_algo;
@@ -1736,6 +1860,9 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
   if (opt.expert && addmode)
     tty_printf (_("  (%d) ECDH (encrypt only)\n"), 12 );
 
+  if (opt.expert && r_keygrip)
+    tty_printf (_("  (%d) Existing key\n"), 13 );
+
   for (;;)
     {
       *r_usage = 0;
@@ -1744,6 +1871,7 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
       cpr_kill_prompt ();
       algo = *answer? atoi (answer) : 1;
       xfree(answer);
+      answer = NULL;
       if (algo == 1 && !addmode)
         {
           algo = PUBKEY_ALGO_RSA;
@@ -1816,10 +1944,42 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
           *r_usage = PUBKEY_USAGE_ENC;
           break;
 	}
+      else if (algo == 13 && opt.expert && r_keygrip)
+        {
+          for (;;)
+            {
+              xfree (answer);
+              answer = tty_get (_("Enter the keygrip: "));
+              tty_kill_prompt ();
+              trim_spaces (answer);
+              if (!*answer)
+                {
+                  xfree (answer);
+                  answer = NULL;
+                  continue;
+                }
+
+              if (strlen (answer) != 40 &&
+                       !(answer[0] == '&' && strlen (answer+1) == 40))
+                tty_printf
+                  (_("Not a valid keygrip (expecting 40 hex digits)\n"));
+              else if (!(algo = check_keygrip (ctrl, answer)) )
+                tty_printf (_("No key with this keygrip\n"));
+              else
+                break; /* Okay.  */
+            }
+          xfree (keygrip);
+          keygrip = answer;
+          answer = NULL;
+          *r_usage = ask_key_flags (algo, addmode);
+          break;
+	}
       else
         tty_printf (_("Invalid selection.\n"));
     }
 
+  if (r_keygrip)
+    *r_keygrip = keygrip;
   return algo;
 }
 
@@ -3099,7 +3259,7 @@ read_parameter_file( const char *fname )
  * imported to the card and a backup file created by gpg-agent.
  */
 void
-generate_keypair (const char *fname, const char *card_serialno,
+generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno,
                   int card_backup_key)
 {
   unsigned int nbits;
@@ -3180,7 +3340,11 @@ generate_keypair (const char *fname, const char *card_serialno,
     {
       int subkey_algo;
 
-      algo = ask_algo (0, &subkey_algo, &use);
+      /* Fixme: To support creating a primary key by keygrip we better
+         also define the keyword for the parameter file.  Note that
+         the subkey case will never be asserted if a keygrip has been
+         given.  */
+      algo = ask_algo (ctrl, 0, &subkey_algo, &use, NULL);
       if (subkey_algo)
         {
           /* Create primary and subkey at once.  */
@@ -3653,7 +3817,7 @@ do_generate_keypair (struct para_data_s *para,
 /* Add a new subkey to an existing key.  Returns 0 if a new key has
    been generated and put into the keyblocks.  */
 gpg_error_t
-generate_subkeypair (KBNODE keyblock)
+generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
 {
   gpg_error_t err = 0;
   kbnode_t node;
@@ -3712,9 +3876,11 @@ generate_subkeypair (KBNODE keyblock)
   if (serialno)
     tty_printf (_("Secret parts of primary key are stored on-card.\n"));
 
-  algo = ask_algo (1, NULL, &use);
+  xfree (hexgrip);
+  hexgrip = NULL;
+  algo = ask_algo (ctrl, 1, NULL, &use, &hexgrip);
   assert (algo);
-  nbits = ask_keysize (algo, 0);
+  nbits = hexgrip? 0 : ask_keysize (algo, 0);
   expire = ask_expire_interval (0, NULL);
   if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
                                                _("Really create? (y/N) ")))
@@ -3723,7 +3889,11 @@ generate_subkeypair (KBNODE keyblock)
       goto leave;
     }
 
-  err = do_create (algo, nbits, keyblock, cur_time, expire, 1, 0, NULL);
+  if (hexgrip)
+    err = do_create_from_keygrip (ctrl, algo, hexgrip,
+                                  keyblock, cur_time, expire, 1);
+  else
+    err = do_create (algo, nbits, keyblock, cur_time, expire, 1, 0, NULL);
   if (err)
     goto leave;
 
diff --git a/g10/main.h b/g10/main.h
index 9548731..7088abe 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -240,8 +240,8 @@ const char *gpg_curve_to_oid (const char *name, unsigned int *r_nbits);
 u32 parse_expire_string(const char *string);
 u32 ask_expire_interval(int object,const char *def_expire);
 u32 ask_expiredate(void);
-void generate_keypair (const char *fname, const char *card_serialno,
-                       int card_backup_key);
+void generate_keypair (ctrl_t ctrl, const char *fname,
+                       const char *card_serialno, int card_backup_key);
 int keygen_set_std_prefs (const char *string,int personal);
 PKT_user_id *keygen_get_std_prefs (void);
 int keygen_add_key_expire( PKT_signature *sig, void *opaque );
@@ -253,7 +253,7 @@ int keygen_add_revkey(PKT_signature *sig, void *opaque);
 gpg_error_t make_backsig (PKT_signature *sig, PKT_public_key *pk,
                           PKT_public_key *sub_pk, PKT_public_key *sub_psk,
                           u32 timestamp, const char *cache_nonce);
-gpg_error_t generate_subkeypair (kbnode_t pub_keyblock);
+gpg_error_t generate_subkeypair (ctrl_t ctrl, kbnode_t pub_keyblock);
 #ifdef ENABLE_CARD_SUPPORT
 gpg_error_t generate_card_subkeypair (kbnode_t pub_keyblock,
                                       int keyno, const char *serialno);

commit 32118628a0f20f87791755a0a110491ad85e23ad
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Nov 2 18:29:47 2011 +0100

    typo fixes

diff --git a/doc/gpg.texi b/doc/gpg.texi
index 715b599..d00e01f 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -3202,7 +3202,7 @@ place, duplicate specification of the same filename is ignored, the
 last filename before a commit is used.  The filename is used until a
 new filename is used (at commit points) and all keys are written to
 that file. If a new filename is given, this file is created (and
-overwrites an existing one).  For gnuPG versions prior to 2.1, both
+overwrites an existing one).  For GnuPG versions prior to 2.1, both
 control statements must be given. For GnuPG 2.1 and later
 @samp{%secring} is a no-op.
 
@@ -3250,7 +3250,7 @@ The requested length of the generated key in bits.  The default is
 returned by running the command @samp{gpg2 --gpgconf-list}.
 
 @item Key-Grip: @var{hexstring}
-This is optional and used to generate a CSR or certificatet for an
+This is optional and used to generate a CSR or certificate for an
 already existing key.  Key-Length will be ignored when given.
 
 @item Key-Usage: @var{usage-list}

-----------------------------------------------------------------------

Summary of changes:
 doc/gpg.texi     |    4 +-
 g10/ChangeLog    |   12 ++++
 g10/call-agent.c |   89 +++++++++++++-------------
 g10/call-agent.h |    4 +
 g10/card-util.c  |    6 +-
 g10/gpg.c        |    4 +-
 g10/keyedit.c    |    2 +-
 g10/keygen.c     |  186 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 g10/main.h       |    6 +-
 9 files changed, 248 insertions(+), 65 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list