common: Add dedicated private key functions to name-value.c.
authorWerner Koch <wk@gnupg.org>
Thu, 23 Jun 2016 11:17:25 +0000 (13:17 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 23 Jun 2016 11:17:25 +0000 (13:17 +0200)
* common/name-value.c (struct name_value_container): Add field
'private_key_mode'.
(my_error): New.  Use instead of gpg_error.
(nvc_new_private_key): New.
(nve_release): Add arg 'private_key_mode'.
(nvc_release): Call nve_release with private_key_mode flag.
(nvc_delete): Ditto.
(_nvc_add): Do no special case "Key:" in non-private_key_mode.
(nvc_get_private_key): Return error in non-private_key_mode.
(nvc_set_private_key): Ditto.
(nvc_parse):  Factor all code out to ...
(do_nvc_parse): new.  Add arg 'for_private_key'.
(nvc_parse_private_key): New.
* agent/findkey.c (write_extended_private_key): Replace nvc_parse by
nvc_parse_private_key.
(read_key_file): Ditto.

* common/t-name-value.c (private_key_mode): New variable.
(my_nvc_new): New.  Replace all callers.
(test_key_extraction): Take mode in account.
(run_tests): Ditto.
(run_modification_tests): Ditto.
(parse): Ditto.
(main): Add option --parse and rename --parse to --parse-key.
--

Signed-off-by: Werner Koch <wk@gnupg.org>
agent/findkey.c
common/name-value.c
common/name-value.h
common/t-name-value.c

index dc7099c..c5ab0e9 100644 (file)
@@ -62,7 +62,7 @@ write_extended_private_key (char *fname, estream_t fp,
   int remove = 0;
   int line;
 
-  err = nvc_parse (&pk, &line, fp);
+  err = nvc_parse_private_key (&pk, &line, fp);
   if (err)
     {
       log_error ("error parsing '%s' line %d: %s\n",
@@ -690,7 +690,7 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
       nvc_t pk;
       int line;
 
-      rc = nvc_parse (&pk, &line, fp);
+      rc = nvc_parse_private_key (&pk, &line, fp);
       es_fclose (fp);
 
       if (rc)
index e297f1a..0b32a44 100644 (file)
@@ -47,6 +47,7 @@ struct name_value_container
 {
   struct name_value_entry *first;
   struct name_value_entry *last;
+  unsigned int private_key_mode:1;
 };
 
 
@@ -75,6 +76,13 @@ my_error_from_syserror (void)
 }
 
 
+static inline gpg_error_t
+my_error (gpg_err_code_t ec)
+{
+  return gpg_err_make (default_errsource, ec);
+}
+
+
 \f
 
 /* Allocation and deallocation.  */
@@ -87,17 +95,31 @@ nvc_new (void)
 }
 
 
+/* Allocate a private key container structure for use with private keys.  */
+nvc_t
+nvc_new_private_key (void)
+{
+  nvc_t nvc = nvc_new ();
+  if (nvc)
+    nvc->private_key_mode = 1;
+  return nvc;
+}
+
+
 static void
-nve_release (nve_t entry)
+nve_release (nve_t entry, int private_key_mode)
 {
   if (entry == NULL)
     return;
 
   xfree (entry->name);
-  if (entry->value)
+  if (entry->value && private_key_mode)
     wipememory (entry->value, strlen (entry->value));
   xfree (entry->value);
-  free_strlist_wipe (entry->raw_value);
+  if (private_key_mode)
+    free_strlist_wipe (entry->raw_value);
+  else
+    free_strlist (entry->raw_value);
   xfree (entry);
 }
 
@@ -114,7 +136,7 @@ nvc_release (nvc_t pk)
   for (e = pk->first; e; e = next)
     {
       next = e->next;
-      nve_release (e);
+      nve_release (e, pk->private_key_mode);
     }
 
   xfree (pk);
@@ -336,13 +358,16 @@ _nvc_add (nvc_t pk, char *name, char *value, strlist_t raw_value,
 
   if (name && ! valid_name (name))
     {
-      err = gpg_error (GPG_ERR_INV_NAME);
+      err = my_error (GPG_ERR_INV_NAME);
       goto leave;
     }
 
-  if (name && ascii_strcasecmp (name, "Key:") == 0 && nvc_lookup (pk, "Key:"))
+  if (name
+      && pk->private_key_mode
+      && !ascii_strcasecmp (name, "Key:")
+      && nvc_lookup (pk, "Key:"))
     {
-      err = gpg_error (GPG_ERR_INV_NAME);
+      err = my_error (GPG_ERR_INV_NAME);
       goto leave;
     }
 
@@ -486,7 +511,7 @@ nvc_delete (nvc_t pk, nve_t entry)
   else
     pk->last = entry->prev;
 
-  nve_release (entry);
+  nve_release (entry, pk->private_key_mode);
 }
 
 \f
@@ -549,9 +574,9 @@ nvc_get_private_key (nvc_t pk, gcry_sexp_t *retsexp)
   gpg_error_t err;
   nve_t e;
 
-  e = nvc_lookup (pk, "Key:");
+  e = pk->private_key_mode? nvc_lookup (pk, "Key:") : NULL;
   if (e == NULL)
-    return gpg_error (GPG_ERR_MISSING_KEY);
+    return my_error (GPG_ERR_MISSING_KEY);
 
   err = assert_value (e);
   if (err)
@@ -569,6 +594,9 @@ nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp)
   char *raw, *clean, *p;
   size_t len, i;
 
+  if (!pk->private_key_mode)
+    return my_error (GPG_ERR_MISSING_KEY);
+
   len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
 
   raw = xtrymalloc (len);
@@ -620,11 +648,9 @@ nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp)
 
 /* Parsing and serialization.  */
 
