* agent.h: Add a callback function to the pin_entry_info structure.
[gnupg.git] / agent / divert-scd.c
index 9b176a6..f2a26ac 100644 (file)
@@ -43,6 +43,7 @@ ask_for_card (const unsigned char *shadow_info, char **r_kid)
   int no_card = 0;
   char *desc;
   char *want_sn, *want_kid;
+  int want_sn_displen;
 
   *r_kid = NULL;
   s = shadow_info;
@@ -58,6 +59,12 @@ ask_for_card (const unsigned char *shadow_info, char **r_kid)
   for (i=0; i < n; i++)
     sprintf (want_sn+2*i, "%02X", s[i]);
   s += n;
+  /* We assume that a 20 byte serial number is a standard one which
+     seems to have the property to have a zero in the last nibble.  We
+     don't display this '0' because it may confuse the user */
+  want_sn_displen = strlen (want_sn);
+  if (want_sn_displen == 20 && want_sn[19] == '0')
+    want_sn_displen--;
 
   n = snext (&s);
   if (!n)
@@ -102,17 +109,17 @@ ask_for_card (const unsigned char *shadow_info, char **r_kid)
         {
           if (asprintf (&desc,
                     "%s:%%0A%%0A"
-                    "  \"%s\"",
+                    "  \"%.*s\"",
                     no_card? "Please insert the card with serial number" 
                     : "Please remove the current card and "
                     "insert the one with serial number",
-                    want_sn) < 0)
+                    want_sn_displen, want_sn) < 0)
             {
               rc = GNUPG_Out_Of_Core;
             }
           else
             {
-              rc = agent_get_confirmation (desc, NULL);
+              rc = agent_get_confirmation (desc, NULL, NULL);
               free (desc);
             }
         }
@@ -126,15 +133,12 @@ ask_for_card (const unsigned char *shadow_info, char **r_kid)
 }
 
 
-/* fixme: this should be moved to libgcrypt and only be used if the
-   smartcard does not support pkcs-1 itself */
+/* Put the DIGEST into an DER encoded comtainer and return it in R_VAL. */
 static int
 encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
-                    unsigned int nbits, unsigned char **r_val, size_t *r_len)
+                    unsigned char **r_val, size_t *r_len)
 {
-  int nframe = (nbits+7) / 8;
   byte *frame;
-  int i, n;
   byte asn[100];
   size_t asnlen;
 
@@ -145,37 +149,16 @@ encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
       return GNUPG_Internal_Error;
     }
 
-  if (digestlen + asnlen + 4  > nframe )
-    {
-      log_error ("can't encode a %d bit MD into a %d bits frame\n",
-                 (int)(digestlen*8), (int)nbits);
-      return GNUPG_Internal_Error;
-    }
-  
-  /* 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);
+  frame = xtrymalloc (asnlen + digestlen);
   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 );
+  memcpy (frame, asn, asnlen);
+  memcpy (frame+asnlen, digest, digestlen);
   if (DBG_CRYPTO)
-    log_printhex ("encoded hash:", frame, nframe);
+    log_printhex ("encoded hash:", frame, asnlen+digestlen);
       
   *r_val = frame;
-  *r_len = nframe;
+  *r_len = asnlen+digestlen;
   return 0;
 }
 
@@ -183,7 +166,7 @@ encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
 /* Callback used to ask for the PIN which should be set into BUF.  The
    buf has been allocated by the caller and is of size MAXBUF which
    includes the terminating null.  The function should return an UTF-8
-   string with the passphrase, the buffer may optioanlly be padded
+   string with the passphrase, the buffer may optionally be padded
    with arbitrary characters */
 static int 
 getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
@@ -191,35 +174,27 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
   struct pin_entry_info_s *pi;
   int rc;
   int tries = 0;
-  const char *errtext;
-  
+
   assert (!opaque);
 
   if (maxbuf < 2)
     return GNUPG_Invalid_Value;
 
-  /* FIXME: keep PI and TRIES in OPAQUE */
+  /* FIXME: keep PI and TRIES in OPAQUE.  Actually this is a whole
+     mess becuase we should call the card's verify function from the
+     pinentry check pin CB. */
   pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
   pi->max_length = maxbuf-1;
   pi->min_digits = 0;  /* we want a real passphrase */
   pi->max_digits = 8;
   pi->max_tries = 3;
 
-  errtext = NULL;
-  do
+  rc = agent_askpin (info, pi);
+  if (!rc)
     {
-      rc = agent_askpin (info, errtext, pi);
-      if (!rc)
-        {
-          strncpy (buf, pi->pin, maxbuf-1);
-          buf[maxbuf-1] = 0;
-          xfree (pi);
-          return 0;
-        }
-      errtext = pi->min_digits? trans ("Bad PIN") : trans ("Bad Passphrase");
+      strncpy (buf, pi->pin, maxbuf-1);
+      buf[maxbuf-1] = 0;
     }
-  while ((rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
-         && tries++ < 3);
   xfree (pi);
   return rc;
 }
@@ -242,7 +217,7 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
   if (rc)
     return rc;
 
-  rc = encode_md_for_card (digest, digestlen, algo, 1024 /* fixme*/,
+  rc = encode_md_for_card (digest, digestlen, algo, 
                            &data, &ndata);
   if (rc)
     return rc;