[git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-433-g0beec2f

by Werner Koch cvs at cvs.gnupg.org
Tue Jun 3 18:55:32 CEST 2014


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  0beec2f0f255a71f9d5a4a0729d0259f673e8838 (commit)
      from  50cd3d40aec3b94cfddec94361ed1aafc999d61b (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 0beec2f0f255a71f9d5a4a0729d0259f673e8838
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Jun 3 18:57:33 2014 +0200

    gpgsm: New commands --export-secret-key-{p8,raw}
    
    * sm/gpgsm.c: Add new commands.
    * sm/minip12.c (build_key_sequence): Add arg mode.
    (p12_raw_build): New.
    * sm/export.c (export_p12): Add arg rawmode.  Call p12_raw_build.
    (gpgsm_p12_export): Ditto.
    (print_short_info): Print the keygrip.

diff --git a/NEWS b/NEWS
index da771f1..ba14079 100644
--- a/NEWS
+++ b/NEWS
@@ -42,6 +42,9 @@ Noteworthy changes in version 2.1.0-betaN (unreleased)
 
  * Protect against rogue keyservers sending secret keys.
 
+ * GPGSM can now be used to export a secret RSA key in PKCS#1 or
+   PKCS#8 format.
+
 
 Noteworthy changes in version 2.1.0beta3 (2011-12-20)
 -----------------------------------------------------
diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi
index 3d2594f..b38ad4d 100644
--- a/doc/gpgsm.texi
+++ b/doc/gpgsm.texi
@@ -259,13 +259,26 @@ certificate are only exported if all @var{pattern} are given as
 fingerprints or keygrips.
 
 @item --export-secret-key-p12 @var{key-id}
- at opindex export
+ at opindex export-secret-key-p12
 Export the private key and the certificate identified by @var{key-id} in
-a PKCS#12 format. When using along with the @code{--armor} option a few
+a PKCS#12 format. When used with the @code{--armor} option a few
 informational lines are prepended to the output.  Note, that the PKCS#12
 format is not very secure and this command is only provided if there is
 no other way to exchange the private key. (@pxref{option --p12-charset})
 
+ at ifset gpgtwoone
+ at item --export-secret-key-p8 @var{key-id}
+ at itemx --export-secret-key-raw @var{key-id}
+ at opindex export-secret-key-p8
+ at opindex export-secret-key-raw
+Export the private key of the certificate identified by @var{key-id}
+with any encryption stripped.  The @code{...-raw} command exports in
+PKCS#1 format; the @code{...-p8} command exports in PKCS#8 format.
+When used with the @code{--armor} option a few informational lines are
+prepended to the output.  These commands are useful to prepare a key
+for use on a TLS server.
+ at end ifset
+
 @item --import [@var{files}]
 @opindex import
 Import the certificates from the PEM or binary encoded files as well as
diff --git a/sm/export.c b/sm/export.c
index 0403fe2..1dce106 100644
--- a/sm/export.c
+++ b/sm/export.c
@@ -60,6 +60,7 @@ static void print_short_info (ksba_cert_t cert, estream_t stream);
 static gpg_error_t export_p12 (ctrl_t ctrl,
                                const unsigned char *certimg, size_t certimglen,
                                const char *prompt, const char *keygrip,
+                               int rawmode,
                                void **r_result, size_t *r_resultlen);
 
 
@@ -315,9 +316,14 @@ gpgsm_export (ctrl_t ctrl, strlist_t names, estream_t stream)
 }
 
 
-/* Export a certificate and its private key. */
+/* Export a certificate and its private key.  RAWMODE controls the
+   actual output:
+       0 - Private key and certifciate in PKCS#12 format
+       1 - Only unencrypted private key in PKCS#8 format
+       2 - Only unencrypted private key in PKCS#1 format
+    */
 void
-gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream)
+gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream, int rawmode)
 {
   gpg_error_t err = 0;
   KEYDB_HANDLE hd;
@@ -416,13 +422,18 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream)
       es_putc ('\n', stream);
     }
 
-  if (opt.p12_charset && ctrl->create_pem)
+  if (opt.p12_charset && ctrl->create_pem && !rawmode)
     {
       es_fprintf (stream, "The passphrase is %s encoded.\n\n",
                   opt.p12_charset);
     }
 
-  ctrl->pem_name = "PKCS12";
+  if (rawmode == 0)
+    ctrl->pem_name = "PKCS12";
+  else if (rawmode == 1)
+    ctrl->pem_name = "PRIVATE KEY";
+  else
+    ctrl->pem_name = "RSA PRIVATE KEY";
   err = gpgsm_create_writer (&b64writer, ctrl, stream, &writer);
   if (err)
     {
@@ -431,7 +442,8 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream)
     }
 
   prompt = gpgsm_format_keydesc (cert);