-/* Parse STREAM and return a newly allocated private key container
-   structure in RESULT.  If ERRLINEP is given, the line number the
-   parser was last considering is stored there.  */
-gpg_error_t
-nvc_parse (nvc_t *result, int *errlinep, estream_t stream)
+static gpg_error_t
+do_nvc_parse (nvc_t *result, int *errlinep, estream_t stream,
+              int for_private_key)
 {
   gpg_error_t err = 0;
   gpgrt_ssize_t len;
@@ -633,8 +659,7 @@ nvc_parse (nvc_t *result, int *errlinep, estream_t stream)
   char *name = NULL;
   strlist_t raw_value = NULL;
 
-
-  *result = nvc_new ();
+  *result = for_private_key? nvc_new_private_key () : nvc_new ();
   if (*result == NULL)
     return my_error_from_syserror ();
 
@@ -680,7 +705,7 @@ nvc_parse (nvc_t *result, int *errlinep, estream_t stream)
          colon = strchr (buf, ':');
          if (colon == NULL)
            {
-             err = gpg_error (GPG_ERR_INV_VALUE);
+             err = my_error (GPG_ERR_INV_VALUE);
              goto leave;
            }
 
@@ -727,6 +752,27 @@ nvc_parse (nvc_t *result, int *errlinep, estream_t stream)
 }
 
 
+/* Parse STREAM and return a newly allocated name value container
+   structure in RESULT.  If ERRLINEP is given, the line number the
+   parser was last considering is stored there.  */
+gpg_error_t
+nvc_parse (nvc_t *result, int *errlinep, estream_t stream)
+{
+  return do_nvc_parse (result, errlinep, stream, 0);
+}
+
+
+/* Parse STREAM and return a newly allocated name value container
+   structure in RESULT - assuming the extended private key format.  If
+   ERRLINEP is given, the line number the parser was last considering
+   is stored there.  */
+gpg_error_t
+nvc_parse_private_key (nvc_t *result, int *errlinep, estream_t stream)
+{
+  return do_nvc_parse (result, errlinep, stream, 1);
+}
+
+
 /* Write a representation of PK to STREAM.  */
 gpg_error_t
 nvc_write (nvc_t pk, estream_t stream)
index 21a5293..f5f17e6 100644 (file)
@@ -40,10 +40,14 @@ typedef struct name_value_entry *nve_t;
 
 /* Memory management, and dealing with entries.  */
 
-/* Allocate a private key container structure.  */
+/* Allocate a name value container structure.  */
 nvc_t nvc_new (void);
 
-/* Release a private key container structure.  */
+/* Allocate a name value container structure for use with the extended
+ * private key format.  */
+nvc_t nvc_new_private_key (void);
+
+/* Release a name value container structure.  */
 void nvc_release (nvc_t pk);
 
 /* Get the name.  */
@@ -103,6 +107,13 @@ gpg_error_t nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp);
    parser was last considering is stored there.  */
 gpg_error_t nvc_parse (nvc_t *result, int *errlinep, estream_t stream);
 
+/* Parse STREAM and return a newly allocated name value container
+   structure in RESULT - assuming the extended private key format.  If
+   ERRLINEP is given, the line number the parser was last considering
+   is stored there.  */
+gpg_error_t nvc_parse_private_key (nvc_t *result, int *errlinep,
+                                   estream_t stream);
+
 /* Write a representation of PK to STREAM.  */
 gpg_error_t nvc_write (nvc_t pk, estream_t stream);
 
index 810c85c..fc9303b 100644 (file)
 #include "name-value.h"
 
 static int verbose;
+static int private_key_mode;
+
+
+static nvc_t
+my_nvc_new (void)
+{
+  if (private_key_mode)
+    return nvc_new_private_key ();
+  else
+    return nvc_new ();
+}
+
 
 void
 test_getting_values (nvc_t pk)
@@ -55,14 +67,22 @@ test_key_extraction (nvc_t pk)
   gpg_error_t err;
   gcry_sexp_t key;
 
