Add missing variable.
[gnupg.git] / agent / pksign.c
index 28e208e..dc44b88 100644 (file)
@@ -43,13 +43,13 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
       const char *s;
       char tmp[16+1];
       int i;
-      
+
       s = gcry_md_algo_name (algo);
       if (s && strlen (s) < 16)
        {
          for (i=0; i < strlen (s); i++)
            tmp[i] = tolower (s[i]);
-         tmp[i] = '\0';   
+         tmp[i] = '\0';
        }
 
       rc = gcry_sexp_build (&hash, NULL,
@@ -59,7 +59,7 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
   else
     {
       gcry_mpi_t mpi;
-      
+
       rc = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, md, mdlen, NULL);
       if (! rc)
        {
@@ -68,11 +68,11 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
                                mpi);
          gcry_mpi_release (mpi);
        }
-         
+
     }
-  
+
   *r_hash = hash;
-  return rc;   
+  return rc;
 }
 
 
@@ -113,24 +113,29 @@ get_dsa_qbits (gcry_sexp_t key)
 
 /* Encode a message digest for use with an DSA algorithm. */
 static gpg_error_t
-do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
+do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
                gcry_sexp_t *r_hash)
 {
   gpg_error_t err;
   gcry_sexp_t hash;
   unsigned int qbits;
+  int pkalgo;
 
   *r_hash = NULL;
 
-  if (dsaalgo == GCRY_PK_ECDSA)
+  pkalgo = map_pk_openpgp_to_gcry (dsaalgo);
+
+  if (pkalgo == GCRY_PK_ECDSA)
     qbits = gcry_pk_get_nbits (pkey);
-  else if (dsaalgo == GCRY_PK_DSA)
+  else if (pkalgo == GCRY_PK_DSA)
     qbits = get_dsa_qbits (pkey);
   else
     return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
-  
-  if ((qbits%8))
+
+  if (pkalgo == GCRY_PK_DSA && (qbits%8))
     {
+      /* FIXME: We check the QBITS but print a message about the hash
+         length.  */
       log_error (_("DSA requires the hash length to be a"
                    " multiple of 8 bits\n"));
       return gpg_error (GPG_ERR_INV_LENGTH);
@@ -143,27 +148,35 @@ do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
   if (qbits < 160)
     {
       log_error (_("%s key uses an unsafe (%u bit) hash\n"),
-                 gcry_pk_algo_name (dsaalgo), qbits);
+                 gcry_pk_algo_name (pkalgo), qbits);
       return gpg_error (GPG_ERR_INV_LENGTH);
     }
 
   /* Check if we're too short.  Too long is safe as we'll
-     automatically left-truncate.  */
-  if (mdlen < qbits/8)
+   * automatically left-truncate.
+   *
+   * This check would require the use of SHA512 with ECDSA 512. I
+   * think this is overkill to fail in this case.  Therefore, relax
+   * the check, but only for ECDSA keys.  We may need to adjust it
+   * later for general case.  (Note that the check is really a bug for
+   * ECDSA 521 as the only hash that matches it is SHA 512, but 512 <
+   * 521 ).
+   */
+  if (mdlen < ((pkalgo==GCRY_PK_ECDSA && qbits > 521) ? 512 : qbits)/8)
     {
       log_error (_("a %zu bit hash is not valid for a %u bit %s key\n"),
                  mdlen*8,
-                 gcry_pk_get_nbits (pkey), 
-                 gcry_pk_algo_name (dsaalgo));
+                 gcry_pk_get_nbits (pkey),
+                 gcry_pk_algo_name (pkalgo));
       /* FIXME: we need to check the requirements for ECDSA.  */
-      if (mdlen < 20 || dsaalgo == GCRY_PK_DSA)
+      if (mdlen < 20 || pkalgo == GCRY_PK_DSA)
         return gpg_error (GPG_ERR_INV_LENGTH);
     }
 
   /* Truncate.  */
   if (mdlen > qbits/8)
     mdlen = qbits/8;
-            
+
   /* Create the S-expression.  We need to convert to an MPI first
      because we want an unsigned integer.  Using %b directly is not
      possible because libgcrypt assumes an mpi and uses
@@ -171,7 +184,7 @@ do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
      value.  */
   {
     gcry_mpi_t mpi;
-      
+
     err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, md, mdlen, NULL);
     if (!err)
       {
@@ -182,7 +195,7 @@ do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey,
   }
   if (!err)
     *r_hash = hash;
