Patches gpg-agent + scute for ssl/tls auth using opengpg card with 2048 rsa key

Werner Koch wk at gnupg.org
Fri Sep 12 15:50:17 CEST 2014


On Sun, 31 Aug 2014 12:04, oliverml1 at oli1170.net said:

> I prefer to leave the tuning of the details to the specialists ;).

Well, I coded something up but did not test it.  Can you please apply
the attached patch to Scute and try it?  No need for any GnuPG patches.


Salam-Shalom,

   Werner

>From a797aae1476601cdde7152174c02c5cc4447bcc5 Mon Sep 17 00:00:00 2001
From: Werner Koch <wk at gnupg.org>
Date: Fri, 12 Sep 2014 15:46:41 +0200
Subject: [PATCH] Allow signing with other algorithms than MD5+SHA1.

* src/support.h (STR, STR2): NEw.
* src/agent.c (sha1_prefix, sha224_prefix, sha256_prefix)
(sha384_prefix, sha512_prefix): New.
(scute_agent_sign): Increase MAX_DATA_LEN to 64.  Determine hash
algorithm by checking the ASN.1 prefixes.
---
 src/agent.c   |  105 ++++++++++++++++++++++++++++++++++++++++++---------------
 src/support.h |   10 ++++--
 2 files changed, 85 insertions(+), 30 deletions(-)

diff --git a/src/agent.c b/src/agent.c
index 9265ca2..edf8d2d 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -2,7 +2,7 @@
    Copyright (C) 2006, 2007, 2008 g10 Code GmbH
 
    This file is part of Scute.
- 
+
    Scute is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
@@ -65,7 +65,7 @@ static int agent_version_minor;
 
 
 /* Hack required for Windows.  */
