* call-scd.c (inq_needpin): Skip leading spaces in of PIN
[gnupg.git] / agent / protect.c
index df8a9bf..658c8c5 100644 (file)
@@ -46,6 +46,8 @@ static struct {
   int prot_from, prot_to;
 } protect_info[] = {
   { "rsa",  "nedpqu", 2, 5 },
+  { "dsa",  "pqgyx", 4, 4 },
+  { "elg",  "pgyx", 3, 3 },
   { NULL }
 };
 
@@ -58,7 +60,7 @@ hash_passphrase (const char *passphrase, int hashalgo,
 
 
 \f
-/* Calculate the MIC for a private key S-Exp. SHA1HASH should pint to
+/* Calculate the MIC for a private key S-Exp. SHA1HASH should point to
    a 20 byte buffer.  This function is suitable for any algorithms. */
 static int 
 calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
@@ -115,7 +117,7 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
 \f
 /* Encrypt the parameter block starting at PROTBEGIN with length
    PROTLEN using the utf8 encoded key PASSPHRASE and return the entire
-   encrypted block in RESULT or ereturn with an error code.  SHA1HASH
+   encrypted block in RESULT or return with an error code.  SHA1HASH
    is the 20 byte SHA-1 hash required for the integrity code.
 
    The parameter block is expected to be an incomplete S-Expression of
@@ -432,13 +434,13 @@ do_decryption (const unsigned char *protected, size_t protectedlen,
       xfree (outbuf);
       return rc;
     }
-  /* do a quick check first */
+  /* Do a quick check first. */
   if (*outbuf != '(' && outbuf[1] != '(')
     {
       xfree (outbuf);
       return gpg_error (GPG_ERR_BAD_PASSPHRASE);
     }
-  /* check that we have a consistent S-Exp */
+  /* Check that we have a consistent S-Exp. */
   reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL);
   if (!reallen || (reallen + blklen < protectedlen) )
     {
@@ -458,7 +460,8 @@ static int
 merge_lists (const unsigned char *protectedkey,
              size_t replacepos, 
              const unsigned char *cleartext,
-             unsigned char *sha1hash, unsigned char **result)
+             unsigned char *sha1hash,
+             unsigned char **result, size_t *resultlen)
 {
   size_t n, newlistlen;
   unsigned char *newlist, *p;
@@ -559,13 +562,16 @@ merge_lists (const unsigned char *protectedkey,
 
   /* ready */
   *result = newlist;
+  *resultlen = newlistlen;
   return 0;
 
  failure:
+  wipememory (newlist, newlistlen);
   xfree (newlist);
   return rc;
 
  invalid_sexp:
+  wipememory (newlist, newlistlen);
   xfree (newlist);
   return gpg_error (GPG_ERR_INV_SEXP);
 }
@@ -589,6 +595,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
   const unsigned char *prot_begin;
   unsigned char *cleartext;
   unsigned char *final;
+  size_t finallen;
 
   s = protectedkey;
   if (*s != '(')
@@ -612,7 +619,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
   if (!protect_info[infidx].algo)
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); 
 
-  /* now find the list with the protected information.  Here is an
+  /* Now find the list with the protected information.  Here is an
      example for such a list:
      (protected openpgp-s2k3-sha1-aes-cbc 
         ((sha1 <salt> <count>) <Initialization_Vector>)
@@ -669,7 +676,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
   s++; /* skip list end */
 
   n = snext (&s);
-  if (n != 16) /* Wrong blocksize for IV (we support ony aes-128) */
+  if (n != 16) /* Wrong blocksize for IV (we support only aes-128). */
     return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
   iv = s;
   s += n;
@@ -688,7 +695,11 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
     return rc;
 
   rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext,
-                    sha1hash, &final);
+                    sha1hash, &final, &finallen);
+  /* Albeit cleartext has been allocated in secure memory and thus
+     xfree will wipe it out, we do an extra wipe just in case
+     somethings goes badly wrong. */
+  wipememory (cleartext, n);
   xfree (cleartext);
   if (rc)
     return rc;
@@ -698,6 +709,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
     rc = gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
   if (rc)
     {
+      wipememory (final, finallen);
       xfree (final);
       return rc;
     }
@@ -819,10 +831,43 @@ hash_passphrase (const char *passphrase, int hashalgo,
 
 
 \f
+
+/* Create an canonical encoded S-expression with the shadow info from
+   a card's SERIALNO and the IDSTRING.  */
+unsigned char *
+make_shadow_info (const char *serialno, const char *idstring)
+{
+  const char *s;
+  unsigned char *info, *p;
+  char numbuf[21];
+  int n;
+
+  for (s=serialno, n=0; *s && s[1]; s += 2)
+    n++;
+
+  info = p = xtrymalloc (1 + 21 + n
+                           + 21 + strlen (idstring) + 1 + 1);
+  if (!info)
+    return NULL;
+  *p++ = '(';
+  sprintf (numbuf, "%d:", n);
+  p = stpcpy (p, numbuf);
+  for (s=serialno; *s && s[1]; s += 2)
+    *p++ = xtoi_2 (s);
+  sprintf (numbuf, "%d:", strlen (idstring));
+  p = stpcpy (p, numbuf);
+  p = stpcpy (p, idstring);
+  *p++ = ')';
+  *p = 0;
+  return info;
+}
+
+
+
 /* Create a shadow key from a public key.  We use the shadow protocol
   "ti-v1" and insert the S-expressionn SHADOW_INFO.  The resulting
   S-expression is returned in an allocated buffer RESULT will point
-  to. The input parameters are expected to be valid canonilized
+  to. The input parameters are expected to be valid canonicalized
   S-expressions */
 int 
 agent_shadow_key (const unsigned char *pubkey,
@@ -882,7 +927,7 @@ agent_shadow_key (const unsigned char *pubkey,
   s++;
   assert (depth == 1);
 
-  /* calculate required length by taking in account: the "shadowed-"
+  /* Calculate required length by taking in account: the "shadowed-"
      prefix, the "shadowed", "t1-v1" as well as some parenthesis */
   n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
   *result = p = xtrymalloc (n);
@@ -954,7 +999,7 @@ agent_get_shadow_info (const unsigned char *shadowkey,
       depth--;
       s++;
     }
-  /* found the shadowed list, s points to the protocol */
+  /* Found the shadowed list, S points to the protocol */
   n = snext (&s);
   if (!n) 
     return gpg_error (GPG_ERR_INV_SEXP);