2008-02-09 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / scd / app-nks.c
1 /* app-nks.c - The Telesec NKS 2.0 card application.
2  * Copyright (C) 2004, 2007 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       for (i=0; i < 20; i++)
112         sprintf (r_gripstr+i*2, "%02X", grip[i]);
113     }
114   gcry_sexp_release (sexp);
115   return err;
116 }
117
118
119
120 static gpg_error_t
121 do_learn_status (app_t app, ctrl_t ctrl)
122 {
123   gpg_error_t err;
124   char ct_buf[100], id_buf[100];
125   int i;
126
127   /* Output information about all useful objects. */
128   for (i=0; filelist[i].fid; i++)
129     {
130       if (filelist[i].certtype)
131         {
132           size_t len;
133
134           len = app_help_read_length_of_cert (app->slot,
135                                               filelist[i].fid, NULL);
136           if (len)
137             {
138               /* FIXME: We should store the length in the application's
139                  context so that a following readcert does only need to
140                  read that many bytes. */
141               sprintf (ct_buf, "%d", filelist[i].certtype);
142               sprintf (id_buf, "NKS-DF01.%04X", filelist[i].fid);
143               send_status_info (ctrl, "CERTINFO",
144                                 ct_buf, strlen (ct_buf), 
145                                 id_buf, strlen (id_buf), 
146                                 NULL, (size_t)0);
147             }
148         }
149       else if (filelist[i].iskeypair)
150         {
151           char gripstr[40+1];
152
153           err = keygripstr_from_pk_file (app->slot, filelist[i].fid, gripstr);
154           if (err)
155             log_error ("can't get keygrip from FID 0x%04X: %s\n",
156                        filelist[i].fid, gpg_strerror (err));
157           else
158             {
159               sprintf (id_buf, "NKS-DF01.%04X", filelist[i].fid);
160               send_status_info (ctrl, "KEYPAIRINFO",
161                                 gripstr, 40, 
162                                 id_buf, strlen (id_buf), 
163                                 NULL, (size_t)0);
164             }
165         }
166     }
167
168   return 0;
169 }
170
171
172
173
174 /* Read the certificate with id CERTID (as returned by learn_status in
175    the CERTINFO status lines) and return it in the freshly allocated
176    buffer put into CERT and the length of the certificate put into
177    CERTLEN. */
178 static gpg_error_t
179 do_readcert (app_t app, const char *certid,
180              unsigned char **cert, size_t *certlen)
181 {
182   int i, fid;
183   gpg_error_t err;
184   unsigned char *buffer;
185   const unsigned char *p;
186   size_t buflen, n;
187   int class, tag, constructed, ndef;
188   size_t totobjlen, objlen, hdrlen;
189   int rootca = 0;
190
191   *cert = NULL;
192   *certlen = 0;
193   if (strncmp (certid, "NKS-DF01.", 9) ) 
194     return gpg_error (GPG_ERR_INV_ID);
195   certid += 9;
196   if (!hexdigitp (certid) || !hexdigitp (certid+1)
197       || !hexdigitp (certid+2) || !hexdigitp (certid+3) 
198       || certid[4])
199     return gpg_error (GPG_ERR_INV_ID);
200   fid = xtoi_4 (certid);
201   for (i=0; filelist[i].fid; i++)
202     if ((filelist[i].certtype || filelist[i].iskeypair)
203         && filelist[i].fid == fid)
204       break;
205   if (!filelist[i].fid)
206     return gpg_error (GPG_ERR_NOT_FOUND);
207
208   /* If the requested objects is a plain public key, redirect it to
209      the corresponding certificate.  The whole system is a bit messy
210      because we sometime use the key directly or let the caller
211      retrieve the key from the certificate.  The rationale for
212      that is to support not-yet stored certificates. */
213   if (filelist[i].iskeypair)
214     fid = filelist[i].iskeypair;
215
216
217   /* Read the entire file.  fixme: This could be optimized by first
218      reading the header to figure out how long the certificate
219      actually is. */
220   err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
221   if (err)
222     {
223       log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
224       return err;
225     }
226
227   err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
228   if (err)
229     {
230       log_error ("error reading certificate from FID 0x%04X: %s\n",
231                  fid, gpg_strerror (err));
232       return err;
233     }
234   
235   if (!buflen || *buffer == 0xff)
236     {
237       log_info ("no certificate contained in FID 0x%04X\n", fid);
238       err = gpg_error (GPG_ERR_NOT_FOUND);
239       goto leave;
240     }
241
242   /* Now figure something out about the object. */
243   p = buffer;
244   n = buflen;
245   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
246                           &ndef, &objlen, &hdrlen);
247   if (err)
248     goto leave;
249   if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed )
250     ;
251   else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed )
252     rootca = 1;
253   else
254     return gpg_error (GPG_ERR_INV_OBJ);
255   totobjlen = objlen + hdrlen;
256   assert (totobjlen <= buflen);
257
258   err = parse_ber_header (&p, &n, &class, &tag, &constructed,
259                           &ndef, &objlen, &hdrlen);
260   if (err)
261     goto leave;
262   
263   if (rootca)
264     ;
265   else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
266     {
267       const unsigned char *save_p;
268   
269       /* The certificate seems to be contained in a userCertificate
270          container.  Skip this and assume the following sequence is
271          the certificate. */
272       if (n < objlen)
273         {
274           err = gpg_error (GPG_ERR_INV_OBJ);
275           goto leave;
276         }
277       p += objlen;
278       n -= objlen;
279       save_p = p;
280       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
281                               &ndef, &objlen, &hdrlen);
282       if (err) 
283         goto leave;
284       if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) )
285         return gpg_error (GPG_ERR_INV_OBJ);
286       totobjlen = objlen + hdrlen;
287       assert (save_p + totobjlen <= buffer + buflen);
288       memmove (buffer, save_p, totobjlen);
289     }
290   
291   *cert = buffer;
292   buffer = NULL;
293   *certlen = totobjlen;
294
295  leave:
296   xfree (buffer);
297   return err;
298 }
299
300
301 /* Verify the PIN if required.  */
302 static gpg_error_t
303 verify_pin (app_t app,
304             gpg_error_t (*pincb)(void*, const char *, char **),
305             void *pincb_arg)
306 {
307   iso7816_pininfo_t pininfo;
308   int rc;
309
310   /* Note that force_chv1 is never set but we do it here anyway so
311      that other applications may reuse this function.  For example it
312      makes sense to set force_chv1 for German signature law cards.
313      NKS is very similar to the DINSIG draft standard. */
314   if ( app->did_chv1 && !app->force_chv1 ) 
315     return 0;  /* No need to verify it again.  */
316
317   memset (&pininfo, 0, sizeof pininfo);
318   pininfo.mode = 1;
319   pininfo.minlen = 6;
320   pininfo.maxlen = 16;
321
322   if (!opt.disable_keypad
323       && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
324     {
325       rc = pincb (pincb_arg,
326                   _("||Please enter your PIN at the reader's keypad"),
327                   NULL);
328       if (rc)
329         {
330           log_info (_("PIN callback returned error: %s\n"),
331                     gpg_strerror (rc));
332           return rc;
333         }
334  
335       /* Although it is possible to use a local PIN, we use the global
336          PIN for this application.  */
337       rc = iso7816_verify_kp (app->slot, 0, "", 0, &pininfo); 
338       /* Dismiss the prompt. */
339       pincb (pincb_arg, NULL, NULL);
340     }
341   else
342     {
343       char *pinvalue;
344
345       rc = pincb (pincb_arg, "PIN", &pinvalue); 
346       if (rc)
347         {
348           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
349           return rc;
350         }
351
352       /* The following limits are due to TCOS but also defined in the
353          NKS specs. */
354       if (strlen (pinvalue) < pininfo.minlen)
355         {
356           log_error ("PIN is too short; minimum length is %d\n",
357                      pininfo.minlen);
358           xfree (pinvalue);
359           return gpg_error (GPG_ERR_BAD_PIN);
360         }
361       else if (strlen (pinvalue) > pininfo.maxlen)
362         {
363           log_error ("PIN is too large; maximum length is %d\n",
364                      pininfo.maxlen);
365           xfree (pinvalue);
366           return gpg_error (GPG_ERR_BAD_PIN);
367         }
368
369       /* Although it is possible to use a local PIN, we use the global
370          PIN for this application.  */
371       rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
372       xfree (pinvalue);
373     }
374
375   if (rc)
376     {
377       if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
378         log_error (_("the NullPIN has not yet been changed\n"));
379       else
380         log_error ("verify PIN failed\n");
381       return rc;
382     }
383   app->did_chv1 = 1;
384
385   return 0;
386 }
387
388
389
390 /* Create the signature and return the allocated result in OUTDATA.
391    If a PIN is required the PINCB will be used to ask for the PIN;
392    that callback should return the PIN in an allocated buffer and
393    store that in the 3rd argument.  */
394 static gpg_error_t 
395 do_sign (app_t app, const char *keyidstr, int hashalgo,
396          gpg_error_t (*pincb)(void*, const char *, char **),
397          void *pincb_arg,
398          const void *indata, size_t indatalen,
399          unsigned char **outdata, size_t *outdatalen )
400 {
401   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
402     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
403       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
404   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
405     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
406       0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
407   int rc, i;
408   int fid;
409   unsigned char data[35];   /* Must be large enough for a SHA-1 digest
410                                + the largest OID _prefix above. */
411
412   if (!keyidstr || !*keyidstr)
413     return gpg_error (GPG_ERR_INV_VALUE);
414   if (indatalen != 20 && indatalen != 16 && indatalen != 35)
415     return gpg_error (GPG_ERR_INV_VALUE);
416
417   /* Check that the provided ID is vaid.  This is not really needed
418      but we do it to enforce correct usage by the caller. */
419   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
420     return gpg_error (GPG_ERR_INV_ID);
421   keyidstr += 9;
422   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
423       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
424       || keyidstr[4])
425     return gpg_error (GPG_ERR_INV_ID);
426   fid = xtoi_4 (keyidstr);
427   for (i=0; filelist[i].fid; i++)
428     if (filelist[i].iskeypair && filelist[i].fid == fid)
429       break;
430   if (!filelist[i].fid)
431     return gpg_error (GPG_ERR_NOT_FOUND);
432   if (!filelist[i].issignkey)
433     return gpg_error (GPG_ERR_INV_ID);
434
435   /* Prepare the DER object from INDATA. */
436   if (indatalen == 35)
437     {
438       /* Alright, the caller was so kind to send us an already
439          prepared DER object.  Check that it is waht we want and that
440          it matches the hash algorithm. */
441       if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
442         ;
443       else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15))
444         ;
445       else 
446         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
447       memcpy (data, indata, indatalen);
448     }
449   else
450     {
451       if (hashalgo == GCRY_MD_SHA1)
452         memcpy (data, sha1_prefix, 15);
453       else if (hashalgo == GCRY_MD_RMD160)
454         memcpy (data, rmd160_prefix, 15);
455       else 
456         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
457       memcpy (data+15, indata, indatalen);
458     }
459
460   rc = verify_pin (app, pincb, pincb_arg);
461   if (!rc)
462     rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
463   return rc;
464 }
465
466
467
468
469 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
470    If a PIN is required the PINCB will be used to ask for the PIN; it
471    should return the PIN in an allocated buffer and put it into PIN.  */
472 static gpg_error_t 
473 do_decipher (app_t app, const char *keyidstr,
474              gpg_error_t (*pincb)(void*, const char *, char **),
475              void *pincb_arg,
476              const void *indata, size_t indatalen,
477              unsigned char **outdata, size_t *outdatalen )
478 {
479   static const unsigned char mse_parm[] = {
480     0x80, 1, 0x10, /* Select algorithm RSA. */
481     0x84, 1, 0x81  /* Select local secret key 1 for decryption. */
482   };
483   int rc, i;
484   int fid;
485
486   if (!keyidstr || !*keyidstr || !indatalen)
487     return gpg_error (GPG_ERR_INV_VALUE);
488
489   /* Check that the provided ID is valid.  This is not really needed
490      but we do it to to enforce correct usage by the caller. */
491   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
492     return gpg_error (GPG_ERR_INV_ID);
493   keyidstr += 9;
494   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
495       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
496       || keyidstr[4])
497     return gpg_error (GPG_ERR_INV_ID);
498   fid = xtoi_4 (keyidstr);
499   for (i=0; filelist[i].fid; i++)
500     if (filelist[i].iskeypair && filelist[i].fid == fid)
501       break;
502   if (!filelist[i].fid)
503     return gpg_error (GPG_ERR_NOT_FOUND);
504   if (!filelist[i].isenckey)
505     return gpg_error (GPG_ERR_INV_ID);
506
507   /* Do the TCOS specific MSE. */
508   rc = iso7816_manage_security_env (app->slot, 
509                                     0xC1, 0xB8,
510                                     mse_parm, sizeof mse_parm);
511   if (!rc)
512     rc = verify_pin (app, pincb, pincb_arg);
513   if (!rc)
514     rc = iso7816_decipher (app->slot, indata, indatalen, 0x81,
515                            outdata, outdatalen);
516   return rc;
517 }
518
519
520
521 /* Select the NKS 2.0 application.  */
522 gpg_error_t
523 app_select_nks (app_t app)
524 {
525   static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
526   int slot = app->slot;
527   int rc;
528   
529   rc = iso7816_select_application (slot, aid, sizeof aid, 0);
530   if (!rc)
531     {
532       app->apptype = "NKS";
533
534       app->fnc.learn_status = do_learn_status;
535       app->fnc.readcert = do_readcert;
536       app->fnc.getattr = NULL;
537       app->fnc.setattr = NULL;
538       app->fnc.genkey = NULL;
539       app->fnc.sign = do_sign;
540       app->fnc.auth = NULL;
541       app->fnc.decipher = do_decipher;
542       app->fnc.change_pin = NULL;
543       app->fnc.check_pin = NULL;
544    }
545
546   return rc;
547 }
548
549