-void 
+void
 gnupg_allow_set_foregound_window (pid_t pid)
 {
   if (!pid || pid == (pid_t)(-1))
@@ -111,7 +111,7 @@ build_w32_commandline_copy (char *buffer, const char *string)
 /* Build a command line for use with W32's CreateProcess.  On success
    CMDLINE gets the address of a newly allocated string.  */
 static gpg_error_t
-build_w32_commandline (const char *pgmname, const char * const *argv, 
+build_w32_commandline (const char *pgmname, const char * const *argv,
                        char **cmdline)
 {
   int i, n;
@@ -139,7 +139,7 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
     return gpg_error_from_syserror ();
 
   p = build_w32_commandline_copy (p, pgmname);
-  for (i=0; argv[i]; i++) 
+  for (i=0; argv[i]; i++)
     {
       *p++ = ' ';
       p = build_w32_commandline_copy (p, argv[i]);
@@ -161,7 +161,7 @@ spawn_process_detached (const char *pgmname, const char *argv[])
 {
   gpg_error_t err;
   SECURITY_ATTRIBUTES sec_attr;
-  PROCESS_INFORMATION pi = 
+  PROCESS_INFORMATION pi =
     {
       NULL,      /* Returns process handle.  */
       0,         /* Returns primary thread handle.  */
@@ -179,11 +179,11 @@ spawn_process_detached (const char *pgmname, const char *argv[])
   memset (&sec_attr, 0, sizeof sec_attr );
   sec_attr.nLength = sizeof sec_attr;
   sec_attr.bInheritHandle = FALSE;
-  
+
   /* Build the command line.  */
   err = build_w32_commandline (pgmname, argv, &cmdline);
   if (err)
-    return err; 
+    return err;
 
   /* Start the process.  */
   memset (&si, 0, sizeof si);
@@ -194,7 +194,7 @@ spawn_process_detached (const char *pgmname, const char *argv[])
   cr_flags = (CREATE_DEFAULT_ERROR_MODE
               | GetPriorityClass (GetCurrentProcess ())
               | CREATE_NEW_PROCESS_GROUP
-              | DETACHED_PROCESS); 
+              | DETACHED_PROCESS);
   DEBUG (DBG_INFO, "CreateProcess(detached), path=`%s' cmdline=`%s'\n",
 	 pgmname, cmdline);
   if (!CreateProcess (pgmname,       /* Program to start.  */
@@ -221,7 +221,7 @@ spawn_process_detached (const char *pgmname, const char *argv[])
 	 " dwProcessID=%d dwThreadId=%d\n", pi.hProcess, pi.hThread,
 	 (int) pi.dwProcessId, (int) pi.dwThreadId);
 
-  CloseHandle (pi.hThread); 
+  CloseHandle (pi.hThread);
 
   return 0;
 }
@@ -280,8 +280,8 @@ agent_connect (assuan_context_t *ctx_r)
             const char *argv[3];
 
             argv[0] = "--daemon";
-            argv[1] = "--use-standard-socket"; 
-            argv[2] = NULL;  
+            argv[1] = "--use-standard-socket";
+            argv[2] = NULL;
 
             err = spawn_process_detached (agent_program, argv);
             if (err)
@@ -306,15 +306,15 @@ agent_connect (assuan_context_t *ctx_r)
               pgmname = agent_program;
             else
               pgmname++;
-            
+
             argv[0] = pgmname;
             argv[1] = "--server";
             argv[2] = NULL;
-            
+
             i=0;
             no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
             no_close_list[i] = -1;
-            
+
             /* Connect to the agent and perform initial handshaking. */
             err = assuan_pipe_connect (ctx, agent_program, argv,
 				       no_close_list, NULL, NULL, 0);
@@ -353,7 +353,7 @@ agent_connect (assuan_context_t *ctx_r)
 	  force_pipe_server = 1;
 	  goto restart;
 	}
-      
+
       err = assuan_socket_connect (ctx, infostr, pid, 0);
       free (infostr);
       if (err)
@@ -400,7 +400,7 @@ default_inq_cb (void *opaque, const char *line)
 
 
 /* Send a simple command to the agent.  */
-static gpg_error_t 
+static gpg_error_t
 agent_simple_cmd (assuan_context_t ctx, const char *fmt, ...)
 {
   gpg_error_t err;
@@ -421,7 +421,7 @@ agent_simple_cmd (assuan_context_t ctx, const char *fmt, ...)
     DEBUG (DBG_CRIT, "gpg-agent command '%s' failed: %s", optstr,
 	   gpg_strerror (err));
   free (optstr);
-      
+
   return err;
 }
 
@@ -432,7 +432,7 @@ read_version_cb (void *opaque, const void *buffer, size_t length)
 {
   char version[20];
   const char *s;
-  
+
   if (length > sizeof (version) -1)
     length = sizeof (version) - 1;
   strncpy (version, buffer, length);
@@ -444,7 +444,7 @@ read_version_cb (void *opaque, const void *buffer, size_t length)
 
   return 0;
 }
-  
+
 
 /* Configure the GPG agent at connection CTX.  */
 static gpg_error_t
@@ -615,7 +615,7 @@ unescape_status_string (const unsigned char *src)
   while (*src)
     {
       if (*src == '%' && src[1] && src[2])
-        { 
+        {
           src++;
           *dst = xtoi_2 (src);
           if (*dst == '\0')
@@ -631,7 +631,7 @@ unescape_status_string (const unsigned char *src)
       else
         *(dst++) = *(src++);
     }
-  *dst = 0; 
+  *dst = 0;
 
   return buffer;
 }
@@ -894,7 +894,7 @@ geteventcounter_status_cb (void *opaque, const char *line)
           last_count = count;
         }
     }
-  
+
   return 0;
 }
 
@@ -989,6 +989,28 @@ pksign_cb (void *opaque, const void *buffer, size_t length)
 #define SIG_LEN 128
 #define SIG_LEN_2 256
 
+
+static unsigned char sha1_prefix[15] =   /* (1.3.14.3.2.26) */
+  { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
+    0x02, 0x1a, 0x05, 0x00, 0x04, 0x14  };
+static unsigned char sha224_prefix[19] = /* (2.16.840.1.101.3.4.2.4) */
+  { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
+    0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
+    0x1C  };
+static unsigned char sha256_prefix[19] = /* (2.16.840.1.101.3.4.2.1) */
+  { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+    0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
+    0x00, 0x04, 0x20  };
+static unsigned char sha384_prefix[19] = /* (2.16.840.1.101.3.4.2.2) */
+  { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+    0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
+    0x00, 0x04, 0x30  };
+static unsigned char sha512_prefix[19] = /* (2.16.840.1.101.3.4.2.3) */
+  { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+    0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
+    0x00, 0x04, 0x40  };
+
+
 /* Call the agent to learn about a smartcard.  */
 gpg_error_t
 scute_agent_sign (char *grip, unsigned char *data, int len,
@@ -996,10 +1018,12 @@ scute_agent_sign (char *grip, unsigned char *data, int len,
 {
   char cmd[150];
   gpg_error_t err;
-#define MAX_DATA_LEN 36
+#define MAX_DATA_LEN 64  /* For SHA-512 - see below.  */
   unsigned char pretty_data[2 * MAX_DATA_LEN + 1];
   int i;
   struct signature sig;
+  const char *algostr;
+  int off;
 
   sig.len = 0;
 
@@ -1025,11 +1049,38 @@ scute_agent_sign (char *grip, unsigned char *data, int len,
   if (err)
     return err;
 
+  /* Find out the digest algorithm and strip off the prefix.  */
+#define X(a,b)                                                  \
+  (len == sizeof a ## _prefix + (b)                             \
+   && !memcmp (data, a ## _prefix, sizeof a ## _prefix))        \
+    {                                                           \
+      algostr = STR(a);                                         \
+      off = sizeof a ## _prefix;                                \
+      len -= sizeof a ## _prefix;                               \
+    }
+
+  if (len == 36)
+    {
+      algostr = "tls-md5sha1";
+      off = 0;
+    }
+  else if X(sha1,   20)
+  else if X(sha224, 28)
+  else if X(sha256, 32)
+  else if X(sha384, 48)
+  else if X(sha512, 64)  /* MAX_DATA_LEN must be at least this.  */
+  else
+    {
+      DEBUG (DBG_INFO, "sign input data format is unknown, size=%d\n", len);
+      return gpg_error (GPG_ERR_DIGEST_ALGO);
+    }
+#undef X
+
   for (i = 0; i < len; i++)
-    snprintf (&pretty_data[2 * i], 3, "%02X", data[i]);
+    snprintf (&pretty_data[2 * i], 3, "%02X", data[off+i]);
   pretty_data[2 * len] = '\0';
 
-  snprintf (cmd, sizeof (cmd), "SETHASH --hash=tls-md5sha1 %s", pretty_data);
+  snprintf (cmd, sizeof (cmd), "SETHASH --hash=%s %s", algostr, pretty_data);
   err = assuan_transact (agent_ctx, cmd, NULL, NULL, default_inq_cb,
 			 NULL, NULL, NULL);
   if (err)
@@ -1063,8 +1114,8 @@ scute_agent_sign (char *grip, unsigned char *data, int len,
       memcpy (sig_result, sig.data + SIG_PREFIX_LEN, SIG_LEN);
       *sig_len = SIG_LEN;
     }
-  
-  
+
+
   return 0;
 }
 
diff --git a/src/support.h b/src/support.h
index 8f4d538..f6bb80c 100644
--- a/src/support.h
+++ b/src/support.h
@@ -2,7 +2,7 @@
    Copyright (C) 2006 g10 Code GmbH
 
    This file is part of Scute.
- 
+
    Scute is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
@@ -40,6 +40,10 @@
 #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
 
 #define DIM(x) (sizeof (x) / sizeof (x[0]))
+#ifndef STR
+# define STR(v) #v
+#endif
+#define STR2(v) STR(v)
 
 /* Copy a string into its location, with blank character padding.  */
 static inline void
@@ -64,7 +68,7 @@ scute_copy_string (char *dest, char *src, int max_len)
 #ifndef HAVE_TTYNAME
 /* Systems without ttyname (W32) will merely return NULL. */
 static inline char *
-ttyname (int fd) 
+ttyname (int fd)
 {
   return NULL;
 }
@@ -96,5 +100,5 @@ const char *default_homedir (void);
 char *make_filename (const char *first_part, ...);
 
 
-    
+
 #endif	/* !SUPPORT_H */
-- 
1.7.7.1



-- 
Die Gedanken sind frei.  Ausnahmen regelt ein Bundesgesetz.




More information about the Gnupg-devel mailing list