-  err = export_p12 (ctrl, image, imagelen, prompt, keygrip, &data, &datalen);
+  err = export_p12 (ctrl, image, imagelen, prompt, keygrip, rawmode,
+                    &data, &datalen);
   xfree (prompt);
   if (err)
     goto leave;
@@ -513,12 +525,19 @@ print_short_info (ksba_cert_t cert, estream_t stream)
       xfree (p);
     }
   es_putc ('\n', stream);
+
+  p = gpgsm_get_keygrip_hexstring (cert);
+  if (p)
+    {
+      es_fprintf (stream, "Keygrip ..: %s\n", p);
+      xfree (p);
+    }
 }
 
 
 

-/* Parse a private key S-expression and retutn a malloced array with
-   the RSA paramaters in pkcs#12 order.  The caller needs to
+/* Parse a private key S-expression and return a malloced array with
+   the RSA parameters in pkcs#12 order.  The caller needs to
    deep-release this array.  */
 static gcry_mpi_t *
 sexp_to_kparms (gcry_sexp_t sexp)
@@ -587,7 +606,7 @@ sexp_to_kparms (gcry_sexp_t sexp)
 
 static gpg_error_t
 export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen,
-            const char *prompt, const char *keygrip,
+            const char *prompt, const char *keygrip, int rawmode,
             void **r_result, size_t *r_resultlen)
 {
   gpg_error_t err = 0;
@@ -671,20 +690,30 @@ export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen,
       goto leave;
     }
 
