Add option --card-timeout.
[gnupg.git] / scd / app-nks.c
1 /* app-nks.c - The Telesec NKS 2.0 card application.
2  * Copyright (C) 2004, 2007, 2008 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 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <time.h>
27
28 #include "scdaemon.h"
29 #include "i18n.h"
30 #include "iso7816.h"
31 #include "app-common.h"
32 #include "tlv.h"
33
34 static struct
35 {
36   int fid;       /* File ID. */
37   int certtype;  /* Type of certificate or 0 if it is not a certificate. */
38   int iskeypair; /* If true has the FID of the correspoding certificate. */
39   int issignkey; /* True if file is a key usable for signing. */
40   int isenckey;  /* True if file is a key usable for decryption. */
41 } filelist[] = {
42   { 0x4531, 0,  0xC000, 1, 0 }, 
43   { 0xC000, 101 },
44   { 0x4331, 100 },
45   { 0x4332, 100 },
46   { 0xB000, 110 },
47   { 0x45B1, 0,  0xC200, 0, 1 },
48   { 0xC200, 101 },
49   { 0x43B1, 100 },
50   { 0x43B2, 100 },
51   { 0, 0 }
52 };
53
54
55
56 /* Read the file with FID, assume it contains a public key and return
57    its keygrip in the caller provided 41 byte buffer R_GRIPSTR. */
58 static gpg_error_t
59 keygripstr_from_pk_file (int slot, int fid, char *r_gripstr)
60 {
61   gpg_error_t err;
62   unsigned char grip[20];
63   unsigned char *buffer[2];
64   size_t buflen[2];
65   gcry_sexp_t sexp;
66   int i;
67   
68   err = iso7816_select_file (slot, fid, 0, NULL, NULL);
69   if (err)
70     return err;
71   err = iso7816_read_record (slot, 1, 1, 0, &buffer[0], &buflen[0]);
72   if (err)
73     return err;
74   err = iso7816_read_record (slot, 2, 1, 0, &buffer[1], &buflen[1]);
75   if (err)
76     {
77       xfree (buffer[0]);
78       return err;
79     }
80   
81   for (i=0; i < 2; i++)
82     {
83       /* Check that the value appears like an integer encoded as
84          Simple-TLV.  We don't check the tag because the tests cards I
85          have use 1 for both, the modulus and the exponent - the
86          example in the documentation gives 2 for the exponent. */
87       if (buflen[i] < 3)
88         err = gpg_error (GPG_ERR_TOO_SHORT);
89       else if (buffer[i][1] != buflen[i]-2 )
90         err = gpg_error (GPG_ERR_INV_OBJ);
91     }
92
93   if (!err)
94     err = gcry_sexp_build (&sexp, NULL,
95                            "(public-key (rsa (n %b) (e %b)))",
96                            (int)buflen[0]-2, buffer[0]+2,
97                            (int)buflen[1]-2, buffer[1]+2);
98
99   xfree (buffer[0]);
100   xfree (buffer[1]);
101   if (err)
102     return err;
103
104   if (!gcry_pk_get_keygrip (sexp, grip))
105     {
106       err = gpg_error (GPG_ERR_INTERNAL); /* i.e. RSA not supported by
107                                              libgcrypt. */
108     }
109   else
110     {
111       bin2hex (grip, 20, r_gripstr);
112     }
113   gcry_sexp_release (sexp);
114   return err;
115 }
116
117
118
119 static gpg_error_t
120 do_learn_status (app_t app, ctrl_t ctrl)
121 {
122   gpg_error_t err;
123   char ct_buf[100], id_buf[100];
124   int i;
125
126   /* Output information about all useful objects. */
127   for (i=0; filelist[i].fid; i++)
128     {
129       if (filelist[i].certtype)
130         {
131           size_t len;
132
133           len = app_help_read_length_of_cert (app->slot,
134                                               filelist[i].fid, NULL);
135           if (len)
136             {
137               /* FIXME: We should store the length in the application's
138                  context so that a following readcert does only need to
139                  read that many bytes. */
140               sprintf (ct_buf, "%d", filelist[i].certtype);
141               sprintf (id_buf, "NKS-DF01.%04X", filelist[i].fid);
142               send_status_info (ctrl, "CERTINFO",
143                                 ct_buf, strlen (ct_buf), 
144                                 id_buf, strlen (id_buf), 
145                                 NULL, (size_t)0);
146             }
147         }
148       else if (filelist[i].iskeypair)
149         {
150           char gripstr[40+1];
151
152           err = keygripstr_from_pk_file (app->slot, filelist[i].fid, gripstr);
153           if (err)
154             log_error ("can't get keygrip from FID 0x%04X: %s\n",
155                        filelist[i].fid, gpg_strerror (err));
156           else
157             {
158               sprintf (id_buf, "NKS-DF01.%04X", filelist[i].fid);
159               send_status_info (ctrl, "KEYPAIRINFO",
160                                 gripstr, 40, 
161                                 id_buf, strlen (id_buf), 
162                                 NULL, (size_t)0);
163             }
164         }
165     }
166
167   return 0;
168 }
169
170
171
172
173 /* Read the certificate with id CERTID (as returned by learn_status in
174    the CERTINFO status lines) and return it in the freshly allocated
175    buffer put into CERT and the length of the certificate put into
176    CERTLEN. */
177 static gpg_error_t
178 do_readcert (app_t app, const char *certid,
179              unsigned char **cert, size_t *certlen)
180 {
181   int i, fid;
182   gpg_error_t err;
183   unsigned char *buffer;
184   const unsigned char *p;
185   size_t buflen, n;
186   int class, tag, constructed, ndef;
187   size_t totobjlen, objlen, hdrlen;
188   int rootca = 0;
189
190   *cert = NULL;
191   *certlen = 0;
192   if (strncmp (certid, "NKS-DF01.", 9) ) 
193     return gpg_error (GPG_ERR_INV_ID);
194   certid += 9;
195   if (!hexdigitp (certid) || !hexdigitp (certid+1)
196       || !hexdigitp (certid+2) || !hexdigitp (certid+3) 
197       || certid[4])
198     return gpg_error (GPG_ERR_INV_ID);
199   fid = xtoi_4 (certid);
200   for (i=0; filelist[i].fid; i++)
201     if ((filelist[i].certtype || filelist[i].iskeypair)
202         && filelist[i].fid == fid)
203       break;
204   if (!filelist[i].fid)
205     return gpg_error (GPG_ERR_NOT_FOUND);
206
207   /* If the requested objects is a plain public key, redirect it to
208      the corresponding certificate.  The whole system is a bit messy
209      because we sometime use the key directly or let the caller
210      retrieve the key from the certificate.  The rationale for
211      that is to support not-yet stored certificates. */
212   if (filelist[i].iskeypair)
213     fid = filelist[i].iskeypair;
214
215
216   /* Read the entire file.  fixme: This could be optimized by first
217      reading the header to figure out how long the certificate
218      actually is. */
219   err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
220   if (err)
221     {
222       log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
223       return err;
224     }
225
226   err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
227   if (err)
228     {
229       log_error ("error reading certificate from FID 0x%04X: %s\n",
230                  fid, gpg_strerror (err));
231       return err;
232     }
233   
234   if (!buflen || *buffer == 0xff)
235     {
236       log_info ("no certificate contained in FID 0x%04X\n", fid);
237       err = gpg_error (GPG_ERR_NOT_FOUND);
238       goto leave;
239     }
240
241   /* Now figure something out about the object. */
242   p = buffer;
243   n = buflen;
244   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
245                           &ndef, &objlen, &hdrlen);
246   if (err)
247     goto leave;
248   if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed )
249     ;
250   else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed )
251     rootca = 1;
252   else
253     return gpg_error (GPG_ERR_INV_OBJ);
254   totobjlen = objlen + hdrlen;
255   assert (totobjlen <= buflen);
256
257   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
258                           &ndef, &objlen, &hdrlen);
259   if (err)
260     goto leave;
261   
262   if (rootca)
263     ;
264   else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
265     {
266       const unsigned char *save_p;
267   
268       /* The certificate seems to be contained in a userCertificate
269          container.  Skip this and assume the following sequence is
270          the certificate. */
271       if (n < objlen)
272         {
273           err = gpg_error (GPG_ERR_INV_OBJ);
274           goto leave;
275         }
276       p += objlen;
277       n -= objlen;
278       save_p = p;
279       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
280                               &ndef, &objlen, &hdrlen);
281       if (err) 
282         goto leave;
283       if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) )
284         return gpg_error (GPG_ERR_INV_OBJ);
285       totobjlen = objlen + hdrlen;
286       assert (save_p + totobjlen <= buffer + buflen);
287       memmove (buffer, save_p, totobjlen);
288     }
289   
290   *cert = buffer;
291   buffer = NULL;
292   *certlen = totobjlen;
293
294  leave:
295   xfree (buffer);
296   return err;
297 }
298
299
300 /* Verify the PIN if required.  */
301 static gpg_error_t
302 verify_pin (app_t app,
303             gpg_error_t (*pincb)(void*, const char *, char **),
304             void *pincb_arg)
305 {
306   iso7816_pininfo_t pininfo;
307   int rc;
308
309   /* Note that force_chv1 is never set but we do it here anyway so
310      that other applications may reuse this function.  For example it
311      makes sense to set force_chv1 for German signature law cards.
312      NKS is very similar to the DINSIG draft standard. */
313   if ( app->did_chv1 && !app->force_chv1 ) 
314     return 0;  /* No need to verify it again.  */
315
316   memset (&pininfo, 0, sizeof pininfo);
317   pininfo.mode = 1;
318   pininfo.minlen = 6;
319   pininfo.maxlen = 16;
320
321   if (!opt.disable_keypad
322       && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
323     {
324       rc = pincb (pincb_arg,
325                   _("||Please enter your PIN at the reader's keypad"),
326                   NULL);
327       if (rc)
328         {
329           log_info (_("PIN callback returned error: %s\n"),
330                     gpg_strerror (rc));
331           return rc;
332         }
333  
334       /* Although it is possible to use a local PIN, we use the global
335          PIN for this application.  */
336       rc = iso7816_verify_kp (app->slot, 0, "", 0, &pininfo); 
337       /* Dismiss the prompt. */
338       pincb (pincb_arg, NULL, NULL);
339     }
340   else
341     {
342       char *pinvalue;
343
344       rc = pincb (pincb_arg, "PIN", &pinvalue); 
345       if (rc)
346         {
347           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
348           return rc;
349         }
350
351       /* The following limits are due to TCOS but also defined in the
352          NKS specs. */
353       if (strlen (pinvalue) < pininfo.minlen)
354         {
355           log_error ("PIN is too short; minimum length is %d\n",
356                      pininfo.minlen);
357           xfree (pinvalue);
358           return gpg_error (GPG_ERR_BAD_PIN);
359         }
360       else if (strlen (pinvalue) > pininfo.maxlen)
361         {
362           log_error ("PIN is too large; maximum length is %d\n",
363                      pininfo.maxlen);
364           xfree (pinvalue);
365           return gpg_error (GPG_ERR_BAD_PIN);
366         }
367
368       /* Although it is possible to use a local PIN, we use the global
369          PIN for this application.  */
370       rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
371       xfree (pinvalue);
372     }
373
374   if (rc)
375     {
376       if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
377         log_error (_("the NullPIN has not yet been changed\n"));
378       else
379         log_error ("verify PIN failed\n");
380       return rc;
381     }
382   app->did_chv1 = 1;
383
384   return 0;
385 }
386
387
388
389 /* Create the signature and return the allocated result in OUTDATA.
390    If a PIN is required the PINCB will be used to ask for the PIN;
391    that callback should return the PIN in an allocated buffer and
392    store that in the 3rd argument.  */
393 static gpg_error_t 
394 do_sign (app_t app, const char *keyidstr, int hashalgo,
395          gpg_error_t (*pincb)(void*, const char *, char **),
396          void *pincb_arg,
397          const void *indata, size_t indatalen,
398          unsigned char **outdata, size_t *outdatalen )
399 {
400   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
401     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
402       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
403   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
404     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
405       0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
406   int rc, i;
407   int fid;
408   unsigned char data[35];   /* Must be large enough for a SHA-1 digest
409                                + the largest OID _prefix above. */
410
411   if (!keyidstr || !*keyidstr)
412     return gpg_error (GPG_ERR_INV_VALUE);
413   if (indatalen != 20 && indatalen != 16 && indatalen != 35)
414     return gpg_error (GPG_ERR_INV_VALUE);
415
416   /* Check that the provided ID is valid.  This is not really needed
417      but we do it to enforce correct usage by the caller. */
418   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
419     return gpg_error (GPG_ERR_INV_ID);
420   keyidstr += 9;
421   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
422       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
423       || keyidstr[4])
424     return gpg_error (GPG_ERR_INV_ID);
425   fid = xtoi_4 (keyidstr);
426   for (i=0; filelist[i].fid; i++)
427     if (filelist[i].iskeypair && filelist[i].fid == fid)
428       break;
429   if (!filelist[i].fid)
430     return gpg_error (GPG_ERR_NOT_FOUND);
431   if (!filelist[i].issignkey)
432     return gpg_error (GPG_ERR_INV_ID);
433
434   /* Prepare the DER object from INDATA. */
435   if (indatalen == 35)
436     {
437       /* Alright, the caller was so kind to send us an already
438          prepared DER object.  Check that it is waht we want and that
439          it matches the hash algorithm. */
440       if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
441         ;
442       else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15))
443         ;
444       else 
445         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
446       memcpy (data, indata, indatalen);
447     }
448   else
449     {
450       if (hashalgo == GCRY_MD_SHA1)
451         memcpy (data, sha1_prefix, 15);
452       else if (hashalgo == GCRY_MD_RMD160)
453         memcpy (data, rmd160_prefix, 15);
454       else 
455         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
456       memcpy (data+15, indata, indatalen);
457     }
458
459   rc = verify_pin (app, pincb, pincb_arg);
460   if (!rc)
461     rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
462   return rc;
463 }
464
465
466
467
468 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
469    If a PIN is required the PINCB will be used to ask for the PIN; it
470    should return the PIN in an allocated buffer and put it into PIN.  */
471 static gpg_error_t 
472 do_decipher (app_t app, const char *keyidstr,
473              gpg_error_t (*pincb)(void*, const char *, char **),
474              void *pincb_arg,
475              const void *indata, size_t indatalen,
476              unsigned char **outdata, size_t *outdatalen )
477 {
478   static const unsigned char mse_parm[] = {
479     0x80, 1, 0x10, /* Select algorithm RSA. */
480     0x84, 1, 0x81  /* Select local secret key 1 for decryption. */
481   };
482   int rc, i;
483   int fid;
484
485   if (!keyidstr || !*keyidstr || !indatalen)
486     return gpg_error (GPG_ERR_INV_VALUE);
487
488   /* Check that the provided ID is valid.  This is not really needed
489      but we do it to to enforce correct usage by the caller. */
490   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
491     return gpg_error (GPG_ERR_INV_ID);
492   keyidstr += 9;
493   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
494       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
495       || keyidstr[4])
496     return gpg_error (GPG_ERR_INV_ID);
497   fid = xtoi_4 (keyidstr);
498   for (i=0; filelist[i].fid; i++)
499     if (filelist[i].iskeypair && filelist[i].fid == fid)
500       break;
501   if (!filelist[i].fid)
502     return gpg_error (GPG_ERR_NOT_FOUND);
503   if (!filelist[i].isenckey)
504     return gpg_error (GPG_ERR_INV_ID);
505
506   /* Do the TCOS specific MSE. */
507   rc = iso7816_manage_security_env (app->slot, 
508                                     0xC1, 0xB8,
509                                     mse_parm, sizeof mse_parm);
510   if (!rc)
511     rc = verify_pin (app, pincb, pincb_arg);
512   if (!rc)
513     rc = iso7816_decipher (app->slot, indata, indatalen, 0x81,
514                            outdata, outdatalen);
515   return rc;
516 }
517
518
519 /* Handle the PASSWD command.  CHVNOSTR is currently ignored; we
520    always use VHV0.  RESET_MODE is not yet implemented.  */
521 static gpg_error_t 
522 do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr, 
523                unsigned int flags,
524                gpg_error_t (*pincb)(void*, const char *, char **),
525                void *pincb_arg)
526 {
527   gpg_error_t err;
528   char *pinvalue;
529   const char *oldpin;
530   size_t oldpinlen;
531
532   (void)ctrl;
533   (void)chvnostr;
534
535   if ((flags & APP_CHANGE_FLAG_RESET))
536     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
537
538   if ((flags & APP_CHANGE_FLAG_NULLPIN))
539     {
540       /* With the nullpin flag, we do not verify the PIN - it would fail
541          if the Nullpin is still set.  */
542       oldpin = "\0\0\0\0\0";
543       oldpinlen = 6;
544     }
545   else
546     {
547       err = verify_pin (app, pincb, pincb_arg);
548       if (err)
549         return err;
550       oldpin = NULL;
551       oldpinlen = 0;
552     }
553
554   /* TRANSLATORS: Do not translate the "|*|" prefixes but
555      keep it at the start of the string.  We need this elsewhere
556      to get some infos on the string. */
557   err = pincb (pincb_arg, _("|N|New PIN"), &pinvalue); 
558   if (err)
559     {
560       log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
561       return err;
562     }
563
564   err = iso7816_change_reference_data (app->slot, 0x00, 
565                                        oldpin, oldpinlen,
566                                        pinvalue, strlen (pinvalue));
567   xfree (pinvalue);
568   return err;
569 }
570
571
572 /* Perform a simple verify operation.  KEYIDSTR should be NULL or empty.  */
573 static gpg_error_t 
574 do_check_pin (app_t app, const char *keyidstr,
575               gpg_error_t (*pincb)(void*, const char *, char **),
576               void *pincb_arg)
577 {
578   (void)keyidstr;
579   return verify_pin (app, pincb, pincb_arg);
580 }
581
582
583 /* Select the NKS 2.0 application.  */
584 gpg_error_t
585 app_select_nks (app_t app)
586 {
587   static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
588   int slot = app->slot;
589   int rc;
590   
591   rc = iso7816_select_application (slot, aid, sizeof aid, 0);
592   if (!rc)
593     {
594       app->apptype = "NKS";
595
596       app->fnc.learn_status = do_learn_status;
597       app->fnc.readcert = do_readcert;
598       app->fnc.getattr = NULL;
599       app->fnc.setattr = NULL;
600       app->fnc.genkey = NULL;
601       app->fnc.sign = do_sign;
602       app->fnc.auth = NULL;
603       app->fnc.decipher = do_decipher;
604       app->fnc.change_pin = do_change_pin;
605       app->fnc.check_pin = do_check_pin;
606    }
607
608   return rc;
609 }
610
611