New PIN Callback attributes in gpg-agent.
[gnupg.git] / scd / app-nks.c
1 /* app-nks.c - The Telesec NKS card application.
2  * Copyright (C) 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /* Notes:
21
22   - This is still work in progress.  We are now targeting TCOS 3 cards
23     but try to keep compatibility to TCOS 2.  Both are not fully
24     working as of now.  TCOS 3 PIN management seems to work.  Use GPA
25     from SVN trunk to test it.
26
27   - If required, we automagically switch between the NKS application
28     and the SigG application.  This avoids to use the DINSIG
29     application which is somewhat limited, has no support for Secure
30     Messaging as required by TCOS 3 and has no way to change the PIN
31     or even set the NullPIN.
32
33   - We use the prefix NKS-DF01 for TCOS 2 cards and NKS-NKS3 for newer
34     cards.  This is because the NKS application has moved to DF02 with
35     TCOS 3 and thus we better use a DF independent tag.
36
37   - We use only the global PINs for the NKS application.
38
39  */
40
41 #include <config.h>
42 #include <errno.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <assert.h>
47 #include <time.h>
48
49 #include "scdaemon.h"
50 #include "i18n.h"
51 #include "iso7816.h"
52 #include "app-common.h"
53 #include "tlv.h"
54 #include "apdu.h"
55
56 static char const aid_nks[]  = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
57 static char const aid_sigg[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 };
58
59
60 static struct
61 {
62   int is_sigg;   /* Valid for SigG application.  */
63   int fid;       /* File ID. */
64   int nks_ver;   /* 0 for NKS version 2, 3 for version 3. */
65   int certtype;  /* Type of certificate or 0 if it is not a certificate. */
66   int iskeypair; /* If true has the FID of the correspoding certificate. */
67   int issignkey; /* True if file is a key usable for signing. */
68   int isenckey;  /* True if file is a key usable for decryption. */
69 } filelist[] = {
70   { 0, 0x4531, 0, 0,  0xC000, 1, 0 }, /* EF_PK.NKS.SIG */
71   { 1, 0x4531, 3, 0,  0x0000, 1, 1 }, /* EF_PK.CH.SIG  */
72   { 0, 0xC000, 0, 101 },              /* EF_C.NKS.SIG  */
73   { 1, 0xC000, 0, 101 },              /* EF_C.CH.SIG  */
74   { 0, 0x4331, 0, 100 },
75   { 0, 0x4332, 0, 100 },
76   { 0, 0xB000, 0, 110 },              /* EF_PK.RCA.NKS */
77   { 0, 0x45B1, 0, 0,  0xC200, 0, 1 }, /* EF_PK.NKS.ENC */
78   { 0, 0xC200, 0, 101 },              /* EF_C.NKS.ENC  */
79   { 0, 0x43B1, 0, 100 },
80   { 0, 0x43B2, 0, 100 },
81   { 0, 0x4571, 3, 0,  0xc500, 0, 0 }, /* EF_PK.NKS.AUT */
82   { 0, 0xC500, 3, 101 },              /* EF_C.NKS.AUT  */
83   { 0, 0x45B2, 3, 0,  0xC201, 0, 1 }, /* EF_PK.NKS.ENC1024 */
84   { 0, 0xC201, 3, 101 },              /* EF_C.NKS.ENC1024  */
85 /*   { 1, 0xB000, 3, ...  */
86   { 0, 0 }
87 };
88
89
90
91 /* Object with application (i.e. NKS) specific data.  */
92 struct app_local_s {
93   int nks_version;  /* NKS version.  */
94
95   int sigg_active;  /* True if switched to the SigG application.  */
96 };
97
98
99 \f
100 static gpg_error_t switch_application (app_t app, int enable_sigg);
101
102
103 \f
104 /* Release local data. */
105 static void
106 do_deinit (app_t app)
107 {
108   if (app && app->app_local)
109     {
110       xfree (app->app_local);
111       app->app_local = NULL;
112     }
113 }
114
115
116 /* Read the file with FID, assume it contains a public key and return
117    its keygrip in the caller provided 41 byte buffer R_GRIPSTR. */
118 static gpg_error_t
119 keygripstr_from_pk_file (app_t app, int fid, char *r_gripstr)
120 {
121   gpg_error_t err;
122   unsigned char grip[20];
123   unsigned char *buffer[2];
124   size_t buflen[2];
125   gcry_sexp_t sexp;
126   int i;
127   
128   err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
129   if (err)
130     return err;
131   err = iso7816_read_record (app->slot, 1, 1, 0, &buffer[0], &buflen[0]);
132   if (err)
133     return err;
134   err = iso7816_read_record (app->slot, 2, 1, 0, &buffer[1], &buflen[1]);
135   if (err)
136     {
137       xfree (buffer[0]);
138       return err;
139     }
140   
141   if (app->app_local->nks_version < 3)
142     {
143       /* Old versions of NKS store the values in a TLV encoded format.
144          We need to do some checks.  */
145       for (i=0; i < 2; i++)
146         {
147           /* Check that the value appears like an integer encoded as
148              Simple-TLV.  We don't check the tag because the tests cards I
149              have use 1 for both, the modulus and the exponent - the
150              example in the documentation gives 2 for the exponent. */
151           if (buflen[i] < 3)
152             err = gpg_error (GPG_ERR_TOO_SHORT);
153           else if (buffer[i][1] != buflen[i]-2 )
154             err = gpg_error (GPG_ERR_INV_OBJ);
155         }
156     }
157
158   if (!err)
159     err = gcry_sexp_build (&sexp, NULL,
160                            "(public-key (rsa (n %b) (e %b)))",
161                            (int)buflen[0]-2, buffer[0]+2,
162                            (int)buflen[1]-2, buffer[1]+2);
163
164   xfree (buffer[0]);
165   xfree (buffer[1]);
166   if (err)
167     return err;
168
169   if (!gcry_pk_get_keygrip (sexp, grip))
170     {
171       err = gpg_error (GPG_ERR_INTERNAL); /* i.e. RSA not supported by
172                                              libgcrypt. */
173     }
174   else
175     {
176       bin2hex (grip, 20, r_gripstr);
177     }
178   gcry_sexp_release (sexp);
179   return err;
180 }
181
182
183 /* TCOS responds to a verify with empty data (i.e. without the Lc
184    byte) with the status of the PIN.  PWID is the PIN ID, If SIGG is
185    true, the application is switched into SigG mode.
186    Returns:
187             -1 = Error retrieving the data,
188             -2 = No such PIN,
189             -3 = PIN blocked,
190             -4 = NullPIN activ,
191         n >= 0 = Number of verification attempts left.  */
192 static int
193 get_chv_status (app_t app, int sigg, int pwid)
194 {
195   unsigned char *result = NULL;
196   size_t resultlen;
197   char command[4];
198   int rc;
199
200   if (switch_application (app, sigg))
201     return sigg? -2 : -1; /* No such PIN / General error.  */
202
203   command[0] = 0x00;
204   command[1] = 0x20;
205   command[2] = 0x00;
206   command[3] = pwid;
207
208   if (apdu_send_direct (app->slot, command, 4, 0, &result, &resultlen))
209     rc = -1; /* Error. */
210   else if (resultlen < 2)
211     rc = -1; /* Error. */
212   else
213     {
214       unsigned int sw = ((result[resultlen-2] << 8) | result[resultlen-1]);
215
216       if (sw == 0x6a88)
217         rc = -2; /* No such PIN.  */
218       else if (sw == 0x6983)
219         rc = -3; /* PIN is blocked.  */
220       else if (sw == 0x6985)
221         rc = -4; /* NullPIN is activ.  */
222       else if ((sw & 0xfff0) == 0x63C0)
223         rc = (sw & 0x000f); /* PIN has N tries left.  */
224       else
225         rc = -1; /* Other error.  */
226     }
227   xfree (result);
228
229   return rc;
230 }
231
232
233 /* Implement the GETATTR command.  This is similar to the LEARN
234    command but returns just one value via the status interface. */
235 static gpg_error_t 
236 do_getattr (app_t app, ctrl_t ctrl, const char *name)
237 {
238   static struct {
239     const char *name;
240     int special;
241   } table[] = {
242     { "$AUTHKEYID",   1 },
243     { "NKS-VERSION",  2 },
244     { "CHV-STATUS",   3 },
245     { NULL, 0 }
246   };
247   gpg_error_t err = 0;
248   int idx;
249   char buffer[100];
250
251   err = switch_application (app, 0);
252   if (err)
253     return err;
254
255   for (idx=0; table[idx].name && strcmp (table[idx].name, name); idx++)
256     ;
257   if (!table[idx].name)
258     return gpg_error (GPG_ERR_INV_NAME); 
259
260   switch (table[idx].special)
261     {
262     case 1: /* $AUTHKEYID */
263       {
264         /* NetKey 3.0 cards define this key for authentication.
265            FIXME: We don't have the readkey command, so this
266            information is pretty useless.  */
267         char const tmp[] = "NKS-NKS3.4571";
268         send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
269       }
270       break;
271
272     case 2: /* NKS-VERSION */
273       snprintf (buffer, sizeof buffer, "%d", app->app_local->nks_version);
274       send_status_info (ctrl, table[idx].name,
275                         buffer, strlen (buffer), NULL, 0);
276       break;
277
278     case 3: /* CHV-STATUS */
279       {
280         /* Returns: PW1.CH PW2.CH PW1.CH.SIG PW2.CH.SIG That are the
281            two global passwords followed by the two SigG passwords.
282            For the values, see the function get_chv_status.  */
283         int tmp[4];
284         
285         /* We use a helper array so that we can control that there is
286            no superfluous application switch.  Note that PW2.CH.SIG
287            really has the identifier 0x83 and not 0x82 as one would
288            expect.  */
289         tmp[0] = get_chv_status (app, 0, 0x00);
290         tmp[1] = get_chv_status (app, 0, 0x01);
291         tmp[2] = get_chv_status (app, 1, 0x81);
292         tmp[3] = get_chv_status (app, 1, 0x83); 
293         snprintf (buffer, sizeof buffer, 
294                   "%d %d %d %d", tmp[0], tmp[1], tmp[2], tmp[3]);
295         send_status_info (ctrl, table[idx].name,
296                           buffer, strlen (buffer), NULL, 0);
297       }
298       break;
299
300
301     default:
302       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
303       break;
304     }
305
306   return err;
307 }
308
309
310
311
312 static gpg_error_t
313 do_learn_status (app_t app, ctrl_t ctrl)
314 {
315   gpg_error_t err;
316   char ct_buf[100], id_buf[100];
317   int i;
318
319   err = switch_application (app, 0);
320   if (err)
321     return err;
322
323   /* Output information about all useful objects in the NKS application. */
324   for (i=0; filelist[i].fid; i++)
325     {
326       if (filelist[i].nks_ver > app->app_local->nks_version)
327         continue;
328
329       if (filelist[i].is_sigg)
330         continue;
331
332       if (filelist[i].certtype)
333         {
334           size_t len;
335
336           len = app_help_read_length_of_cert (app->slot,
337                                               filelist[i].fid, NULL);
338           if (len)
339             {
340               /* FIXME: We should store the length in the application's
341                  context so that a following readcert does only need to
342                  read that many bytes. */
343               snprintf (ct_buf, sizeof ct_buf, "%d", filelist[i].certtype);
344               snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X", 
345                         app->app_local->nks_version < 3? "DF01":"NKS3",
346                         filelist[i].fid);
347               send_status_info (ctrl, "CERTINFO",
348                                 ct_buf, strlen (ct_buf), 
349                                 id_buf, strlen (id_buf), 
350                                 NULL, (size_t)0);
351             }
352         }
353       else if (filelist[i].iskeypair)
354         {
355           char gripstr[40+1];
356
357           err = keygripstr_from_pk_file (app, filelist[i].fid, gripstr);
358           if (err)
359             log_error ("can't get keygrip from FID 0x%04X: %s\n",
360                        filelist[i].fid, gpg_strerror (err));
361           else
362             {
363               snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X",
364                         app->app_local->nks_version < 3? "DF01":"NKS3",
365                         filelist[i].fid);
366               send_status_info (ctrl, "KEYPAIRINFO",
367                                 gripstr, 40, 
368                                 id_buf, strlen (id_buf), 
369                                 NULL, (size_t)0);
370             }
371         }
372     }
373
374   err = switch_application (app, 1);
375   if (err)
376     return 0;  /* Silently ignore if we can't swicth to SigG.  */
377
378   for (i=0; filelist[i].fid; i++)
379     {
380       if (filelist[i].nks_ver > app->app_local->nks_version)
381         continue;
382
383       if (!filelist[i].is_sigg)
384         continue;
385
386       if (filelist[i].certtype)
387         {
388           size_t len;
389
390           len = app_help_read_length_of_cert (app->slot,
391                                               filelist[i].fid, NULL);
392           if (len)
393             {
394               /* FIXME: We should store the length in the application's
395                  context so that a following readcert does only need to
396                  read that many bytes. */
397               snprintf (ct_buf, sizeof ct_buf, "%d", filelist[i].certtype);
398               snprintf (id_buf, sizeof id_buf, "NKS-SIGG.%04X",
399                         filelist[i].fid);
400               send_status_info (ctrl, "CERTINFO",
401                                 ct_buf, strlen (ct_buf), 
402                                 id_buf, strlen (id_buf), 
403                                 NULL, (size_t)0);
404             }
405         }
406       else if (filelist[i].iskeypair)
407         {
408           char gripstr[40+1];
409
410           err = keygripstr_from_pk_file (app, filelist[i].fid, gripstr);
411           if (err)
412             log_error ("can't get keygrip from FID 0x%04X: %s\n",
413                        filelist[i].fid, gpg_strerror (err));
414           else
415             {
416               snprintf (id_buf, sizeof id_buf, "NKS-SIGG.%04X",
417                         filelist[i].fid);
418               send_status_info (ctrl, "KEYPAIRINFO",
419                                 gripstr, 40, 
420                                 id_buf, strlen (id_buf), 
421                                 NULL, (size_t)0);
422             }
423         }
424     }
425
426
427   return 0;
428 }
429
430
431
432
433 /* Read the certificate with id CERTID (as returned by learn_status in
434    the CERTINFO status lines) and return it in the freshly allocated
435    buffer put into CERT and the length of the certificate put into
436    CERTLEN. */
437 static gpg_error_t
438 do_readcert (app_t app, const char *certid,
439              unsigned char **cert, size_t *certlen)
440 {
441   int i, fid;
442   gpg_error_t err;
443   unsigned char *buffer;
444   const unsigned char *p;
445   size_t buflen, n;
446   int class, tag, constructed, ndef;
447   size_t totobjlen, objlen, hdrlen;
448   int rootca = 0;
449
450   *cert = NULL;
451   *certlen = 0;
452
453   err = switch_application (app, 0);
454   if (err)
455     return err;
456
457   if (!strncmp (certid, "NKS-NKS3.", 9)) 
458     ;
459   else if (!strncmp (certid, "NKS-DF01.", 9)) 
460     ;
461   else
462     return gpg_error (GPG_ERR_INV_ID);
463   certid += 9;
464   if (!hexdigitp (certid) || !hexdigitp (certid+1)
465       || !hexdigitp (certid+2) || !hexdigitp (certid+3) 
466       || certid[4])
467     return gpg_error (GPG_ERR_INV_ID);
468   fid = xtoi_4 (certid);
469   for (i=0; filelist[i].fid; i++)
470     if ((filelist[i].certtype || filelist[i].iskeypair)
471         && filelist[i].fid == fid)
472       break;
473   if (!filelist[i].fid)
474     return gpg_error (GPG_ERR_NOT_FOUND);
475
476   /* If the requested objects is a plain public key, redirect it to
477      the corresponding certificate.  The whole system is a bit messy
478      because we sometime use the key directly or let the caller
479      retrieve the key from the certificate.  The rationale for
480      that is to support not-yet stored certificates. */
481   if (filelist[i].iskeypair)
482     fid = filelist[i].iskeypair;
483
484
485   /* Read the entire file.  fixme: This could be optimized by first
486      reading the header to figure out how long the certificate
487      actually is. */
488   err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
489   if (err)
490     {
491       log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
492       return err;
493     }
494
495   err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
496   if (err)
497     {
498       log_error ("error reading certificate from FID 0x%04X: %s\n",
499                  fid, gpg_strerror (err));
500       return err;
501     }
502   
503   if (!buflen || *buffer == 0xff)
504     {
505       log_info ("no certificate contained in FID 0x%04X\n", fid);
506       err = gpg_error (GPG_ERR_NOT_FOUND);
507       goto leave;
508     }
509
510   /* Now figure something out about the object. */
511   p = buffer;
512   n = buflen;
513   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
514                           &ndef, &objlen, &hdrlen);
515   if (err)
516     goto leave;
517   if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed )
518     ;
519   else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed )
520     rootca = 1;
521   else
522     return gpg_error (GPG_ERR_INV_OBJ);
523   totobjlen = objlen + hdrlen;
524   assert (totobjlen <= buflen);
525
526   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
527                           &ndef, &objlen, &hdrlen);
528   if (err)
529     goto leave;
530   
531   if (rootca)
532     ;
533   else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
534     {
535       const unsigned char *save_p;
536   
537       /* The certificate seems to be contained in a userCertificate
538          container.  Skip this and assume the following sequence is
539          the certificate. */
540       if (n < objlen)
541         {
542           err = gpg_error (GPG_ERR_INV_OBJ);
543           goto leave;
544         }
545       p += objlen;
546       n -= objlen;
547       save_p = p;
548       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
549                               &ndef, &objlen, &hdrlen);
550       if (err) 
551         goto leave;
552       if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) )
553         return gpg_error (GPG_ERR_INV_OBJ);
554       totobjlen = objlen + hdrlen;
555       assert (save_p + totobjlen <= buffer + buflen);
556       memmove (buffer, save_p, totobjlen);
557     }
558   
559   *cert = buffer;
560   buffer = NULL;
561   *certlen = totobjlen;
562
563  leave:
564   xfree (buffer);
565   return err;
566 }
567
568
569 static gpg_error_t
570 basic_pin_checks (const char *pinvalue, int minlen, int maxlen)
571 {
572   if (strlen (pinvalue) < minlen)
573     {
574       log_error ("PIN is too short; minimum length is %d\n", minlen);
575       return gpg_error (GPG_ERR_BAD_PIN);
576     }
577   if (strlen (pinvalue) > maxlen)
578     {
579       log_error ("PIN is too large; maximum length is %d\n", maxlen);
580       return gpg_error (GPG_ERR_BAD_PIN);
581     }
582   return 0;
583 }
584
585
586 /* Verify the PIN if required.  */
587 static gpg_error_t
588 verify_pin (app_t app, int pwid, const char *desc,
589             gpg_error_t (*pincb)(void*, const char *, char **),
590             void *pincb_arg)
591 {
592   iso7816_pininfo_t pininfo;
593   int rc;
594
595   if (!desc)
596     desc = "PIN";
597
598   memset (&pininfo, 0, sizeof pininfo);
599   pininfo.mode = 1;
600   pininfo.minlen = 6;
601   pininfo.maxlen = 16;
602
603   if (!opt.disable_keypad
604       && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
605     {
606       rc = pincb (pincb_arg,
607                   _("||Please enter your PIN at the reader's keypad"),
608                   NULL);
609       if (rc)
610         {
611           log_info (_("PIN callback returned error: %s\n"),
612                     gpg_strerror (rc));
613           return rc;
614         }
615  
616       /* Although it is possible to use a local PIN, we use the global
617          PIN for this application.  */
618       rc = iso7816_verify_kp (app->slot, 0, "", 0, &pininfo); 
619       /* Dismiss the prompt. */
620       pincb (pincb_arg, NULL, NULL);
621     }
622   else
623     {
624       char *pinvalue;
625
626       rc = pincb (pincb_arg, desc, &pinvalue); 
627       if (rc)
628         {
629           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
630           return rc;
631         }
632
633       /* The following limits are due to TCOS but also defined in the
634          NKS specs. */
635       rc = basic_pin_checks (pinvalue, pininfo.minlen, pininfo.maxlen);
636       if (rc)
637         {
638           xfree (pinvalue);
639           return rc;
640         }
641
642       rc = iso7816_verify (app->slot, pwid, pinvalue, strlen (pinvalue));
643       xfree (pinvalue);
644     }
645
646   if (rc)
647     {
648       if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
649         log_error (_("the NullPIN has not yet been changed\n"));
650       else
651         log_error ("verify PIN failed\n");
652       return rc;
653     }
654
655   return 0;
656 }
657
658
659
660 /* Create the signature and return the allocated result in OUTDATA.
661    If a PIN is required the PINCB will be used to ask for the PIN;
662    that callback should return the PIN in an allocated buffer and
663    store that in the 3rd argument.  */
664 static gpg_error_t 
665 do_sign (app_t app, const char *keyidstr, int hashalgo,
666          gpg_error_t (*pincb)(void*, const char *, char **),
667          void *pincb_arg,
668          const void *indata, size_t indatalen,
669          unsigned char **outdata, size_t *outdatalen )
670 {
671   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
672     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
673       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
674   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
675     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
676       0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
677   int rc, i;
678   int fid;
679   unsigned char data[35];   /* Must be large enough for a SHA-1 digest
680                                + the largest OID _prefix above. */
681
682   if (!keyidstr || !*keyidstr)
683     return gpg_error (GPG_ERR_INV_VALUE);
684   if (indatalen != 20 && indatalen != 16 && indatalen != 35)
685     return gpg_error (GPG_ERR_INV_VALUE);
686
687   rc = switch_application (app, 0);
688   if (rc)
689     return rc;
690
691   /* Check that the provided ID is valid.  This is not really needed
692      but we do it to enforce correct usage by the caller. */
693   if (!strncmp (keyidstr, "NKS-NKS3.", 9) ) 
694     ;
695   else if (!strncmp (keyidstr, "NKS-DF01.", 9) ) 
696     ;
697   else
698     return gpg_error (GPG_ERR_INV_ID);
699   keyidstr += 9;
700   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
701       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
702       || keyidstr[4])
703     return gpg_error (GPG_ERR_INV_ID);
704   fid = xtoi_4 (keyidstr);
705   for (i=0; filelist[i].fid; i++)
706     if (filelist[i].iskeypair && filelist[i].fid == fid)
707       break;
708   if (!filelist[i].fid)
709     return gpg_error (GPG_ERR_NOT_FOUND);
710   if (!filelist[i].issignkey)
711     return gpg_error (GPG_ERR_INV_ID);
712
713   /* Prepare the DER object from INDATA. */
714   if (indatalen == 35)
715     {
716       /* Alright, the caller was so kind to send us an already
717          prepared DER object.  Check that it is waht we want and that
718          it matches the hash algorithm. */
719       if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
720         ;
721       else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15))
722         ;
723       else 
724         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
725       memcpy (data, indata, indatalen);
726     }
727   else
728     {
729       if (hashalgo == GCRY_MD_SHA1)
730         memcpy (data, sha1_prefix, 15);
731       else if (hashalgo == GCRY_MD_RMD160)
732         memcpy (data, rmd160_prefix, 15);
733       else 
734         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
735       memcpy (data+15, indata, indatalen);
736     }
737
738   rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
739   if (!rc)
740     rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
741   return rc;
742 }
743
744
745
746
747 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
748    If a PIN is required the PINCB will be used to ask for the PIN; it
749    should return the PIN in an allocated buffer and put it into PIN.  */
750 static gpg_error_t 
751 do_decipher (app_t app, const char *keyidstr,
752              gpg_error_t (*pincb)(void*, const char *, char **),
753              void *pincb_arg,
754              const void *indata, size_t indatalen,
755              unsigned char **outdata, size_t *outdatalen )
756 {
757   static const unsigned char mse_parm[] = {
758     0x80, 1, 0x10, /* Select algorithm RSA. */
759     0x84, 1, 0x81  /* Select local secret key 1 for decryption. */
760   };
761   int rc, i;
762   int fid;
763
764   if (!keyidstr || !*keyidstr || !indatalen)
765     return gpg_error (GPG_ERR_INV_VALUE);
766
767   rc = switch_application (app, 0);
768   if (rc)
769     return rc;
770
771   /* Check that the provided ID is valid.  This is not really needed
772      but we do it to to enforce correct usage by the caller. */
773   if (!strncmp (keyidstr, "NKS-NKS3.", 9) ) 
774     ;
775   else if (!strncmp (keyidstr, "NKS-DF01.", 9) ) 
776     ;
777   else
778     return gpg_error (GPG_ERR_INV_ID);
779   keyidstr += 9;
780   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
781       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
782       || keyidstr[4])
783     return gpg_error (GPG_ERR_INV_ID);
784   fid = xtoi_4 (keyidstr);
785   for (i=0; filelist[i].fid; i++)
786     if (filelist[i].iskeypair && filelist[i].fid == fid)
787       break;
788   if (!filelist[i].fid)
789     return gpg_error (GPG_ERR_NOT_FOUND);
790   if (!filelist[i].isenckey)
791     return gpg_error (GPG_ERR_INV_ID);
792
793   /* Do the TCOS specific MSE. */
794   rc = iso7816_manage_security_env (app->slot, 
795                                     0xC1, 0xB8,
796                                     mse_parm, sizeof mse_parm);
797   if (!rc)
798     rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
799   if (!rc)
800     rc = iso7816_decipher (app->slot, indata, indatalen, 0x81,
801                            outdata, outdatalen);
802   return rc;
803 }
804
805
806
807 /* Parse a password ID string.  Returns NULL on error or a string
808    suitable as passpahrse prompt on success.  On success stores the
809    reference value for the password at R_PWID and a flag indicating
810    that the SigG application is to be used at R_SIGG.  If NEW_MODE is
811    true, the returned description is suitable for a new Password.
812    Supported values for PWIDSTR are:
813
814      PW1.CH       - Global password 1
815      PW2.CH       - Global password 2
816      PW1.CH.SIG   - SigG password 1
817      PW2.CH.SIG   - SigG password 2
818  */
819 static const char *
820 parse_pwidstr (const char *pwidstr, int new_mode, int *r_sigg, int *r_pwid)
821 {
822   const char *desc;
823
824   if (!pwidstr)
825     desc = NULL;
826   else if (!strcmp (pwidstr, "PW1.CH"))
827     {
828       *r_sigg = 0;
829       *r_pwid = 0x00;
830       /* TRANSLATORS: Do not translate the "|*|" prefixes but keep
831          them verbatim at the start of the string.  */
832       desc = (new_mode
833               ? _("|N|Please enter a new PIN for the standard keys.")
834               : _("||Please enter the PIN for the standard keys."));
835     }
836   else if (!strcmp (pwidstr, "PW2.CH"))
837     {
838       *r_pwid = 0x01;
839       desc = (new_mode
840               ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
841                   "for the standard keys.")
842               : _("|P|Please enter the PIN Unblocking Code (PUK) "
843                   "for the standard keys."));
844     }
845   else if (!strcmp (pwidstr, "PW1.CH.SIG"))
846     {
847       *r_pwid = 0x81;
848       *r_sigg = 1;
849       desc = (new_mode
850               ? _("|N|Please enter a new PIN for the key to create "
851                   "qualified signatures.")
852               : _("||Please enter the PIN for the key to create "
853                   "qualified signatures."));
854     }
855   else if (!strcmp (pwidstr, "PW2.CH.SIG"))
856     {
857       *r_pwid = 0x83;  /* Yes, that is 83 and not 82.  */
858       *r_sigg = 1;
859       desc = (new_mode
860               ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
861                   "for the key to create qualified signatures.")
862               : _("|P|Please enter the PIN Unblocking Code (PUK) "
863                   "for the key to create qualified signatures."));
864     }
865   else
866     desc = NULL;
867
868   return desc;
869 }
870
871
872 /* Handle the PASSWD command. See parse_pwidstr() for allowed values
873    for CHVNOSTR.  */
874 static gpg_error_t 
875 do_change_pin (app_t app, ctrl_t ctrl,  const char *pwidstr, 
876                unsigned int flags,
877                gpg_error_t (*pincb)(void*, const char *, char **),
878                void *pincb_arg)
879 {
880   gpg_error_t err;
881   char *newpin = NULL;
882   char *oldpin = NULL;
883   size_t newpinlen;
884   size_t oldpinlen;
885   int is_sigg;
886   const char *newdesc;
887   int pwid;
888   iso7816_pininfo_t pininfo;
889
890   (void)ctrl;
891
892   /* The minimum length is enforced by TCOS, the maximum length is
893      just a reasonable value.  */
894   memset (&pininfo, 0, sizeof pininfo);
895   pininfo.minlen = 6;
896   pininfo.maxlen = 16;
897   
898   newdesc = parse_pwidstr (pwidstr, 1, &is_sigg, &pwid);
899   if (!newdesc)
900     return gpg_error (GPG_ERR_INV_ID);
901
902   err = switch_application (app, is_sigg);
903   if (err)
904     return err;
905
906   if ((flags & APP_CHANGE_FLAG_NULLPIN))
907     {
908       /* With the nullpin flag, we do not verify the PIN - it would
909          fail if the Nullpin is still set.  */
910       oldpin = xtrycalloc (1, 6);
911       if (!oldpin)
912         {
913           err = gpg_error_from_syserror ();
914           goto leave;
915         }
916       oldpinlen = 6;
917     }
918   else
919     {
920       const char *desc;
921       int dummy1, dummy2;
922
923       if ((flags & APP_CHANGE_FLAG_RESET))
924         {
925           /* Reset mode: Ask for the alternate PIN.  */
926           const char *altpwidstr;
927
928           if (!strcmp (pwidstr, "PW1.CH"))
929             altpwidstr = "PW2.CH";
930           else if (!strcmp (pwidstr, "PW2.CH"))
931             altpwidstr = "PW1.CH";
932           else if (!strcmp (pwidstr, "PW1.CH.SIG"))
933             altpwidstr = "PW2.CH.SIG";
934           else if (!strcmp (pwidstr, "PW2.CH.SIG"))
935             altpwidstr = "PW1.CH.SIG";
936           else
937             {
938               err = gpg_error (GPG_ERR_BUG);
939               goto leave;
940             }
941           desc = parse_pwidstr (altpwidstr, 0, &dummy1, &dummy2);
942         }
943       else
944         {
945           /* Regular change mode:  Ask for the old PIN.  */
946           desc = parse_pwidstr (pwidstr, 0, &dummy1, &dummy2);
947         }
948       err = pincb (pincb_arg, desc, &oldpin); 
949       if (err)
950         {
951           log_error ("error getting old PIN: %s\n", gpg_strerror (err));
952           goto leave;
953         }
954       oldpinlen = strlen (oldpin);
955       err = basic_pin_checks (oldpin, pininfo.minlen, pininfo.maxlen);
956       if (err)
957         goto leave;
958     }
959
960   err = pincb (pincb_arg, newdesc, &newpin); 
961   if (err)
962     {
963       log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
964       goto leave;
965     }
966   newpinlen = strlen (newpin);
967   
968   err = basic_pin_checks (newpin, pininfo.minlen, pininfo.maxlen);
969   if (err)
970     goto leave;
971
972   if ((flags & APP_CHANGE_FLAG_RESET))
973     {
974       char *data;
975       size_t datalen = oldpinlen + newpinlen;
976
977       data = xtrymalloc (datalen);
978       if (!data)
979         {
980           err = gpg_error_from_syserror ();
981           goto leave;
982         }
983       memcpy (data, oldpin, oldpinlen);
984       memcpy (data+oldpinlen, newpin, newpinlen);
985       err = iso7816_reset_retry_counter_with_rc (app->slot, pwid,
986                                                  data, datalen);
987       wipememory (data, datalen);
988       xfree (data);
989     }
990   else 
991     err = iso7816_change_reference_data (app->slot, pwid, 
992                                          oldpin, oldpinlen,
993                                          newpin, newpinlen);
994  leave:
995   xfree (oldpin);
996   xfree (newpin);
997   return err;
998 }
999
1000
1001 /* Perform a simple verify operation.  KEYIDSTR should be NULL or empty.  */
1002 static gpg_error_t 
1003 do_check_pin (app_t app, const char *pwidstr,
1004               gpg_error_t (*pincb)(void*, const char *, char **),
1005               void *pincb_arg)
1006 {
1007   gpg_error_t err;
1008   int pwid;
1009   int is_sigg;
1010   const char *desc;
1011
1012   desc = parse_pwidstr (pwidstr, 0, &is_sigg, &pwid);
1013   if (!desc)
1014     return gpg_error (GPG_ERR_INV_ID);
1015
1016   err = switch_application (app, is_sigg);
1017   if (err)
1018     return err;
1019
1020   return verify_pin (app, pwid, desc, pincb, pincb_arg);
1021 }
1022
1023
1024 /* Return the version of the NKS application.  */
1025 static int
1026 get_nks_version (int slot)
1027 {
1028   unsigned char *result = NULL;
1029   size_t resultlen;
1030   int type;
1031
1032   if (iso7816_apdu_direct (slot, "\x80\xaa\x06\x00\x00", 5, 0, 
1033                            &result, &resultlen))
1034     return 2; /* NKS 2 does not support this command.  */
1035   
1036   /* Example value:    04 11 19 22 21 6A 20 80 03 03 01 01 01 00 00 00
1037                        vv tt ccccccccccccccccc aa bb cc vvvvvvvvvvv xx
1038      vendor (Philips) -+  |  |                 |  |  |  |           |
1039      chip type -----------+  |                 |  |  |  |           |
1040      chip id ----------------+                 |  |  |  |           |
1041      card type (3 - tcos 3) -------------------+  |  |  |           |
1042      OS version of card type ---------------------+  |  |           |
1043      OS release of card type ------------------------+  |           |
1044      OS vendor internal version ------------------------+           |
1045      RFU -----------------------------------------------------------+
1046   */
1047   if (resultlen < 16)
1048     type = 0;  /* Invalid data returned.  */
1049   else
1050     type = result[8];
1051   xfree (result);
1052
1053   return type;
1054 }
1055
1056
1057 /* If ENABLE_SIGG is true switch to the SigG application if not yet
1058    active.  If false switch to the NKS application if not yet active.
1059    Returns 0 on success.  */
1060 static gpg_error_t
1061 switch_application (app_t app, int enable_sigg)
1062 {
1063   gpg_error_t err;
1064
1065   if ((app->app_local->sigg_active && enable_sigg)
1066       || (!app->app_local->sigg_active && !enable_sigg) )
1067     return 0;  /* Already switched.  */
1068
1069   log_info ("app-nks: switching to %s\n", enable_sigg? "SigG":"NKS");
1070   if (enable_sigg)
1071     err = iso7816_select_application (app->slot, aid_sigg, sizeof aid_sigg, 0);
1072   else
1073     err = iso7816_select_application (app->slot, aid_nks, sizeof aid_nks, 0);
1074   
1075   if (!err)
1076     app->app_local->sigg_active = enable_sigg;
1077   else
1078     log_error ("app-nks: error switching to %s: %s\n",
1079                enable_sigg? "SigG":"NKS", gpg_strerror (err));
1080
1081   return err;
1082 }
1083
1084
1085 /* Select the NKS application.  */
1086 gpg_error_t
1087 app_select_nks (app_t app)
1088 {
1089   int slot = app->slot;
1090   int rc;
1091   
1092   rc = iso7816_select_application (slot, aid_nks, sizeof aid_nks, 0);
1093   if (!rc)
1094     {
1095       app->apptype = "NKS";
1096
1097       app->app_local = xtrycalloc (1, sizeof *app->app_local);
1098       if (!app->app_local)
1099         {
1100           rc = gpg_error (gpg_err_code_from_errno (errno));
1101           goto leave;
1102         }
1103
1104       app->app_local->nks_version = get_nks_version (slot);
1105       if (opt.verbose)
1106         log_info ("Detected NKS version: %d\n", app->app_local->nks_version);
1107
1108       app->fnc.deinit = do_deinit;
1109       app->fnc.learn_status = do_learn_status;
1110       app->fnc.readcert = do_readcert;
1111       app->fnc.getattr = do_getattr;
1112       app->fnc.setattr = NULL;
1113       app->fnc.genkey = NULL;
1114       app->fnc.sign = do_sign;
1115       app->fnc.auth = NULL;
1116       app->fnc.decipher = do_decipher;
1117       app->fnc.change_pin = do_change_pin;
1118       app->fnc.check_pin = do_check_pin;
1119    }
1120
1121  leave:
1122   if (rc)
1123     do_deinit (app);
1124   return rc;
1125 }
1126
1127