Add support for the TCOS NullPIN feature.
authorWerner Koch <wk@gnupg.org>
Tue, 24 Jun 2008 16:00:29 +0000 (16:00 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 24 Jun 2008 16:00:29 +0000 (16:00 +0000)
doc/scdaemon.texi
scd/ChangeLog
scd/app-common.h
scd/app-nks.c
scd/app-openpgp.c
scd/command.c

index 423d84b..bec343e 100644 (file)
@@ -580,11 +580,12 @@ TO BE WRITTEN.
 @subsection Change PINs.
 
 @example
-   PASSWD [--reset] @var{chvno}
+   PASSWD [--reset] [--nullpin] @var{chvno}
 @end example
   
 Change the PIN or reset the retry counter of the card holder
-verification vector number @var{chvno}.
+verification vector number @var{chvno}.  The option @option{--nullpin}
+is used to initialize the PIN of TCOS cards (6 byte NullPIN only).
 
 
 @node Scdaemon CHECKPIN
index 41a9e33..60c139c 100644 (file)
@@ -1,3 +1,14 @@
+2008-06-24  Werner Koch  <wk@g10code.com>
+
+       * app-common.h (app_ctx_s): Renamed reset_mode parameter of
+       change_pin to mode_Flags and make it an unsigned int.
+       (APP_CHANGE_FLAG_RESET, APP_CHANGE_FLAG_NULLPIN): New.
+       * app-openpgp.c (do_change_pin): Adjust for that.
+
+       * command.c (cmd_passwd): Add option --nullpin.
+       * app-nks.c (do_check_pin, do_change_pin): New.
+       (app_select_nks): Register new functions.
+
 2008-04-21  Moritz Schulte  <mo@g10code.com>  (wk)
 
        * app-openpgp.c (verify_a_chv): Make use of the default CHV flag.
index 5ddf0c0..dc1581e 100644 (file)
 #endif
 
 
+#define APP_CHANGE_FLAG_RESET    1
+#define APP_CHANGE_FLAG_NULLPIN  2
+
+
 struct app_local_s;  /* Defined by all app-*.c.  */
 
 struct app_ctx_s {
@@ -101,7 +105,7 @@ struct app_ctx_s {
                            gpg_error_t (*pincb)(void*, const char *, char **),
                            void *pincb_arg);
     gpg_error_t (*change_pin) (app_t app, ctrl_t ctrl,
-                       const char *chvnostr, int reset_mode,
+                       const char *chvnostr, unsigned int flags,
                        gpg_error_t (*pincb)(void*, const char *, char **),
                        void *pincb_arg);
     gpg_error_t (*check_pin) (app_t app, const char *keyidstr,
index 514ae10..848e764 100644 (file)
@@ -1,5 +1,5 @@
 /* app-nks.c - The Telesec NKS 2.0 card application.
- * Copyright (C) 2004, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -414,7 +414,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
   if (indatalen != 20 && indatalen != 16 && indatalen != 35)
     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 enforce correct usage by the caller. */
   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
     return gpg_error (GPG_ERR_INV_ID);
@@ -517,6 +517,65 @@ do_decipher (app_t app, const char *keyidstr,
 }
 
 
+/* Handle the PASSWD command.  CHVNOSTR is currently ignored; we
+   always use VHV0.  RESET_MODE is not yet implemented.  */
+static gpg_error_t 
+do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr, 
+               unsigned int flags,
+               gpg_error_t (*pincb)(void*, const char *, char **),
+               void *pincb_arg)
+{
+  gpg_error_t err;
+  char *pinvalue;
+  const char *oldpin;
+  size_t oldpinlen;
+
+  if ((flags & APP_CHANGE_FLAG_RESET))
+    return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+  if ((flags & APP_CHANGE_FLAG_NULLPIN))
+    {
+      /* With the nullpin flag, we do not verify the PIN - it would fail
+         if the Nullpin is still set.  */
+      oldpin = "\0\0\0\0\0";
+      oldpinlen = 6;
+    }
+  else
+    {
+      err = verify_pin (app, pincb, pincb_arg);
+      if (err)
+        return err;
+      oldpin = NULL;
+      oldpinlen = 0;
+    }
+
+  /* TRANSLATORS: Do not translate the "|*|" prefixes but
+     keep it at the start of the string.  We need this elsewhere
+     to get some infos on the string. */
+  err = pincb (pincb_arg, _("|N|New PIN"), &pinvalue); 
+  if (err)
+    {
+      log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
+      return err;
+    }
+
+  err = iso7816_change_reference_data (app->slot, 0x00, 
+                                       oldpin, oldpinlen,
+                                       pinvalue, strlen (pinvalue));
+  xfree (pinvalue);
+  return err;
+}
+
+
+/* Perform a simple verify operation.  KEYIDSTR should be NULL or empty.  */
+static gpg_error_t 
+do_check_pin (app_t app, const char *keyidstr,
+              gpg_error_t (*pincb)(void*, const char *, char **),
+              void *pincb_arg)
+{
+  return verify_pin (app, pincb, pincb_arg);
+}
+
 
 /* Select the NKS 2.0 application.  */
 gpg_error_t
@@ -539,8 +598,8 @@ app_select_nks (app_t app)
       app->fnc.sign = do_sign;
       app->fnc.auth = NULL;
       app->fnc.decipher = do_decipher;
-      app->fnc.change_pin = NULL;
-      app->fnc.check_pin = NULL;
+      app->fnc.change_pin = do_change_pin;
+      app->fnc.check_pin = do_check_pin;
    }
 
   return rc;
index c8ad936..9433318 100644 (file)
@@ -1644,13 +1644,15 @@ do_setattr (app_t app, const char *name,
 
 /* Handle the PASSWD command. */
 static gpg_error_t 
-do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr, int reset_mode,
+do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr, 
+               unsigned int flags,
                gpg_error_t (*pincb)(void*, const char *, char **),
                void *pincb_arg)
 {
   int rc = 0;
   int chvno = atoi (chvnostr);
   char *pinvalue;
+  int reset_mode = !!(flags & APP_CHANGE_FLAG_RESET);
 
   if (reset_mode && chvno == 3)
     {
index 361b13f..6a52412 100644 (file)
@@ -1273,17 +1273,23 @@ cmd_random (assuan_context_t ctx, char *line)
 }
 
 \f
-/* PASSWD [--reset] <chvno>
+/* PASSWD [--reset] [--nullpin] <chvno>
   
    Change the PIN or reset the retry counter of the card holder
-   verfication vector CHVNO. */
+   verfication vector CHVNO.  The option --nullpin is used for TCOS
+   cards to set the initial PIN. */
 static int
 cmd_passwd (assuan_context_t ctx, char *line)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
   int rc;
   char *chvnostr;
-  int reset_mode = has_option (line, "--reset");
+  unsigned int flags = 0;
+
+  if (has_option (line, "--reset"))
+    flags |= APP_CHANGE_FLAG_RESET;
+  if (has_option (line, "--nullpin"))
+    flags |= APP_CHANGE_FLAG_NULLPIN;
 
   if ( IS_LOCKED (ctrl) )
     return gpg_error (GPG_ERR_LOCKED);
@@ -1312,7 +1318,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
   chvnostr = xtrystrdup (chvnostr);
   if (!chvnostr)
     return out_of_core ();
-  rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx);
+  rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, flags, pin_cb, ctx);
   if (rc)
     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
   xfree (chvnostr);