-  return err;   
+  return err;
 }
 
 
@@ -198,7 +211,7 @@ do_encode_raw_pkcs1 (const byte *md, size_t mdlen, unsigned int nbits,
   gcry_sexp_t hash;
   unsigned char *frame;
   size_t i, n, nframe;
-            
+
   nframe = (nbits+7) / 8;
   if ( !mdlen || mdlen + 8 + 4 > nframe )
     {
@@ -209,7 +222,7 @@ do_encode_raw_pkcs1 (const byte *md, size_t mdlen, unsigned int nbits,
   frame = xtrymalloc (nframe);
   if (!frame)
     return gpg_error_from_syserror ();
-  
+
   /* Assemble the pkcs#1 block type 1. */
   n = 0;
   frame[n++] = 0;
@@ -222,7 +235,7 @@ do_encode_raw_pkcs1 (const byte *md, size_t mdlen, unsigned int nbits,
   memcpy (frame+n, md, mdlen );
   n += mdlen;
   assert (n == nframe);
-  
+
   /* Create the S-expression.  */
   rc = gcry_sexp_build (&hash, NULL,
                         "(data (flags raw) (value %b))",
@@ -230,16 +243,19 @@ do_encode_raw_pkcs1 (const byte *md, size_t mdlen, unsigned int nbits,
   xfree (frame);
 
   *r_hash = hash;
-  return rc;   
+  return rc;
 }
 
 
 
 /* SIGN whatever information we have accumulated in CTRL and return
    the signature S-expression.  LOOKUP is an optional function to
-   provide a way for lower layers to ask for the caching TTL. */
+   provide a way for lower layers to ask for the caching TTL.  If a
+   CACHE_NONCE is given that cache item is first tried to get a
+   passphrase.  */
 int
-agent_pksign_do (ctrl_t ctrl, const char *desc_text,
+agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
+                 const char *desc_text,
                 gcry_sexp_t *signature_sexp,
                  cache_mode_t cache_mode, lookup_ttl_t lookup_ttl)
 {
@@ -250,9 +266,9 @@ agent_pksign_do (ctrl_t ctrl, const char *desc_text,
   if (! ctrl->have_keygrip)
     return gpg_error (GPG_ERR_NO_SECKEY);
 
-  rc = agent_key_from_file (ctrl, desc_text, ctrl->keygrip,
+  rc = agent_key_from_file (ctrl, cache_nonce, desc_text, ctrl->keygrip,
                             &shadow_info, cache_mode, lookup_ttl,
-                            &s_skey);
+                            &s_skey, NULL);
   if (rc)
     {
       log_error ("failed to read the secret key\n");
@@ -266,8 +282,8 @@ agent_pksign_do (ctrl_t ctrl, const char *desc_text,
       unsigned char *buf = NULL;
       size_t len = 0;
 
-      rc = divert_pksign (ctrl, 
-                          ctrl->digest.value, 
+      rc = divert_pksign (ctrl,
+                          ctrl->digest.value,
                           ctrl->digest.valuelen,
                           ctrl->digest.algo,
                           shadow_info, &buf);
@@ -349,17 +365,18 @@ agent_pksign_do (ctrl_t ctrl, const char *desc_text,
 }
 
 /* SIGN whatever information we have accumulated in CTRL and write it
-   back to OUTFP. */
+   back to OUTFP.  If a CACHE_NONCE is given that cache item is first
+   tried to get a passphrase.  */
 int
-agent_pksign (ctrl_t ctrl, const char *desc_text,
-              membuf_t *outbuf, cache_mode_t cache_mode) 
+agent_pksign (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
+              membuf_t *outbuf, cache_mode_t cache_mode)
 {
   gcry_sexp_t s_sig = NULL;
   char *buf = NULL;
   size_t len = 0;
   int rc = 0;
 
-  rc = agent_pksign_do (ctrl, desc_text, &s_sig, cache_mode, NULL);
+  rc = agent_pksign_do (ctrl, cache_nonce, desc_text, &s_sig, cache_mode, NULL);
   if (rc)
     goto leave;