agent: New option --enable-extended-key-format.
authorWerner Koch <wk@gnupg.org>
Fri, 24 Mar 2017 09:30:17 +0000 (10:30 +0100)
committerWerner Koch <wk@gnupg.org>
Fri, 24 Mar 2017 09:35:36 +0000 (10:35 +0100)
* agent/gpg-agent.c (oEnableExtendedKeyFormat): New const.
(opts): New option --enable-extended-key-format.
(parse_rereadable_options): Set option
* agent/findkey.c (write_extended_private_key): Add arg 'update'.
(agent_write_private_key): Implement new option.

Signed-off-by: Werner Koch <wk@gnupg.org>
agent/agent.h
agent/findkey.c
agent/gpg-agent.c
doc/gpg-agent.texi

index 3b53ba4..01e675b 100644 (file)
@@ -124,6 +124,9 @@ struct
      passphrase change.  */
   int enable_passphrase_history;
 
+  /* If set the extended key format is used for new keys.  */
+  int enable_extended_key_format;
+
   int running_detached; /* We are running detached from the tty. */
 
   /* If this global option is true, the passphrase cache is ignored
index 4429b7a..0b2ddf1 100644 (file)
@@ -52,23 +52,38 @@ struct try_unprotect_arg_s
 };
 
 
+/* Note: Ownership of FNAME and FP are moved to this function.  */
 static gpg_error_t
-write_extended_private_key (char *fname, estream_t fp,
+write_extended_private_key (char *fname, estream_t fp, int update,
                             const void *buf, size_t len)
 {
   gpg_error_t err;
   nvc_t pk = NULL;
   gcry_sexp_t key = NULL;
   int remove = 0;
-  int line;
 
-  err = nvc_parse_private_key (&pk, &line, fp);
-  if (err)
+  if (update)
     {
-      log_error ("error parsing '%s' line %d: %s\n",
-                 fname, line, gpg_strerror (err));
-      goto leave;
+      int line;
+
+      err = nvc_parse_private_key (&pk, &line, fp);
+      if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
+        {
+          log_error ("error parsing '%s' line %d: %s\n",
+                     fname, line, gpg_strerror (err));
+          goto leave;
+        }
     }
+  else
+    {
+      pk = nvc_new_private_key ();
+      if (!pk)
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
+    }
+  es_clearerr (fp);
 
   err = gcry_sexp_sscan (&key, NULL, buf, len);
   if (err)
@@ -111,8 +126,7 @@ write_extended_private_key (char *fname, estream_t fp,
   bump_key_eventcounter ();
 
  leave:
-  if (fp)
-    es_fclose (fp);
+  es_fclose (fp);
   if (remove)
     gnupg_remove (fname);
   xfree (fname);
@@ -193,11 +207,19 @@ agent_write_private_key (const unsigned char *grip,
 
       if (first != '(')
         {
-          /* Key is in extended format.  */
-          return write_extended_private_key (fname, fp, buffer, length);
+          /* Key is already in the extended format.  */
+          return write_extended_private_key (fname, fp, 1, buffer, length);
+        }
+      if (first == '(' && opt.enable_extended_key_format)
+        {
+          /* Key is in the old format - but we want the extended format.  */
+          return write_extended_private_key (fname, fp, 0, buffer, length);
         }
     }
 
+  if (opt.enable_extended_key_format)
+    return write_extended_private_key (fname, fp, 0, buffer, length);
+
   if (es_fwrite (buffer, length, 1, fp) != 1)
     {
       gpg_error_t tmperr = gpg_error_from_syserror ();
index c84dce7..49b10c1 100644 (file)
@@ -111,6 +111,7 @@ enum cmd_and_opt_values
   oCheckPassphrasePattern,
   oMaxPassphraseDays,
   oEnablePassphraseHistory,
+  oEnableExtendedKeyFormat,
   oUseStandardSocket,
   oNoUseStandardSocket,
   oExtraSocket,
@@ -238,6 +239,7 @@ static ARGPARSE_OPTS opts[] = {
                 /* */           "@"
 #endif
                 ),
+  ARGPARSE_s_n (oEnableExtendedKeyFormat, "enable-extended-key-format", "@"),
 
   /* Dummy options for backward compatibility.  */
   ARGPARSE_o_s (oWriteEnvFile, "write-env-file", "@"),
@@ -790,6 +792,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       opt.check_passphrase_pattern = NULL;
       opt.max_passphrase_days = MAX_PASSPHRASE_DAYS;
       opt.enable_passphrase_history = 0;
+      opt.enable_extended_key_format = 0;
       opt.ignore_cache_for_signing = 0;
       opt.allow_mark_trusted = 1;
       opt.allow_external_cache = 1;
@@ -859,6 +862,10 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       opt.enable_passphrase_history = 1;
       break;
 
+    case oEnableExtendedKeyFormat:
+      opt.enable_extended_key_format = 1;
+      break;
+
     case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
 
     case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break;
index b72892c..ca9d469 100644 (file)
@@ -571,6 +571,15 @@ local gpg-agent and use its private keys.  This enables decrypting or
 signing data on a remote machine without exposing the private keys to the
 remote machine.
 
+@anchor{option --enable-extended-key-format}
+@item --enable-extended-key-format
+@opindex enable-extended-key-format
+This option creates keys in the extended private key format.  Changing
+the passphrase of a key will also convert the key to that new format.
+Using this option makes the private keys unreadable for gpg-agent
+versions before 2.1.12.  The advantage of the extended private key
+format is that it is text based and can carry additional meta data.
+
 
 @anchor{option --enable-ssh-support}
 @item --enable-ssh-support