chiark / gitweb /
Replace use of variable-length-arrays.
[gnupg2.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 <https://www.gnu.org/licenses/>.
18  */
19
20 /* Notes:
21
22   - We are now targeting TCOS 3 cards and it may happen that there is
23     a regression towards TCOS 2 cards.  Please report.
24
25   - The TKS3 AUT key is not used.  It seems that it is only useful for
26     the internal authentication command and not accessible by other
27     applications.  The key itself is in the encryption class but the
28     corresponding certificate has only the digitalSignature
29     capability.
30
31   - If required, we automagically switch between the NKS application
32     and the SigG application.  This avoids to use the DINSIG
33     application which is somewhat limited, has no support for Secure
34     Messaging as required by TCOS 3 and has no way to change the PIN
35     or even set the NullPIN.
36
37   - We use the prefix NKS-DF01 for TCOS 2 cards and NKS-NKS3 for newer
38     cards.  This is because the NKS application has moved to DF02 with
39     TCOS 3 and thus we better use a DF independent tag.
40
41   - We use only the global PINs for the NKS application.
42
43  */
44
45 #include <config.h>
46 #include <errno.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <assert.h>
51 #include <time.h>
52
53 #include "scdaemon.h"
54 #include "i18n.h"
55 #include "iso7816.h"
56 #include "app-common.h"
57 #include "tlv.h"
58 #include "apdu.h"
59 #include "host2net.h"
60
61 static char const aid_nks[]  = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
62 static char const aid_sigg[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 };
63
64
65 static struct
66 {
67   int is_sigg;   /* Valid for SigG application.  */
68   int fid;       /* File ID. */
69   int nks_ver;   /* 0 for NKS version 2, 3 for version 3. */
70   int certtype;  /* Type of certificate or 0 if it is not a certificate. */
71   int iskeypair; /* If true has the FID of the corresponding certificate. */
72   int issignkey; /* True if file is a key usable for signing. */
73   int isenckey;  /* True if file is a key usable for decryption. */
74   unsigned char kid;  /* Corresponding key references.  */
75 } filelist[] = {
76   { 0, 0x4531, 0, 0,  0xC000, 1, 0, 0x80 }, /* EF_PK.NKS.SIG */
77   { 0, 0xC000, 0, 101 },                    /* EF_C.NKS.SIG  */
78   { 0, 0x4331, 0, 100 },
79   { 0, 0x4332, 0, 100 },
80   { 0, 0xB000, 0, 110 },                    /* EF_PK.RCA.NKS */
81   { 0, 0x45B1, 0, 0,  0xC200, 0, 1, 0x81 }, /* EF_PK.NKS.ENC */
82   { 0, 0xC200, 0, 101 },                    /* EF_C.NKS.ENC  */
83   { 0, 0x43B1, 0, 100 },
84   { 0, 0x43B2, 0, 100 },
85 /* The authentication key is not used.  */
86 /*   { 0, 0x4571, 3, 0,  0xC500, 0, 0, 0x82 }, /\* EF_PK.NKS.AUT *\/ */
87 /*   { 0, 0xC500, 3, 101 },                    /\* EF_C.NKS.AUT  *\/ */
88   { 0, 0x45B2, 3, 0,  0xC201, 0, 1, 0x83 }, /* EF_PK.NKS.ENC1024 */
89   { 0, 0xC201, 3, 101 },                    /* EF_C.NKS.ENC1024  */
90   { 1, 0x4531, 3, 0,  0xC000, 1, 1, 0x84 }, /* EF_PK.CH.SIG  */
91   { 1, 0xC000, 0, 101 },                    /* EF_C.CH.SIG  */
92   { 1, 0xC008, 3, 101 },                    /* EF_C.CA.SIG  */
93   { 1, 0xC00E, 3, 111 },                    /* EF_C.RCA.SIG  */
94   { 0, 0 }
95 };
96
97
98
99 /* Object with application (i.e. NKS) specific data.  */
100 struct app_local_s {
101   int nks_version;  /* NKS version.  */
102
103   int sigg_active;  /* True if switched to the SigG application.  */
104   int sigg_msig_checked;/*  True if we checked for a mass signature card.  */
105   int sigg_is_msig; /* True if this is a mass signature card.  */
106
107   int need_app_select; /* Need to re-select the application.  */
108
109 };
110
111
112 \f
113 static gpg_error_t switch_application (app_t app, int enable_sigg);
114
115
116 \f
117 /* Release local data. */
118 static void
119 do_deinit (app_t app)
120 {
121   if (app && app->app_local)
122     {
123       xfree (app->app_local);
124       app->app_local = NULL;
125     }
126 }
127
128
129 static int
130 all_zero_p (void *buffer, size_t length)
131 {
132   char *p;
133
134   for (p=buffer; length; length--, p++)
135     if (*p)
136       return 0;
137   return 1;
138 }
139
140
141 /* Read the file with FID, assume it contains a public key and return
142    its keygrip in the caller provided 41 byte buffer R_GRIPSTR. */
143 static gpg_error_t
144 keygripstr_from_pk_file (app_t app, int fid, char *r_gripstr)
145 {
146   gpg_error_t err;
147   unsigned char grip[20];
148   unsigned char *buffer[2];
149   size_t buflen[2];
150   gcry_sexp_t sexp;
151   int i;
152   int offset[2] = { 0, 0 };
153
154   err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
155   if (err)
156     return err;
157   err = iso7816_read_record (app->slot, 1, 1, 0, &buffer[0], &buflen[0]);
158   if (err)
159     return err;
160   err = iso7816_read_record (app->slot, 2, 1, 0, &buffer[1], &buflen[1]);
161   if (err)
162     {
163       xfree (buffer[0]);
164       return err;
165     }
166
167   if (app->app_local->nks_version < 3)
168     {
169       /* Old versions of NKS store the values in a TLV encoded format.
170          We need to do some checks.  */
171       for (i=0; i < 2; i++)
172         {
173           /* Check that the value appears like an integer encoded as
174              Simple-TLV.  We don't check the tag because the tests cards I
175              have use 1 for both, the modulus and the exponent - the
176              example in the documentation gives 2 for the exponent. */
177           if (buflen[i] < 3)
178             err = gpg_error (GPG_ERR_TOO_SHORT);
179           else if (buffer[i][1] != buflen[i]-2 )
180             err = gpg_error (GPG_ERR_INV_OBJ);
181           else
182             offset[i] = 2;
183         }
184     }
185   else
186     {
187       /* Remove leading zeroes to get a correct keygrip.  Take care of
188          negative numbers.  We should also fix it the same way in
189          libgcrypt but we can't yet rely on it yet.  */
190       for (i=0; i < 2; i++)
191         {
192           while (buflen[i]-offset[i] > 1
193                  && !buffer[i][offset[i]]
194                  && !(buffer[i][offset[i]+1] & 0x80))
195             offset[i]++;
196         }
197     }
198
199   /* Check whether negative values are not prefixed with a zero and
200      fix that.  */
201   for (i=0; i < 2; i++)
202     {
203       if ((buflen[i]-offset[i]) && (buffer[i][offset[i]] & 0x80))
204         {
205           unsigned char *newbuf;
206           size_t newlen;
207
208           newlen = 1 + buflen[i] - offset[i];
209           newbuf = xtrymalloc (newlen);
210           if (!newlen)
211             {
212               xfree (buffer[0]);
213               xfree (buffer[1]);
214               return gpg_error_from_syserror ();
215             }
216           newbuf[0] = 0;
217           memcpy (newbuf+1, buffer[i]+offset[i], buflen[i] - offset[i]);
218           xfree (buffer[i]);
219           buffer[i] = newbuf;
220           buflen[i] = newlen;
221           offset[i] = 0;
222         }
223     }
224
225   if (!err)
226     err = gcry_sexp_build (&sexp, NULL,
227                            "(public-key (rsa (n %b) (e %b)))",
228                            (int)buflen[0]-offset[0], buffer[0]+offset[0],
229                            (int)buflen[1]-offset[1], buffer[1]+offset[1]);
230
231   xfree (buffer[0]);
232   xfree (buffer[1]);
233   if (err)
234     return err;
235
236   if (!gcry_pk_get_keygrip (sexp, grip))
237     {
238       err = gpg_error (GPG_ERR_INTERNAL); /* i.e. RSA not supported by
239                                              libgcrypt. */
240     }
241   else
242     {
243       bin2hex (grip, 20, r_gripstr);
244     }
245   gcry_sexp_release (sexp);
246   return err;
247 }
248
249
250 /* TCOS responds to a verify with empty data (i.e. without the Lc
251    byte) with the status of the PIN.  PWID is the PIN ID, If SIGG is
252    true, the application is switched into SigG mode.
253    Returns:
254             -1 = Error retrieving the data,
255             -2 = No such PIN,
256             -3 = PIN blocked,
257             -4 = NullPIN activ,
258         n >= 0 = Number of verification attempts left.  */
259 static int
260 get_chv_status (app_t app, int sigg, int pwid)
261 {
262   unsigned char *result = NULL;
263   size_t resultlen;
264   char command[4];
265   int rc;
266
267   if (switch_application (app, sigg))
268     return sigg? -2 : -1; /* No such PIN / General error.  */
269
270   command[0] = 0x00;
271   command[1] = 0x20;
272   command[2] = 0x00;
273   command[3] = pwid;
274
275   if (apdu_send_direct (app->slot, 0, (unsigned char *)command,
276                         4, 0, &result, &resultlen))
277     rc = -1; /* Error. */
278   else if (resultlen < 2)
279     rc = -1; /* Error. */
280   else
281     {
282       unsigned int sw = buf16_to_uint (result+resultlen-2);
283
284       if (sw == 0x6a88)
285         rc = -2; /* No such PIN.  */
286       else if (sw == 0x6983)
287         rc = -3; /* PIN is blocked.  */
288       else if (sw == 0x6985)
289         rc = -4; /* NullPIN is activ.  */
290       else if ((sw & 0xfff0) == 0x63C0)
291         rc = (sw & 0x000f); /* PIN has N tries left.  */
292       else
293         rc = -1; /* Other error.  */
294     }
295   xfree (result);
296
297   return rc;
298 }
299
300
301 /* Implement the GETATTR command.  This is similar to the LEARN
302    command but returns just one value via the status interface. */
303 static gpg_error_t
304 do_getattr (app_t app, ctrl_t ctrl, const char *name)
305 {
306   static struct {
307     const char *name;
308     int special;
309   } table[] = {
310     { "$AUTHKEYID",   1 },
311     { "NKS-VERSION",  2 },
312     { "CHV-STATUS",   3 },
313     { NULL, 0 }
314   };
315   gpg_error_t err = 0;
316   int idx;
317   char buffer[100];
318
319   err = switch_application (app, 0);
320   if (err)
321     return err;
322
323   for (idx=0; table[idx].name && strcmp (table[idx].name, name); idx++)
324     ;
325   if (!table[idx].name)
326     return gpg_error (GPG_ERR_INV_NAME);
327
328   switch (table[idx].special)
329     {
330     case 1: /* $AUTHKEYID */
331       {
332         /* NetKey 3.0 cards define an authentication key but according
333            to the specs this key is only usable for encryption and not
334            signing.  it might work anyway but it has not yet been
335            tested - fixme.  Thus for now we use the NKS signature key
336            for authentication.  */
337         char const tmp[] = "NKS-NKS3.4531";
338         send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
339       }
340       break;
341
342     case 2: /* NKS-VERSION */
343       snprintf (buffer, sizeof buffer, "%d", app->app_local->nks_version);
344       send_status_info (ctrl, table[idx].name,
345                         buffer, strlen (buffer), NULL, 0);
346       break;
347
348     case 3: /* CHV-STATUS */
349       {
350         /* Returns: PW1.CH PW2.CH PW1.CH.SIG PW2.CH.SIG That are the
351            two global passwords followed by the two SigG passwords.
352            For the values, see the function get_chv_status.  */
353         int tmp[4];
354
355         /* We use a helper array so that we can control that there is
356            no superfluous application switch.  Note that PW2.CH.SIG
357            really has the identifier 0x83 and not 0x82 as one would
358            expect.  */
359         tmp[0] = get_chv_status (app, 0, 0x00);
360         tmp[1] = get_chv_status (app, 0, 0x01);
361         tmp[2] = get_chv_status (app, 1, 0x81);
362         tmp[3] = get_chv_status (app, 1, 0x83);
363         snprintf (buffer, sizeof buffer,
364                   "%d %d %d %d", tmp[0], tmp[1], tmp[2], tmp[3]);
365         send_status_info (ctrl, table[idx].name,
366                           buffer, strlen (buffer), NULL, 0);
367       }
368       break;
369
370
371     default:
372       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
373       break;
374     }
375
376   return err;
377 }
378
379
380
381 static void
382 do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags, int is_sigg)
383 {
384   gpg_error_t err;
385   char ct_buf[100], id_buf[100];
386   int i;
387   const char *tag;
388
389   if (is_sigg)
390     tag = "SIGG";
391   else if (app->app_local->nks_version < 3)
392     tag = "DF01";
393   else
394     tag = "NKS3";
395
396   /* Output information about all useful objects in the NKS application. */
397   for (i=0; filelist[i].fid; i++)
398     {
399       if (filelist[i].nks_ver > app->app_local->nks_version)
400         continue;
401
402       if (!!filelist[i].is_sigg != !!is_sigg)
403         continue;
404
405       if (filelist[i].certtype && !(flags &1))
406         {
407           size_t len;
408
409           len = app_help_read_length_of_cert (app->slot,
410                                               filelist[i].fid, NULL);
411           if (len)
412             {
413               /* FIXME: We should store the length in the application's
414                  context so that a following readcert does only need to
415                  read that many bytes. */
416               snprintf (ct_buf, sizeof ct_buf, "%d", filelist[i].certtype);
417               snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X",
418                         tag, filelist[i].fid);
419               send_status_info (ctrl, "CERTINFO",
420                                 ct_buf, strlen (ct_buf),
421                                 id_buf, strlen (id_buf),
422                                 NULL, (size_t)0);
423             }
424         }
425       else if (filelist[i].iskeypair)
426         {
427           char gripstr[40+1];
428
429           err = keygripstr_from_pk_file (app, filelist[i].fid, gripstr);
430           if (err)
431             log_error ("can't get keygrip from FID 0x%04X: %s\n",
432                        filelist[i].fid, gpg_strerror (err));
433           else
434             {
435               snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X",
436                         tag, filelist[i].fid);
437               send_status_info (ctrl, "KEYPAIRINFO",
438                                 gripstr, 40,
439                                 id_buf, strlen (id_buf),
440                                 NULL, (size_t)0);
441             }
442         }
443     }
444
445
446 }
447
448
449 static gpg_error_t
450 do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
451 {
452   gpg_error_t err;
453
454   err = switch_application (app, 0);
455   if (err)
456     return err;
457
458   do_learn_status_core (app, ctrl, flags, 0);
459
460   err = switch_application (app, 1);
461   if (err)
462     return 0;  /* Silently ignore if we can't switch to SigG.  */
463
464   do_learn_status_core (app, ctrl, flags, 1);
465
466   return 0;
467 }
468
469
470
471
472 /* Read the certificate with id CERTID (as returned by learn_status in
473    the CERTINFO status lines) and return it in the freshly allocated
474    buffer put into CERT and the length of the certificate put into
475    CERTLEN. */
476 static gpg_error_t
477 do_readcert (app_t app, const char *certid,
478              unsigned char **cert, size_t *certlen)
479 {
480   int i, fid;
481   gpg_error_t err;
482   unsigned char *buffer;
483   const unsigned char *p;
484   size_t buflen, n;
485   int class, tag, constructed, ndef;
486   size_t totobjlen, objlen, hdrlen;
487   int rootca = 0;
488   int is_sigg = 0;
489
490   *cert = NULL;
491   *certlen = 0;
492
493   if (!strncmp (certid, "NKS-NKS3.", 9))
494     ;
495   else if (!strncmp (certid, "NKS-DF01.", 9))
496     ;
497   else if (!strncmp (certid, "NKS-SIGG.", 9))
498     is_sigg = 1;
499   else
500     return gpg_error (GPG_ERR_INV_ID);
501
502   err = switch_application (app, is_sigg);
503   if (err)
504     return err;
505
506   certid += 9;
507   if (!hexdigitp (certid) || !hexdigitp (certid+1)
508       || !hexdigitp (certid+2) || !hexdigitp (certid+3)
509       || certid[4])
510     return gpg_error (GPG_ERR_INV_ID);
511   fid = xtoi_4 (certid);
512   for (i=0; filelist[i].fid; i++)
513     if ((filelist[i].certtype || filelist[i].iskeypair)
514         && filelist[i].fid == fid)
515       break;
516   if (!filelist[i].fid)
517     return gpg_error (GPG_ERR_NOT_FOUND);
518
519   /* If the requested objects is a plain public key, redirect it to
520      the corresponding certificate.  The whole system is a bit messy
521      because we sometime use the key directly or let the caller
522      retrieve the key from the certificate.  The rationale for
523      that is to support not-yet stored certificates. */
524   if (filelist[i].iskeypair)
525     fid = filelist[i].iskeypair;
526
527
528   /* Read the entire file.  fixme: This could be optimized by first
529      reading the header to figure out how long the certificate
530      actually is. */
531   err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
532   if (err)
533     {
534       log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
535       return err;
536     }
537
538   err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
539   if (err)
540     {
541       log_error ("error reading certificate from FID 0x%04X: %s\n",
542                  fid, gpg_strerror (err));
543       return err;
544     }
545
546   if (!buflen || *buffer == 0xff)
547     {
548       log_info ("no certificate contained in FID 0x%04X\n", fid);
549       err = gpg_error (GPG_ERR_NOT_FOUND);
550       goto leave;
551     }
552
553   /* Now figure something out about the object. */
554   p = buffer;
555   n = buflen;
556   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
557                           &ndef, &objlen, &hdrlen);
558   if (err)
559     goto leave;
560   if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed )
561     ;
562   else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed )
563     rootca = 1;
564   else
565     return gpg_error (GPG_ERR_INV_OBJ);
566   totobjlen = objlen + hdrlen;
567   assert (totobjlen <= buflen);
568
569   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
570                           &ndef, &objlen, &hdrlen);
571   if (err)
572     goto leave;
573
574   if (rootca)
575     ;
576   else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
577     {
578       const unsigned char *save_p;
579
580       /* The certificate seems to be contained in a userCertificate
581          container.  Skip this and assume the following sequence is
582          the certificate. */
583       if (n < objlen)
584         {
585           err = gpg_error (GPG_ERR_INV_OBJ);
586           goto leave;
587         }
588       p += objlen;
589       n -= objlen;
590       save_p = p;
591       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
592                               &ndef, &objlen, &hdrlen);
593       if (err)
594         goto leave;
595       if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) )
596         return gpg_error (GPG_ERR_INV_OBJ);
597       totobjlen = objlen + hdrlen;
598       assert (save_p + totobjlen <= buffer + buflen);
599       memmove (buffer, save_p, totobjlen);
600     }
601
602   *cert = buffer;
603   buffer = NULL;
604   *certlen = totobjlen;
605
606  leave:
607   xfree (buffer);
608   return err;
609 }
610
611
612 /* Handle the READKEY command. On success a canonical encoded
613    S-expression with the public key will get stored at PK and its
614    length at PKLEN; the caller must release that buffer.  On error PK
615    and PKLEN are not changed and an error code is returned.  As of now
616    this function is only useful for the internal authentication key.
617    Other keys are automagically retrieved via by means of the
618    certificate parsing code in commands.c:cmd_readkey.  For internal
619    use PK and PKLEN may be NULL to just check for an existing key.  */
620 static gpg_error_t
621 do_readkey (app_t app, int advanced, const char *keyid,
622             unsigned char **pk, size_t *pklen)
623 {
624   gpg_error_t err;
625   unsigned char *buffer[2];
626   size_t buflen[2];
627   unsigned short path[1] = { 0x4500 };
628
629   if (advanced)
630     return GPG_ERR_NOT_SUPPORTED;
631
632   /* We use a generic name to retrieve PK.AUT.IFD-SPK.  */
633   if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
634     ;
635   else /* Return the error code expected by cmd_readkey.  */
636     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
637
638   /* Access the KEYD file which is always in the master directory.  */
639   err = iso7816_select_path (app->slot, path, DIM (path), NULL, NULL);
640   if (err)
641     return err;
642   /* Due to the above select we need to re-select our application.  */
643   app->app_local->need_app_select = 1;
644   /* Get the two records.  */
645   err = iso7816_read_record (app->slot, 5, 1, 0, &buffer[0], &buflen[0]);
646   if (err)
647     return err;
648   if (all_zero_p (buffer[0], buflen[0]))
649     {
650       xfree (buffer[0]);
651       return gpg_error (GPG_ERR_NOT_FOUND);
652     }
653   err = iso7816_read_record (app->slot, 6, 1, 0, &buffer[1], &buflen[1]);
654   if (err)
655     {
656       xfree (buffer[0]);
657       return err;
658     }
659
660   if (pk && pklen)
661     {
662       *pk = make_canon_sexp_from_rsa_pk (buffer[0], buflen[0],
663                                          buffer[1], buflen[1],
664                                          pklen);
665       if (!*pk)
666         err = gpg_error_from_syserror ();
667     }
668
669   xfree (buffer[0]);
670   xfree (buffer[1]);
671   return err;
672 }
673
674
675 /* Handle the WRITEKEY command for NKS.  This function expects a
676    canonical encoded S-expression with the public key in KEYDATA and
677    its length in KEYDATALEN.  The only supported KEYID is
678    "$IFDAUTHKEY" to store the terminal key on the card.  Bit 0 of
679    FLAGS indicates whether an existing key shall get overwritten.
680    PINCB and PINCB_ARG are the usual arguments for the pinentry
681    callback.  */
682 static gpg_error_t
683 do_writekey (app_t app, ctrl_t ctrl,
684              const char *keyid, unsigned int flags,
685              gpg_error_t (*pincb)(void*, const char *, char **),
686              void *pincb_arg,
687              const unsigned char *keydata, size_t keydatalen)
688 {
689   gpg_error_t err;
690   int force = (flags & 1);
691   const unsigned char *rsa_n = NULL;
692   const unsigned char *rsa_e = NULL;
693   size_t rsa_n_len, rsa_e_len;
694   unsigned int nbits;
695
696   (void)ctrl;
697   (void)pincb;
698   (void)pincb_arg;
699
700   if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
701     ;
702   else
703     return gpg_error (GPG_ERR_INV_ID);
704
705   if (!force && !do_readkey (app, 0, keyid, NULL, NULL))
706     return gpg_error (GPG_ERR_EEXIST);
707
708   /* Parse the S-expression.  */
709   err = get_rsa_pk_from_canon_sexp (keydata, keydatalen,
710                                     &rsa_n, &rsa_n_len, &rsa_e, &rsa_e_len);
711   if (err)
712     goto leave;
713
714   /* Check that the parameters match the requirements.  */
715   nbits = app_help_count_bits (rsa_n, rsa_n_len);
716   if (nbits != 1024)
717     {
718       log_error (_("RSA modulus missing or not of size %d bits\n"), 1024);
719       err = gpg_error (GPG_ERR_BAD_PUBKEY);
720       goto leave;
721     }
722
723   nbits = app_help_count_bits (rsa_e, rsa_e_len);
724   if (nbits < 2 || nbits > 32)
725     {
726       log_error (_("RSA public exponent missing or larger than %d bits\n"),
727                  32);
728       err = gpg_error (GPG_ERR_BAD_PUBKEY);
729       goto leave;
730     }
731
732 /*   /\* Store them.  *\/ */
733 /*   err = verify_pin (app, 0, NULL, pincb, pincb_arg); */
734 /*   if (err) */
735 /*     goto leave; */
736
737   /* Send the MSE:Store_Public_Key.  */
738   err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
739 /*   mse = xtrymalloc (1000); */
740
741 /*   mse[0] = 0x80; /\* Algorithm reference.  *\/ */
742 /*   mse[1] = 1; */
743 /*   mse[2] = 0x17; */
744 /*   mse[3] = 0x84; /\* Private key reference.  *\/ */
745 /*   mse[4] = 1; */
746 /*   mse[5] = 0x77; */
747 /*   mse[6] = 0x7F; /\* Public key parameter.  *\/ */
748 /*   mse[7] = 0x49; */
749 /*   mse[8] = 0x81; */
750 /*   mse[9] = 3 + 0x80 + 2 + rsa_e_len; */
751 /*   mse[10] = 0x81; /\* RSA modulus of 128 byte.  *\/ */
752 /*   mse[11] = 0x81; */
753 /*   mse[12] = rsa_n_len; */
754 /*   memcpy (mse+12, rsa_n, rsa_n_len); */
755 /*   mse[10] = 0x82; /\* RSA public exponent of up to 4 bytes.  *\/ */
756 /*   mse[12] = rsa_e_len; */
757 /*   memcpy (mse+12, rsa_e, rsa_e_len); */
758 /*   err = iso7816_manage_security_env (app->slot, 0x81, 0xB6, */
759 /*                                      mse, sizeof mse); */
760
761  leave:
762   return err;
763 }
764
765
766 static gpg_error_t
767 basic_pin_checks (const char *pinvalue, int minlen, int maxlen)
768 {
769   if (strlen (pinvalue) < minlen)
770     {
771       log_error ("PIN is too short; minimum length is %d\n", minlen);
772       return gpg_error (GPG_ERR_BAD_PIN);
773     }
774   if (strlen (pinvalue) > maxlen)
775     {
776       log_error ("PIN is too large; maximum length is %d\n", maxlen);
777       return gpg_error (GPG_ERR_BAD_PIN);
778     }
779   return 0;
780 }
781
782
783 /* Verify the PIN if required.  */
784 static gpg_error_t
785 verify_pin (app_t app, int pwid, const char *desc,
786             gpg_error_t (*pincb)(void*, const char *, char **),
787             void *pincb_arg)
788 {
789   pininfo_t pininfo;
790   int rc;
791
792   if (!desc)
793     desc = "PIN";
794
795   memset (&pininfo, 0, sizeof pininfo);
796   pininfo.fixedlen = -1;
797   pininfo.minlen = 6;
798   pininfo.maxlen = 16;
799
800   if (!opt.disable_pinpad
801       && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
802     {
803       rc = pincb (pincb_arg, desc, NULL);
804       if (rc)
805         {
806           log_info (_("PIN callback returned error: %s\n"),
807                     gpg_strerror (rc));
808           return rc;
809         }
810
811       rc = iso7816_verify_kp (app->slot, pwid, &pininfo);
812       pincb (pincb_arg, NULL, NULL);  /* Dismiss the prompt. */
813     }
814   else
815     {
816       char *pinvalue;
817
818       rc = pincb (pincb_arg, desc, &pinvalue);
819       if (rc)
820         {
821           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
822           return rc;
823         }
824
825       rc = basic_pin_checks (pinvalue, pininfo.minlen, pininfo.maxlen);
826       if (rc)
827         {
828           xfree (pinvalue);
829           return rc;
830         }
831
832       rc = iso7816_verify (app->slot, pwid, pinvalue, strlen (pinvalue));
833       xfree (pinvalue);
834     }
835
836   if (rc)
837     {
838       if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
839         log_error (_("the NullPIN has not yet been changed\n"));
840       else
841         log_error ("verify PIN failed\n");
842       return rc;
843     }
844
845   return 0;
846 }
847
848
849 /* Create the signature and return the allocated result in OUTDATA.
850    If a PIN is required the PINCB will be used to ask for the PIN;
851    that callback should return the PIN in an allocated buffer and
852    store that in the 3rd argument.  */
853 static gpg_error_t
854 do_sign (app_t app, const char *keyidstr, int hashalgo,
855          gpg_error_t (*pincb)(void*, const char *, char **),
856          void *pincb_arg,
857          const void *indata, size_t indatalen,
858          unsigned char **outdata, size_t *outdatalen )
859 {
860   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
861     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
862       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
863   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
864     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
865       0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
866   int rc, i;
867   int is_sigg = 0;
868   int fid;
869   unsigned char kid;
870   unsigned char data[83];   /* Must be large enough for a SHA-1 digest
871                                + the largest OID prefix. */
872   size_t datalen;
873
874   if (!keyidstr || !*keyidstr)
875     return gpg_error (GPG_ERR_INV_VALUE);
876   switch (indatalen)
877     {
878     case 16: case 20: case 35: case 47: case 51: case 67: case 83: break;
879     default: return gpg_error (GPG_ERR_INV_VALUE);
880     }
881
882   /* Check that the provided ID is valid.  This is not really needed
883      but we do it to enforce correct usage by the caller. */
884   if (!strncmp (keyidstr, "NKS-NKS3.", 9) )
885     ;
886   else if (!strncmp (keyidstr, "NKS-DF01.", 9) )
887     ;
888   else if (!strncmp (keyidstr, "NKS-SIGG.", 9) )
889     is_sigg = 1;
890   else
891     return gpg_error (GPG_ERR_INV_ID);
892   keyidstr += 9;
893
894   rc = switch_application (app, is_sigg);
895   if (rc)
896     return rc;
897
898   if (is_sigg && app->app_local->sigg_is_msig)
899     {
900       log_info ("mass signature cards are not allowed\n");
901       return gpg_error (GPG_ERR_NOT_SUPPORTED);
902     }
903
904   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
905       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
906       || keyidstr[4])
907     return gpg_error (GPG_ERR_INV_ID);
908   fid = xtoi_4 (keyidstr);
909   for (i=0; filelist[i].fid; i++)
910     if (filelist[i].iskeypair && filelist[i].fid == fid)
911       break;
912   if (!filelist[i].fid)
913     return gpg_error (GPG_ERR_NOT_FOUND);
914   if (!filelist[i].issignkey)
915     return gpg_error (GPG_ERR_INV_ID);
916   kid = filelist[i].kid;
917
918   /* Prepare the DER object from INDATA.  */
919   if (app->app_local->nks_version > 2 && (indatalen == 35
920                                           || indatalen == 47
921                                           || indatalen == 51
922                                           || indatalen == 67
923                                           || indatalen == 83))
924     {
925       /* The caller send data matching the length of the ASN.1 encoded
926          hash for SHA-{1,224,256,384,512}.  Assume that is okay.  */
927       assert (indatalen <= sizeof data);
928       memcpy (data, indata, indatalen);
929       datalen = indatalen;
930     }
931   else if (indatalen == 35)
932     {
933       /* Alright, the caller was so kind to send us an already
934          prepared DER object.  This is for TCOS 2. */
935       if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
936         ;
937       else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata,rmd160_prefix,15))
938         ;
939       else
940         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
941       memcpy (data, indata, indatalen);
942       datalen = 35;
943     }
944   else if (indatalen == 20)
945     {
946       if (hashalgo == GCRY_MD_SHA1)
947         memcpy (data, sha1_prefix, 15);
948       else if (hashalgo == GCRY_MD_RMD160)
949         memcpy (data, rmd160_prefix, 15);
950       else
951         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
952       memcpy (data+15, indata, indatalen);
953       datalen = 35;
954     }
955   else
956     return gpg_error (GPG_ERR_INV_VALUE);
957
958
959   /* Send an MSE for PSO:Computer_Signature.  */
960   if (app->app_local->nks_version > 2)
961     {
962       unsigned char mse[6];
963
964       mse[0] = 0x80; /* Algorithm reference.  */
965       mse[1] = 1;
966       mse[2] = 2;    /* RSA, card does pkcs#1 v1.5 padding, no ASN.1 check.  */
967       mse[3] = 0x84; /* Private key reference.  */
968       mse[4] = 1;
969       mse[5] = kid;
970       rc = iso7816_manage_security_env (app->slot, 0x41, 0xB6,
971                                         mse, sizeof mse);
972     }
973   /* Verify using PW1.CH.  */
974   if (!rc)
975     rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
976   /* Compute the signature.  */
977   if (!rc)
978     rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0,
979                              outdata, outdatalen);
980   return rc;
981 }
982
983
984
985 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
986    If a PIN is required the PINCB will be used to ask for the PIN; it
987    should return the PIN in an allocated buffer and put it into PIN.  */
988 static gpg_error_t
989 do_decipher (app_t app, const char *keyidstr,
990              gpg_error_t (*pincb)(void*, const char *, char **),
991              void *pincb_arg,
992              const void *indata, size_t indatalen,
993              unsigned char **outdata, size_t *outdatalen,
994              unsigned int *r_info)
995 {
996   int rc, i;
997   int is_sigg = 0;
998   int fid;
999   int kid;
1000
1001   (void)r_info;
1002
1003   if (!keyidstr || !*keyidstr || !indatalen)
1004     return gpg_error (GPG_ERR_INV_VALUE);
1005
1006   /* Check that the provided ID is valid.  This is not really needed
1007      but we do it to to enforce correct usage by the caller. */
1008   if (!strncmp (keyidstr, "NKS-NKS3.", 9) )
1009     ;
1010   else if (!strncmp (keyidstr, "NKS-DF01.", 9) )
1011     ;
1012   else if (!strncmp (keyidstr, "NKS-SIGG.", 9) )
1013     is_sigg = 1;
1014   else
1015     return gpg_error (GPG_ERR_INV_ID);
1016   keyidstr += 9;
1017
1018   rc = switch_application (app, is_sigg);
1019   if (rc)
1020     return rc;
1021
1022   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
1023       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
1024       || keyidstr[4])
1025     return gpg_error (GPG_ERR_INV_ID);
1026   fid = xtoi_4 (keyidstr);
1027   for (i=0; filelist[i].fid; i++)
1028     if (filelist[i].iskeypair && filelist[i].fid == fid)
1029       break;
1030   if (!filelist[i].fid)
1031     return gpg_error (GPG_ERR_NOT_FOUND);
1032   if (!filelist[i].isenckey)
1033     return gpg_error (GPG_ERR_INV_ID);
1034   kid = filelist[i].kid;
1035
1036   if (app->app_local->nks_version > 2)
1037     {
1038       unsigned char mse[6];
1039       mse[0] = 0x80; /* Algorithm reference.  */
1040       mse[1] = 1;
1041       mse[2] = 0x0a; /* RSA no padding.  (0x1A is pkcs#1.5 padding.)  */
1042       mse[3] = 0x84; /* Private key reference.  */
1043       mse[4] = 1;
1044       mse[5] = kid;
1045       rc = iso7816_manage_security_env (app->slot, 0x41, 0xB8,
1046                                         mse, sizeof mse);
1047     }
1048   else
1049     {
1050       static const unsigned char mse[] =
1051         {
1052           0x80, 1, 0x10, /* Select algorithm RSA. */
1053           0x84, 1, 0x81  /* Select local secret key 1 for decryption. */
1054         };
1055       rc = iso7816_manage_security_env (app->slot, 0xC1, 0xB8,
1056                                         mse, sizeof mse);
1057
1058     }
1059
1060   if (!rc)
1061     rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
1062
1063   /* Note that we need to use extended length APDUs for TCOS 3 cards.
1064      Command chaining does not work.  */
1065   if (!rc)
1066     rc = iso7816_decipher (app->slot, app->app_local->nks_version > 2? 1:0,
1067                            indata, indatalen, 0, 0x81,
1068                            outdata, outdatalen);
1069   return rc;
1070 }
1071
1072
1073
1074 /* Parse a password ID string.  Returns NULL on error or a string
1075    suitable as passphrase prompt on success.  On success stores the
1076    reference value for the password at R_PWID and a flag indicating
1077    that the SigG application is to be used at R_SIGG.  If NEW_MODE is
1078    true, the returned description is suitable for a new Password.
1079    Supported values for PWIDSTR are:
1080
1081      PW1.CH       - Global password 1
1082      PW2.CH       - Global password 2
1083      PW1.CH.SIG   - SigG password 1
1084      PW2.CH.SIG   - SigG password 2
1085  */
1086 static const char *
1087 parse_pwidstr (const char *pwidstr, int new_mode, int *r_sigg, int *r_pwid)
1088 {
1089   const char *desc;
1090
1091   if (!pwidstr)
1092     desc = NULL;
1093   else if (!strcmp (pwidstr, "PW1.CH"))
1094     {
1095       *r_sigg = 0;
1096       *r_pwid = 0x00;
1097       /* TRANSLATORS: Do not translate the "|*|" prefixes but keep
1098          them verbatim at the start of the string.  */
1099       desc = (new_mode
1100               ? _("|N|Please enter a new PIN for the standard keys.")
1101               : _("||Please enter the PIN for the standard keys."));
1102     }
1103   else if (!strcmp (pwidstr, "PW2.CH"))
1104     {
1105       *r_pwid = 0x01;
1106       desc = (new_mode
1107               ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
1108                   "for the standard keys.")
1109               : _("|P|Please enter the PIN Unblocking Code (PUK) "
1110                   "for the standard keys."));
1111     }
1112   else if (!strcmp (pwidstr, "PW1.CH.SIG"))
1113     {
1114       *r_pwid = 0x81;
1115       *r_sigg = 1;
1116       desc = (new_mode
1117               ? _("|N|Please enter a new PIN for the key to create "
1118                   "qualified signatures.")
1119               : _("||Please enter the PIN for the key to create "
1120                   "qualified signatures."));
1121     }
1122   else if (!strcmp (pwidstr, "PW2.CH.SIG"))
1123     {
1124       *r_pwid = 0x83;  /* Yes, that is 83 and not 82.  */
1125       *r_sigg = 1;
1126       desc = (new_mode
1127               ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
1128                   "for the key to create qualified signatures.")
1129               : _("|P|Please enter the PIN Unblocking Code (PUK) "
1130                   "for the key to create qualified signatures."));
1131     }
1132   else
1133     {
1134       *r_pwid = 0; /* Only to avoid gcc warning in calling function.  */
1135       desc = NULL; /* Error.  */
1136     }
1137
1138   return desc;
1139 }
1140
1141
1142 /* Handle the PASSWD command. See parse_pwidstr() for allowed values
1143    for CHVNOSTR.  */
1144 static gpg_error_t
1145 do_change_pin (app_t app, ctrl_t ctrl,  const char *pwidstr,
1146                unsigned int flags,
1147                gpg_error_t (*pincb)(void*, const char *, char **),
1148                void *pincb_arg)
1149 {
1150   gpg_error_t err;
1151   char *newpin = NULL;
1152   char *oldpin = NULL;
1153   size_t newpinlen;
1154   size_t oldpinlen;
1155   int is_sigg;
1156   const char *newdesc;
1157   int pwid;
1158   pininfo_t pininfo;
1159
1160   (void)ctrl;
1161
1162   /* The minimum length is enforced by TCOS, the maximum length is
1163      just a reasonable value.  */
1164   memset (&pininfo, 0, sizeof pininfo);
1165   pininfo.minlen = 6;
1166   pininfo.maxlen = 16;
1167
1168   newdesc = parse_pwidstr (pwidstr, 1, &is_sigg, &pwid);
1169   if (!newdesc)
1170     return gpg_error (GPG_ERR_INV_ID);
1171
1172   err = switch_application (app, is_sigg);
1173   if (err)
1174     return err;
1175
1176   if ((flags & APP_CHANGE_FLAG_NULLPIN))
1177     {
1178       /* With the nullpin flag, we do not verify the PIN - it would
1179          fail if the Nullpin is still set.  */
1180       oldpin = xtrycalloc (1, 6);
1181       if (!oldpin)
1182         {
1183           err = gpg_error_from_syserror ();
1184           goto leave;
1185         }
1186       oldpinlen = 6;
1187     }
1188   else
1189     {
1190       const char *desc;
1191       int dummy1, dummy2;
1192
1193       if ((flags & APP_CHANGE_FLAG_RESET))
1194         {
1195           /* Reset mode: Ask for the alternate PIN.  */
1196           const char *altpwidstr;
1197
1198           if (!strcmp (pwidstr, "PW1.CH"))
1199             altpwidstr = "PW2.CH";
1200           else if (!strcmp (pwidstr, "PW2.CH"))
1201             altpwidstr = "PW1.CH";
1202           else if (!strcmp (pwidstr, "PW1.CH.SIG"))
1203             altpwidstr = "PW2.CH.SIG";
1204           else if (!strcmp (pwidstr, "PW2.CH.SIG"))
1205             altpwidstr = "PW1.CH.SIG";
1206           else
1207             {
1208               err = gpg_error (GPG_ERR_BUG);
1209               goto leave;
1210             }
1211           desc = parse_pwidstr (altpwidstr, 0, &dummy1, &dummy2);
1212         }
1213       else
1214         {
1215           /* Regular change mode:  Ask for the old PIN.  */
1216           desc = parse_pwidstr (pwidstr, 0, &dummy1, &dummy2);
1217         }
1218       err = pincb (pincb_arg, desc, &oldpin);
1219       if (err)
1220         {
1221           log_error ("error getting old PIN: %s\n", gpg_strerror (err));
1222           goto leave;
1223         }
1224       oldpinlen = strlen (oldpin);
1225       err = basic_pin_checks (oldpin, pininfo.minlen, pininfo.maxlen);
1226       if (err)
1227         goto leave;
1228     }
1229
1230   err = pincb (pincb_arg, newdesc, &newpin);
1231   if (err)
1232     {
1233       log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
1234       goto leave;
1235     }
1236   newpinlen = strlen (newpin);
1237
1238   err = basic_pin_checks (newpin, pininfo.minlen, pininfo.maxlen);
1239   if (err)
1240     goto leave;
1241
1242   if ((flags & APP_CHANGE_FLAG_RESET))
1243     {
1244       char *data;
1245       size_t datalen = oldpinlen + newpinlen;
1246
1247       data = xtrymalloc (datalen);
1248       if (!data)
1249         {
1250           err = gpg_error_from_syserror ();
1251           goto leave;
1252         }
1253       memcpy (data, oldpin, oldpinlen);
1254       memcpy (data+oldpinlen, newpin, newpinlen);
1255       err = iso7816_reset_retry_counter_with_rc (app->slot, pwid,
1256                                                  data, datalen);
1257       wipememory (data, datalen);
1258       xfree (data);
1259     }
1260   else
1261     err = iso7816_change_reference_data (app->slot, pwid,
1262                                          oldpin, oldpinlen,
1263                                          newpin, newpinlen);
1264  leave:
1265   xfree (oldpin);
1266   xfree (newpin);
1267   return err;
1268 }
1269
1270
1271 /* Perform a simple verify operation.  KEYIDSTR should be NULL or empty.  */
1272 static gpg_error_t
1273 do_check_pin (app_t app, const char *pwidstr,
1274               gpg_error_t (*pincb)(void*, const char *, char **),
1275               void *pincb_arg)
1276 {
1277   gpg_error_t err;
1278   int pwid;
1279   int is_sigg;
1280   const char *desc;
1281
1282   desc = parse_pwidstr (pwidstr, 0, &is_sigg, &pwid);
1283   if (!desc)
1284     return gpg_error (GPG_ERR_INV_ID);
1285
1286   err = switch_application (app, is_sigg);
1287   if (err)
1288     return err;
1289
1290   return verify_pin (app, pwid, desc, pincb, pincb_arg);
1291 }
1292
1293
1294 /* Return the version of the NKS application.  */
1295 static int
1296 get_nks_version (int slot)
1297 {
1298   unsigned char *result = NULL;
1299   size_t resultlen;
1300   int type;
1301
1302   if (iso7816_apdu_direct (slot, "\x80\xaa\x06\x00\x00", 5, 0,
1303                            &result, &resultlen))
1304     return 2; /* NKS 2 does not support this command.  */
1305
1306   /* Example value:    04 11 19 22 21 6A 20 80 03 03 01 01 01 00 00 00
1307                        vv tt ccccccccccccccccc aa bb cc vvvvvvvvvvv xx
1308      vendor (Philips) -+  |  |                 |  |  |  |           |
1309      chip type -----------+  |                 |  |  |  |           |
1310      chip id ----------------+                 |  |  |  |           |
1311      card type (3 - tcos 3) -------------------+  |  |  |           |
1312      OS version of card type ---------------------+  |  |           |
1313      OS release of card type ------------------------+  |           |
1314      OS vendor internal version ------------------------+           |
1315      RFU -----------------------------------------------------------+
1316   */
1317   if (resultlen < 16)
1318     type = 0;  /* Invalid data returned.  */
1319   else
1320     type = result[8];
1321   xfree (result);
1322
1323   return type;
1324 }
1325
1326
1327 /* If ENABLE_SIGG is true switch to the SigG application if not yet
1328    active.  If false switch to the NKS application if not yet active.
1329    Returns 0 on success.  */
1330 static gpg_error_t
1331 switch_application (app_t app, int enable_sigg)
1332 {
1333   gpg_error_t err;
1334
1335   if (((app->app_local->sigg_active && enable_sigg)
1336        || (!app->app_local->sigg_active && !enable_sigg))
1337       && !app->app_local->need_app_select)
1338     return 0;  /* Already switched.  */
1339
1340   log_info ("app-nks: switching to %s\n", enable_sigg? "SigG":"NKS");
1341   if (enable_sigg)
1342     err = iso7816_select_application (app->slot, aid_sigg, sizeof aid_sigg, 0);
1343   else
1344     err = iso7816_select_application (app->slot, aid_nks, sizeof aid_nks, 0);
1345
1346   if (!err && enable_sigg && app->app_local->nks_version >= 3
1347       && !app->app_local->sigg_msig_checked)
1348     {
1349       /* Check whether this card is a mass signature card.  */
1350       unsigned char *buffer;
1351       size_t buflen;
1352       const unsigned char *tmpl;
1353       size_t tmpllen;
1354
1355       app->app_local->sigg_msig_checked = 1;
1356       app->app_local->sigg_is_msig = 1;
1357       err = iso7816_select_file (app->slot, 0x5349, 0, NULL, NULL);
1358       if (!err)
1359         err = iso7816_read_record (app->slot, 1, 1, 0, &buffer, &buflen);
1360       if (!err)
1361         {
1362           tmpl = find_tlv (buffer, buflen, 0x7a, &tmpllen);
1363           if (tmpl && tmpllen == 12
1364               && !memcmp (tmpl,
1365                           "\x93\x02\x00\x01\xA4\x06\x83\x01\x81\x83\x01\x83",
1366                           12))
1367             app->app_local->sigg_is_msig = 0;
1368           xfree (buffer);
1369         }
1370       if (app->app_local->sigg_is_msig)
1371         log_info ("This is a mass signature card\n");
1372     }
1373
1374   if (!err)
1375     {
1376       app->app_local->need_app_select = 0;
1377       app->app_local->sigg_active = enable_sigg;
1378     }
1379   else
1380     log_error ("app-nks: error switching to %s: %s\n",
1381                enable_sigg? "SigG":"NKS", gpg_strerror (err));
1382
1383   return err;
1384 }
1385
1386
1387 /* Select the NKS application.  */
1388 gpg_error_t
1389 app_select_nks (app_t app)
1390 {
1391   int slot = app->slot;
1392   int rc;
1393
1394   rc = iso7816_select_application (slot, aid_nks, sizeof aid_nks, 0);
1395   if (!rc)
1396     {
1397       app->apptype = "NKS";
1398
1399       app->app_local = xtrycalloc (1, sizeof *app->app_local);
1400       if (!app->app_local)
1401         {
1402           rc = gpg_error (gpg_err_code_from_errno (errno));
1403           goto leave;
1404         }
1405
1406       app->app_local->nks_version = get_nks_version (slot);
1407       if (opt.verbose)
1408         log_info ("Detected NKS version: %d\n", app->app_local->nks_version);
1409
1410       app->fnc.deinit = do_deinit;
1411       app->fnc.learn_status = do_learn_status;
1412       app->fnc.readcert = do_readcert;
1413       app->fnc.readkey = do_readkey;
1414       app->fnc.getattr = do_getattr;
1415       app->fnc.setattr = NULL;
1416       app->fnc.writekey = do_writekey;
1417       app->fnc.genkey = NULL;
1418       app->fnc.sign = do_sign;
1419       app->fnc.auth = NULL;
1420       app->fnc.decipher = do_decipher;
1421       app->fnc.change_pin = do_change_pin;
1422       app->fnc.check_pin = do_check_pin;
1423    }
1424
1425  leave:
1426   if (rc)
1427     do_deinit (app);
1428   return rc;
1429 }