Forgot to remove the unsued variable.
[gnupg.git] / agent / pksign.c
index bdf1ff4..3022e79 100644 (file)
@@ -1,5 +1,5 @@
 /* pksign.c - public key signing (well, acually using a secret key)
- *     Copyright (C) 2001 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 
 
 static int
-do_encode_md (const unsigned char *digest, size_t digestlen, int algo,
-              unsigned int nbits, GCRY_MPI *r_val)
+do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash)
 {
-  int nframe = (nbits+7) / 8;
-  byte *frame;
-  int i, n;
-  byte asn[100];
-  size_t asnlen;
-
-  asnlen = DIM(asn);
-  if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
+  gcry_sexp_t hash;
+  const char * s;
+  char * p, tmp[16];
+  int i, rc;
+
+  p = xmalloc (64+mdlen);
+  s = gcry_md_algo_name (algo);
+  if (s && strlen (s) < 16)
     {
-      log_error ("No object identifier for algo %d\n", algo);
-      return GNUPG_Internal_Error;
+      for (i=0; i < strlen (s); i++)
+        tmp[i] = tolower (s[i]);
+      tmp[i] = '\0';   
     }
-
-  if (digestlen + asnlen + 4  > nframe )
+  sprintf (p, "(data\n (flags pkcs1)\n (hash %s #", tmp);
+  for (i=0; i < mdlen; i++)
     {
-      log_error ("can't encode a %d bit MD into a %d bits frame\n",
-                 (int)(digestlen*8), (int)nbits);
-      return GNUPG_Internal_Error;
+      sprintf (tmp, "%02x", md[i]);
+      strcat (p, tmp);   
     }
-  
-  /* We encode the MD in this way:
-   *
-   *      0  1 PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
-   *
-   * PAD consists of FF bytes.
-   */
-  frame = xtrymalloc (nframe);
-  if (!frame)
-    return GNUPG_Out_Of_Core;
-  n = 0;
-  frame[n++] = 0;
-  frame[n++] = 1; /* block type */
-  i = nframe - digestlen - asnlen -3 ;
-  assert ( i > 1 );
-  memset ( frame+n, 0xff, i ); n += i;
-  frame[n++] = 0;
-  memcpy ( frame+n, asn, asnlen ); n += asnlen;
-  memcpy ( frame+n, digest, digestlen ); n += digestlen;
-  assert ( n == nframe );
-  if (DBG_CRYPTO)
-    log_printhex ("encoded hash:", frame, nframe);
-      
-  gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, &nframe);
-  xfree (frame);
-  return 0;
+  strcat (p, "#))\n");
+  rc = gcry_sexp_sscan (&hash, NULL, p, strlen (p));
+  xfree (p);
+  *r_hash = hash;
+  return rc;   
 }
 
 
 /* SIGN whatever information we have accumulated in CTRL and write it
    back to OUTFP. */
 int
-agent_pksign (CTRL ctrl, FILE *outfp) 
+agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache
 {
-  GCRY_SEXP s_skey = NULL, s_hash = NULL, s_sig = NULL;
-  GCRY_MPI frame = NULL;
+  gcry_sexp_t s_skey = NULL, s_hash = NULL, s_sig = NULL;
   unsigned char *shadow_info = NULL;
   int rc;
   char *buf = NULL;
   size_t len;
 
   if (!ctrl->have_keygrip)
-    return seterr (No_Secret_Key);
+    return gpg_error (GPG_ERR_NO_SECKEY);
 
-  s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info);
+  s_skey = agent_key_from_file (ctrl,
+                                ctrl->keygrip, &shadow_info, ignore_cache);
   if (!s_skey && !shadow_info)
     {
       log_error ("failed to read the secret key\n");
-      rc = seterr (No_Secret_Key);
+      rc = gpg_error (GPG_ERR_NO_SECKEY);
       goto leave;
     }
 
-  /* put the hash into a sexp FIXME: this belongs into libgcrypt/divert-scd.c*/
-  rc = do_encode_md (ctrl->digest.value,
-                     ctrl->digest.valuelen,
-                     ctrl->digest.algo,
-                     gcry_pk_get_nbits (s_skey),
-                     &frame);
-  if (rc)
-    goto leave;
-  if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
-    BUG ();
-
   if (!s_skey)
     { /* divert operation to the smartcard */
-      rc = divert_pksign (&s_sig, s_hash, shadow_info);
+      unsigned char *sigbuf;
+
+      rc = divert_pksign (ctrl, 
+                          ctrl->digest.value, 
+                          ctrl->digest.valuelen,
+                          ctrl->digest.algo,
+                          shadow_info, &sigbuf);
       if (rc)
         {
-          log_error ("smartcard signing failed: %s\n", gnupg_strerror (rc));
+          log_error ("smartcard signing failed: %s\n", gpg_strerror (rc));
           goto leave;
         }
+      len = gcry_sexp_canon_len (sigbuf, 0, NULL, NULL);
+      assert (len);
+      buf = sigbuf;
     }
   else
     { /* no smartcard, but a private key */
+
+      /* put the hash into a sexp */
+      rc = do_encode_md (ctrl->digest.value,
+                         ctrl->digest.valuelen,
+                         ctrl->digest.algo,
+                         &s_hash);
+      if (rc)
+        goto leave;
+
       if (DBG_CRYPTO)
         {
           log_debug ("skey: ");
@@ -138,23 +123,23 @@ agent_pksign (CTRL ctrl, FILE *outfp)
       rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
       if (rc)
         {
-          log_error ("signing failed: %s\n", gcry_strerror (rc));
+          log_error ("signing failed: %s\n", gpg_strerror (rc));
           rc = map_gcry_err (rc);
           goto leave;
         }
-    }
 
-  if (DBG_CRYPTO)
-    {
-      log_debug ("result: ");
-      gcry_sexp_dump (s_sig);
-    }
+      if (DBG_CRYPTO)
+        {
+          log_debug ("result: ");
+          gcry_sexp_dump (s_sig);
+        }
 
-  len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0);
-  assert (len);
-  buf = xmalloc (len);
-  len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len);
-  assert (len);
+      len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0);
+      assert (len);
+      buf = xmalloc (len);
+      len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len);
+      assert (len);
+    }
 
   /* FIXME: we must make sure that no buffering takes place or we are
      in full control of the buffer memory (easy to do) - should go
@@ -165,7 +150,6 @@ agent_pksign (CTRL ctrl, FILE *outfp)
   gcry_sexp_release (s_skey);
   gcry_sexp_release (s_hash);
   gcry_sexp_release (s_sig);
-  gcry_mpi_release (frame);
   xfree (buf);
   xfree (shadow_info);
   return rc;