-  err = gpgsm_agent_ask_passphrase
-    (ctrl,
-     i18n_utf8 ("Please enter the passphrase to protect the "
-                "new PKCS#12 object."),
-     1, &passphrase);
-  if (err)
-    goto leave;
+  if (rawmode)
+    {
+      /* Export in raw mode, that is only the pkcs#1/#8 private key. */
+      result = p12_raw_build (kparms, rawmode, &resultlen);
+      if (!result)
+        err = gpg_error (GPG_ERR_GENERAL);
+    }
+  else
+    {
+      err = gpgsm_agent_ask_passphrase
+        (ctrl,
+         i18n_utf8 ("Please enter the passphrase to protect the "
+                    "new PKCS#12 object."),
+         1, &passphrase);
+      if (err)
+        goto leave;
 
-  result = p12_build (kparms, certimg, certimglen, passphrase,
-                      opt.p12_charset, &resultlen);
-  xfree (passphrase);
-  passphrase = NULL;
-  if (!result)
-    err = gpg_error (GPG_ERR_GENERAL);
+      result = p12_build (kparms, certimg, certimglen, passphrase,
+                          opt.p12_charset, &resultlen);
+      xfree (passphrase);
+      passphrase = NULL;
+      if (!result)
+        err = gpg_error (GPG_ERR_GENERAL);
+    }
 
  leave:
   xfree (key);
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 3822717..01f33e3 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -74,6 +74,8 @@ enum cmd_and_opt_values {
   aRecvKeys,
   aExport,
   aExportSecretKeyP12,
+  aExportSecretKeyP8,
+  aExportSecretKeyRaw,
   aServer,
   aLearnCard,
   aCallDirmngr,
@@ -208,7 +210,13 @@ static ARGPARSE_OPTS opts[] = {
 /*ARGPARSE_c (aRecvKeys, "recv-keys", N_("import keys from a key server")),*/
   ARGPARSE_c (aImport, "import", N_("import certificates")),
   ARGPARSE_c (aExport, "export", N_("export certificates")),
+
+  /* We use -raw and not -p1 for pkcs#1 secret key export so that it
+     won't accidently be used in case -p12 was intended.  */
   ARGPARSE_c (aExportSecretKeyP12, "export-secret-key-p12", "@"),
+  ARGPARSE_c (aExportSecretKeyP8,  "export-secret-key-p8", "@"),
+  ARGPARSE_c (aExportSecretKeyRaw, "export-secret-key-raw", "@"),
+
   ARGPARSE_c (aLearnCard, "learn-card", N_("register a smartcard")),
   ARGPARSE_c (aServer, "server", N_("run in server mode")),
   ARGPARSE_c (aCallDirmngr, "call-dirmngr",
@@ -1084,6 +1092,8 @@ main ( int argc, char **argv)
         case aRecvKeys:
         case aExport:
         case aExportSecretKeyP12:
+        case aExportSecretKeyP8:
+        case aExportSecretKeyRaw:
         case aDumpKeys:
         case aDumpChain:
         case aDumpExternalKeys:
@@ -1888,7 +1898,7 @@ main ( int argc, char **argv)
         estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
 
         if (argc == 1)
-          gpgsm_p12_export (&ctrl, *argv, fp);
+          gpgsm_p12_export (&ctrl, *argv, fp, 0);
         else
           wrong_args ("--export-secret-key-p12 KEY-ID");
         if (fp != es_stdout)
@@ -1896,6 +1906,32 @@ main ( int argc, char **argv)
       }
       break;
 
+    case aExportSecretKeyP8:
+      {
+        estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
+
+        if (argc == 1)
+          gpgsm_p12_export (&ctrl, *argv, fp, 1);
+        else
+          wrong_args ("--export-secret-key-p8 KEY-ID");
+        if (fp != es_stdout)
+          es_fclose (fp);
+      }
+      break;
+
+    case aExportSecretKeyRaw:
+      {
+        estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
+
+        if (argc == 1)
+          gpgsm_p12_export (&ctrl, *argv, fp, 2);
+        else
+          wrong_args ("--export-secret-key-raw KEY-ID");
+        if (fp != es_stdout)
+          es_fclose (fp);
+      }
+      break;
+
     case aSendKeys:
     case aRecvKeys:
       log_error ("this command has not yet been implemented\n");
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 6c68af7..7c7ca7a 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -348,7 +348,8 @@ int gpgsm_import_files (ctrl_t ctrl, int nfiles, char **files,
 
 /*-- export.c --*/
 void gpgsm_export (ctrl_t ctrl, strlist_t names, estream_t stream);
-void gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream);
+void gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream,
+                       int rawmode);
 
 /*-- delete.c --*/
 int gpgsm_delete (ctrl_t ctrl, strlist_t names);
diff --git a/sm/minip12.c b/sm/minip12.c
index c91ef22..01b91b7 100644
--- a/sm/minip12.c
+++ b/sm/minip12.c
@@ -1,5 +1,6 @@
 /* minip12.c - A minimal pkcs-12 implementation.
  * Copyright (C) 2002, 2003, 2004, 2006, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2014 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -1891,10 +1892,15 @@ create_final (struct buffer_s *sequences, const char *pw, size_t *r_length)
          }
        }
      }
+
+  MODE controls what is being generated:
+     0 - As described above
+     1 - Ditto but without the padding
+     2 - Only the inner part (pkcs#1)
 */
 
 static unsigned char *
-build_key_sequence (gcry_mpi_t *kparms, size_t *r_length)
+build_key_sequence (gcry_mpi_t *kparms, int mode, size_t *r_length)
 {
   int rc, i;
   size_t needed, n;
@@ -1902,7 +1908,7 @@ build_key_sequence (gcry_mpi_t *kparms, size_t *r_length)
   size_t plainlen;
   size_t outseqlen, oidseqlen, octstrlen, inseqlen;
 
-  needed = 3; /* The version(?) integer of value 0. */
+  needed = 3; /* The version integer with value 0. */
   for (i=0; kparms[i]; i++)
     {
       n = 0;
@@ -1929,23 +1935,27 @@ build_key_sequence (gcry_mpi_t *kparms, size_t *r_length)
   if (!n)
     return NULL;
   needed += n;
-  /* Encapsulate all into an octet string. */
-  octstrlen = needed;
-  n = compute_tag_length (needed);
-  if (!n)
-    return NULL;
-  needed += n;
-  /* Prepend the object identifier sequence. */
-  oidseqlen = 2 + DIM (oid_rsaEncryption) + 2;
-  needed += 2 + oidseqlen;
-  /* The version number. */
-  needed += 3;
-  /* And finally put the whole thing into a sequence. */
-  outseqlen = needed;
-  n = compute_tag_length (needed);
-  if (!n)
-    return NULL;
-  needed += n;
+
+  if (mode != 2)
+    {
+      /* Encapsulate all into an octet string. */
+      octstrlen = needed;
+      n = compute_tag_length (needed);
+      if (!n)
+        return NULL;
+      needed += n;
+      /* Prepend the object identifier sequence. */
+      oidseqlen = 2 + DIM (oid_rsaEncryption) + 2;
+      needed += 2 + oidseqlen;
+      /* The version number. */
+      needed += 3;
+      /* And finally put the whole thing into a sequence. */
+      outseqlen = needed;
+      n = compute_tag_length (needed);
+      if (!n)
+        return NULL;
+      needed += n;
+    }
 
   /* allocate 8 extra bytes for padding */
   plain = gcry_malloc_secure (needed+8);
@@ -1957,20 +1967,24 @@ build_key_sequence (gcry_mpi_t *kparms, size_t *r_length)
 
   /* And now fill the plaintext buffer. */
   p = plain;
-  p = store_tag_length (p, TAG_SEQUENCE, outseqlen);
-  /* Store version. */
-  *p++ = TAG_INTEGER;
-  *p++ = 1;
-  *p++ = 0;
-  /* Store object identifier sequence. */
-  p = store_tag_length (p, TAG_SEQUENCE, oidseqlen);
-  p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_rsaEncryption));
-  memcpy (p, oid_rsaEncryption, DIM (oid_rsaEncryption));
-  p += DIM (oid_rsaEncryption);
-  *p++ = TAG_NULL;
-  *p++ = 0;
-  /* Start with the octet string. */
-  p = store_tag_length (p, TAG_OCTET_STRING, octstrlen);
+  if (mode != 2)
+    {
+      p = store_tag_length (p, TAG_SEQUENCE, outseqlen);
+      /* Store version. */
+      *p++ = TAG_INTEGER;
+      *p++ = 1;
+      *p++ = 0;
+      /* Store object identifier sequence. */
+      p = store_tag_length (p, TAG_SEQUENCE, oidseqlen);
+      p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_rsaEncryption));
+      memcpy (p, oid_rsaEncryption, DIM (oid_rsaEncryption));
+      p += DIM (oid_rsaEncryption);
+      *p++ = TAG_NULL;
+      *p++ = 0;
+      /* Start with the octet string. */
+      p = store_tag_length (p, TAG_OCTET_STRING, octstrlen);
+    }
+
   p = store_tag_length (p, TAG_SEQUENCE, inseqlen);
   /* Store the key parameters. */
   *p++ = TAG_INTEGER;
