Add CVE number.
[gnupg.git] / scd / app-nks.c
index 1ca8d41..514ae10 100644 (file)
@@ -1,11 +1,11 @@
 /* app-nks.c - The Telesec NKS 2.0 card application.
- *     Copyright (C) 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2007 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -14,9 +14,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -33,7 +31,8 @@
 #include "app-common.h"
 #include "tlv.h"
 
-static struct {
+static struct
+{
   int fid;       /* File ID. */
   int certtype;  /* Type of certificate or 0 if it is not a certificate. */
   int iskeypair; /* If true has the FID of the correspoding certificate. */
@@ -119,7 +118,7 @@ keygripstr_from_pk_file (int slot, int fid, char *r_gripstr)
 
 
 static gpg_error_t
-do_learn_status (APP app, CTRL ctrl)
+do_learn_status (app_t app, ctrl_t ctrl)
 {
   gpg_error_t err;
   char ct_buf[100], id_buf[100];
@@ -208,8 +207,8 @@ do_readcert (app_t app, const char *certid,
 
   /* If the requested objects is a plain public key, redirect it to
      the corresponding certificate.  The whole system is a bit messy
-     becuase we sometime use the key directly or let the caller
-     retrieve the key from the certificate.  The valid point behind
+     because we sometime use the key directly or let the caller
+     retrieve the key from the certificate.  The rationale for
      that is to support not-yet stored certificates. */
   if (filelist[i].iskeypair)
     fid = filelist[i].iskeypair;
@@ -305,14 +304,43 @@ verify_pin (app_t app,
             gpg_error_t (*pincb)(void*, const char *, char **),
             void *pincb_arg)
 {
+  iso7816_pininfo_t pininfo;
+  int rc;
+
   /* Note that force_chv1 is never set but we do it here anyway so
      that other applications may reuse this function.  For example it
      makes sense to set force_chv1 for German signature law cards.
      NKS is very similar to the DINSIG draft standard. */
-  if (!app->did_chv1 || app->force_chv1 ) 
+  if ( app->did_chv1 && !app->force_chv1 ) 
+    return 0;  /* No need to verify it again.  */
+
+  memset (&pininfo, 0, sizeof pininfo);
+  pininfo.mode = 1;
+  pininfo.minlen = 6;
+  pininfo.maxlen = 16;
+
+  if (!opt.disable_keypad
+      && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
+    {
+      rc = pincb (pincb_arg,
+                  _("||Please enter your PIN at the reader's keypad"),
+                  NULL);
+      if (rc)
+        {
+          log_info (_("PIN callback returned error: %s\n"),
+                    gpg_strerror (rc));
+          return rc;
+        }
+      /* Although it is possible to use a local PIN, we use the global
+         PIN for this application.  */
+      rc = iso7816_verify_kp (app->slot, 0, "", 0, &pininfo); 
+      /* Dismiss the prompt. */
+      pincb (pincb_arg, NULL, NULL);
+    }
+  else
     {
       char *pinvalue;
-      int rc;
 
       rc = pincb (pincb_arg, "PIN", &pinvalue); 
       if (rc)
@@ -323,35 +351,37 @@ verify_pin (app_t app,
 
       /* The following limits are due to TCOS but also defined in the
          NKS specs. */
-      if (strlen (pinvalue) < 6)
+      if (strlen (pinvalue) < pininfo.minlen)
         {
-          log_error ("PIN is too short; minimum length is 6\n");
+          log_error ("PIN is too short; minimum length is %d\n",
+                     pininfo.minlen);
           xfree (pinvalue);
           return gpg_error (GPG_ERR_BAD_PIN);
         }
-      else if (strlen (pinvalue) > 16)
+      else if (strlen (pinvalue) > pininfo.maxlen)
         {
-          log_error ("PIN is too large; maximum length is 16\n");
+          log_error ("PIN is too large; maximum length is %d\n",
+                     pininfo.maxlen);
           xfree (pinvalue);
           return gpg_error (GPG_ERR_BAD_PIN);
         }
 
-      /* Also it is possible to use a local PIN, we use the gloabl
+      /* Although it is possible to use a local PIN, we use the global
          PIN for this application.  */
       rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
-      if (rc)
-        {
-          if ( gpg_error (rc) == GPG_ERR_USE_CONDITIONS )
-            log_error (_("the NullPIN has not yet been changed\n"));
-          else
-            log_error ("verify PIN failed\n");
-          xfree (pinvalue);
-          return rc;
-        }
-      app->did_chv1 = 1;
       xfree (pinvalue);
     }
 
+  if (rc)
+    {
+      if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
+        log_error (_("the NullPIN has not yet been changed\n"));
+      else
+        log_error ("verify PIN failed\n");
+      return rc;
+    }
+  app->did_chv1 = 1;
+
   return 0;
 }
 
@@ -385,7 +415,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
     return gpg_error (GPG_ERR_INV_VALUE);
 
   /* Check that the provided ID is vaid.  This is not really needed
-     but we do it to to enforce correct usage by the caller. */
+     but we do it to enforce correct usage by the caller. */
   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
     return gpg_error (GPG_ERR_INV_ID);
   keyidstr += 9;
@@ -456,7 +486,7 @@ do_decipher (app_t app, const char *keyidstr,
   if (!keyidstr || !*keyidstr || !indatalen)
     return gpg_error (GPG_ERR_INV_VALUE);
 
-  /* Check that the provided ID is vaid.  This is not really needed
+  /* Check that the provided ID is valid.  This is not really needed
      but we do it to to enforce correct usage by the caller. */
   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
     return gpg_error (GPG_ERR_INV_ID);
@@ -488,9 +518,9 @@ do_decipher (app_t app, const char *keyidstr,
 
 
 
-/* Select the NKS 2.0 application on the card in SLOT.  */
+/* Select the NKS 2.0 application.  */
 gpg_error_t
-app_select_nks (APP app)
+app_select_nks (app_t app)
 {
   static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
   int slot = app->slot;