agent: pksign result conversion to sexp to upper layer.
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 28 Feb 2013 02:17:47 +0000 (11:17 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 28 Feb 2013 02:17:47 +0000 (11:17 +0900)
* agent/agent.h (divert_pksign): Add R_SIGLEN argument.
* agent/divert-scd.c (divert_pksign): Return length at R_SIGLEN.
* agent/call-scd.c (agent_card_pksign): Move composition of
S-expression to...
* agent/pksign.c (agent_pksign_do): ... here.
--

Composing S-expression would be better to be done by SCDaemon.

agent/agent.h
agent/call-scd.c
agent/divert-scd.c
agent/pksign.c

index 030b295..2fd0b8b 100644 (file)
@@ -405,7 +405,8 @@ void agent_reload_trustlist (void);
 /*-- divert-scd.c --*/
 int divert_pksign (ctrl_t ctrl,
                    const unsigned char *digest, size_t digestlen, int algo,
-                   const unsigned char *shadow_info, unsigned char **r_sig);
+                   const unsigned char *shadow_info, unsigned char **r_sig,
+                   size_t *r_siglen);
 int divert_pkdecrypt (ctrl_t ctrl,
                       const unsigned char *cipher,
                       const unsigned char *shadow_info,
index f4ea20b..a334b15 100644 (file)
@@ -825,10 +825,6 @@ agent_card_pksign (ctrl_t ctrl,
   char *p, line[ASSUAN_LINELENGTH];
   membuf_t data;
   struct inq_needpin_s inqparm;
-  size_t len;
-  unsigned char *sigbuf;
-  size_t sigbuflen;
-  int prepend_nul;
 
   *r_buf = NULL;
   rc = start_scd (ctrl);
@@ -868,32 +864,13 @@ agent_card_pksign (ctrl_t ctrl,
 
   if (rc)
     {
+      size_t len;
+
       xfree (get_membuf (&data, &len));
       return unlock_scd (ctrl, rc);
     }
-  sigbuf = get_membuf (&data, &sigbuflen);
-
-  /* Create an S-expression from it which is formatted like this:
-     "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))".  We better make sure
-     that this won't be interpreted as a negative number.  */
-  prepend_nul = (sigbuflen && (*sigbuf & 0x80));
-
-  *r_buflen = 21 + 11 + prepend_nul + sigbuflen + 4;
-  p = xtrymalloc (*r_buflen);
-  *r_buf = (unsigned char*)p;
-  if (!p)
-    return unlock_scd (ctrl, out_of_core ());
-  p = stpcpy (p, "(7:sig-val(3:rsa(1:s" );
-  sprintf (p, "%u:", (unsigned int)sigbuflen + prepend_nul);
-  p += strlen (p);
-  if (prepend_nul)
-    *p++ = 0;
-  memcpy (p, sigbuf, sigbuflen);
-  p += sigbuflen;
-  strcpy (p, ")))");
-  xfree (sigbuf);
-
-  assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
+
+  *r_buf = get_membuf (&data, r_buflen);
   return unlock_scd (ctrl, 0);
 }
 
index 5fb037e..f0d8473 100644 (file)
@@ -335,7 +335,8 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
 int
 divert_pksign (ctrl_t ctrl,
                const unsigned char *digest, size_t digestlen, int algo,
-               const unsigned char *shadow_info, unsigned char **r_sig)
+               const unsigned char *shadow_info, unsigned char **r_sig,
+               size_t *r_siglen)
 {
   int rc;
   char *kid;
@@ -369,7 +370,10 @@ divert_pksign (ctrl_t ctrl,
     }
 
   if (!rc)
-    *r_sig = sigval;
+    {
+      *r_sig = sigval;
+      *r_siglen = siglen;
+    }
 
   xfree (kid);
 
index dc44b88..8518730 100644 (file)
@@ -278,24 +278,104 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
   if (!s_skey)
     {
       /* Divert operation to the smartcard */
-
+      gcry_sexp_t s_pkey, l;
+      const char *name;
+      size_t len;
       unsigned char *buf = NULL;
-      size_t len = 0;
+      int is_RSA = 0;
+      int is_ECDSA = 0;
+
+      /* Check keytype by public key */
+      rc = agent_public_key_from_file (ctrl, ctrl->keygrip, &s_pkey);
+      if (rc)
+        {
+          log_error ("failed to read the public key\n");
+          goto leave;
+        }
+      l = gcry_sexp_cadr (s_pkey);
+      name = gcry_sexp_nth_data (l, 0, &len);
+      if (len == 3 && !memcmp (name, "rsa", 3))
+        is_RSA = 1;
+      else if (len == 5 && !memcmp (name, "ecdsa", 5))
+        is_ECDSA = 1;
+      gcry_sexp_release (l);
+      gcry_sexp_release (s_pkey);
 
       rc = divert_pksign (ctrl,
                           ctrl->digest.value,
                           ctrl->digest.valuelen,
                           ctrl->digest.algo,
-                          shadow_info, &buf);
+                          shadow_info, &buf, &len);
       if (rc)
         {
           log_error ("smartcard signing failed: %s\n", gpg_strerror (rc));
           goto leave;
         }
-      len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
-      assert (len);
 
-      rc = gcry_sexp_sscan (&s_sig, NULL, (char*)buf, len);
+      if (is_RSA)
+        {
+          if (*buf & 0x80)
+            {
+              len++;
+              buf = xtryrealloc (buf, len);
+              if (!buf)
+                goto leave;
+
+              memmove (buf + 1, buf, len - 1);
+              *buf = 0;
+            }
+
+          rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%b)))", len, buf);
+        }
+      else if (is_ECDSA)
+        {
+          unsigned char *r_buf_allocated = NULL;
+          unsigned char *s_buf_allocated = NULL;
+          unsigned char *r_buf, *s_buf;
+          int r_buflen, s_buflen;
+
+          r_buflen = s_buflen = len/2;
+
+          if (*buf & 0x80)
+            {
+              r_buflen++;
+              r_buf_allocated = xtrymalloc (r_buflen);
+              if (!r_buf_allocated)
+                goto leave;
+
+              r_buf = r_buf_allocated;
+              memcpy (r_buf + 1, buf, len/2);
+              *r_buf = 0;
+            }
+          else
+            r_buf = buf;
+
+          if (*(buf + len/2) & 0x80)
+            {
+              s_buflen++;
+              s_buf_allocated = xtrymalloc (s_buflen);
+              if (!s_buf_allocated)
+                {
+                  xfree (r_buf_allocated);
+                  goto leave;
+                }
+
+              s_buf = s_buf_allocated;
+              memcpy (s_buf + 1, buf + len/2, len/2);
+              *s_buf = 0;
+            }
+          else
+            s_buf = buf + len/2;
+
+          rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(ecdsa(r%b)(s%b)))",
+                                r_buflen, r_buf,
+                                s_buflen, s_buf);
+          xfree (r_buf_allocated);
+          xfree (s_buf_allocated);
+        }
+      else
+        rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
       xfree (buf);
       if (rc)
        {