@@ -2003,10 +2017,14 @@ build_key_sequence (gcry_mpi_t *kparms, size_t *r_length)
 
   plainlen = p - plain;
   assert (needed == plainlen);
-  /* Append some pad characters; we already allocated extra space. */
-  n = 8 - plainlen % 8;
-  for (i=0; i < n; i++, plainlen++)
-    *p++ = n;
+
+  if (!mode)
+    {
+      /* Append some pad characters; we already allocated extra space. */
+      n = 8 - plainlen % 8;
+      for (i=0; i < n; i++, plainlen++)
+        *p++ = n;
+    }
 
   *r_length = plainlen;
   return plain;
@@ -2459,7 +2477,7 @@ p12_build (gcry_mpi_t *kparms, const void *cert, size_t certlen,
   if (kparms)
     {
       /* Encode the key. */
-      buffer = build_key_sequence (kparms, &buflen);
+      buffer = build_key_sequence (kparms, 0, &buflen);
       if (!buffer)
         goto failure;
 
@@ -2502,6 +2520,24 @@ p12_build (gcry_mpi_t *kparms, const void *cert, size_t certlen,
 }
 
 
+/* This is actually not a pkcs#12 function but one which creates an
+   unencrypted a pkcs#1 private key.  */
+unsigned char *
+p12_raw_build (gcry_mpi_t *kparms, int rawmode, size_t *r_length)
+{
+  unsigned char *buffer;
+  size_t buflen;
+
+  assert (rawmode == 1 || rawmode == 2);
+  buffer = build_key_sequence (kparms, rawmode, &buflen);
+  if (!buffer)
+    return NULL;
+
+  *r_length = buflen;
+  return buffer;
+}
+
+
 #ifdef TEST
 
 static void
diff --git a/sm/minip12.h b/sm/minip12.h
index 27f24f5..7a1950f 100644
--- a/sm/minip12.h
+++ b/sm/minip12.h
@@ -31,6 +31,9 @@ unsigned char *p12_build (gcry_mpi_t *kparms,
                           const void *cert, size_t certlen,
                           const char *pw, const char *charset,
                           size_t *r_length);
+unsigned char *p12_raw_build (gcry_mpi_t *kparms,
+                              int rawmode,
+                              size_t *r_length);
 
 
 #endif /*MINIP12_H*/

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

Summary of changes:
 NEWS           |    3 ++
 doc/gpgsm.texi |   17 ++++++++-
 sm/export.c    |   71 ++++++++++++++++++++++++-----------
 sm/gpgsm.c     |   38 ++++++++++++++++++-
 sm/gpgsm.h     |    3 +-
 sm/minip12.c   |  112 +++++++++++++++++++++++++++++++++++++-------------------
 sm/minip12.h   |    3 ++
 7 files changed, 184 insertions(+), 63 deletions(-)


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




More information about the Gnupg-commits mailing list