-  err = nvc_get_private_key (pk, &key);
-  assert (err == 0);
-  assert (key);
+  if (private_key_mode)
+    {
+      err = nvc_get_private_key (pk, &key);
+      assert (err == 0);
+      assert (key);
 
-  if (verbose)
-    gcry_sexp_dump (key);
+      if (verbose)
+        gcry_sexp_dump (key);
 
-  gcry_sexp_release (key);
+      gcry_sexp_release (key);
+    }
+  else
+    {
+      err = nvc_get_private_key (pk, &key);
+      assert (gpg_err_code (err) == GPG_ERR_MISSING_KEY);
+    }
 }
 
 
@@ -240,7 +260,10 @@ run_tests (void)
                         0, dummy_realloc, dummy_free, "r");
       assert (source);
 
-      err = nvc_parse (&pk, NULL, source);
+      if (private_key_mode)
+        err = nvc_parse_private_key (&pk, NULL, source);
+      else
+        err = nvc_parse (&pk, NULL, source);
       assert (err == 0);
       assert (pk);
 
@@ -272,7 +295,7 @@ run_modification_tests (void)
   gcry_sexp_t key;
   char *buf;
 
-  pk = nvc_new ();
+  pk = my_nvc_new ();
   assert (pk);
 
   nvc_set (pk, "Foo:", "Bar");
@@ -354,20 +377,29 @@ run_modification_tests (void)
   xfree (buf);
   nvc_release (pk);
 
-  pk = nvc_new ();
+  pk = my_nvc_new ();
   assert (pk);
 
   err = gcry_sexp_build (&key, NULL, "(hello world)");
   assert (err == 0);
   assert (key);
 
-  err = nvc_set_private_key (pk, key);
-  gcry_sexp_release (key);
-  assert (err == 0);
-  buf = nvc_to_string (pk);
-  assert (strcmp (buf, "Key: (hello world)\n") == 0);
-  xfree (buf);
-  nvc_release (pk);
+  if (private_key_mode)
+    {
+      err = nvc_set_private_key (pk, key);
+      gcry_sexp_release (key);
+      assert (err == 0);
+
+      buf = nvc_to_string (pk);
+      assert (strcmp (buf, "Key: (hello world)\n") == 0);
+      xfree (buf);
+      nvc_release (pk);
+    }
+  else
+    {
+      err = nvc_set_private_key (pk, key);
+      assert (gpg_err_code (err) == GPG_ERR_MISSING_KEY);
+    }
 }
 
 
@@ -403,7 +435,7 @@ convert (const char *fname)
       exit (1);
     }
 
-  pk = nvc_new ();
+  pk = my_nvc_new ();
   assert (pk);
 
   err = nvc_set_private_key (pk, key);
@@ -437,7 +469,10 @@ parse (const char *fname)
       exit (1);
     }
 
-  err = nvc_parse (&pk_a, &line, source);
+  if (private_key_mode)
+    err = nvc_parse_private_key (&pk_a, &line, source);
+  else
+    err = nvc_parse (&pk_a, &line, source);
   if (err)
     {
       fprintf (stderr, "failed to parse %s line %d: %s\n",
@@ -448,14 +483,14 @@ parse (const char *fname)
   buf = nvc_to_string (pk_a);
   xfree (buf);
 
-  pk_b = nvc_new ();
+  pk_b = my_nvc_new ();
   assert (pk_b);
 
   for (e = nvc_first (pk_a); e; e = nve_next (e))
     {
       gcry_sexp_t key = NULL;
 
-      if (strcasecmp (nve_name (e), "Key:") == 0)
+      if (private_key_mode && !strcasecmp (nve_name (e), "Key:"))
        {
          err = nvc_get_private_key (pk_a, &key);
          if (err)
@@ -487,7 +522,8 @@ print_usage (void)
   fprintf (stderr,
           "usage: t-private-keys [--verbose]"
           " [--convert <private-key-file>"
-          " || --parse <extended-private-key-file>]\n");
+          " || --parse-key <extended-private-key-file>"
+           " || --parse <file> ]\n");
   exit (2);
 }
 
@@ -495,7 +531,7 @@ print_usage (void)
 int
 main (int argc, char **argv)
 {
-  enum { TEST, CONVERT, PARSE } command = TEST;
+  enum { TEST, CONVERT, PARSE, PARSEKEY } command = TEST;
 
   if (argc)
     { argc--; argv++; }
@@ -513,6 +549,14 @@ main (int argc, char **argv)
        print_usage ();
     }
 
+  if (argc && !strcmp (argv[0], "--parse-key"))
+    {
+      command = PARSEKEY;
+      argc--; argv++;
+      if (argc != 1)
+       print_usage ();
+    }
+
   if (argc && !strcmp (argv[0], "--parse"))
     {
       command = PARSE;
@@ -526,12 +570,20 @@ main (int argc, char **argv)
     case TEST:
       run_tests ();
       run_modification_tests ();
+      private_key_mode = 1;
+      run_tests ();
+      run_modification_tests ();
       break;
 
     case CONVERT:
       convert (*argv);
       break;
 
+    case PARSEKEY:
+      private_key_mode = 1;
+      parse (*argv);
+      break;
+
     case PARSE:
       parse (*argv);
       break;