Preparing an interim release
[gnupg.git] / scd / app-nks.c
1 /* app-nks.c - The Telesec NKS 2.0 card application.
2  *      Copyright (C) 2004 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 2 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <time.h>
28
29 #include "scdaemon.h"
30 #include "i18n.h"
31 #include "iso7816.h"
32 #include "app-common.h"
33 #include "tlv.h"
34
35 static struct {
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 app, CTRL 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      becuase we sometime use the key directly or let the caller
211      retrieve the key from the certificate.  The valid point behind
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   /* Note that force_chv1 is never set but we do it here anyway so
308      that other applications may reuse this function.  For example it
309      makes sense to set force_chv1 for German signature law cards.
310      NKS is very similar to the DINSIG draft standard. */
311   if (!app->did_chv1 || app->force_chv1 ) 
312     {
313       char *pinvalue;
314       int rc;
315
316       rc = pincb (pincb_arg, "PIN", &pinvalue); 
317       if (rc)
318         {
319           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
320           return rc;
321         }
322
323       /* The following limits are due to TCOS but also defined in the
324          NKS specs. */
325       if (strlen (pinvalue) < 6)
326         {
327           log_error ("PIN is too short; minimum length is 6\n");
328           xfree (pinvalue);
329           return gpg_error (GPG_ERR_BAD_PIN);
330         }
331       else if (strlen (pinvalue) > 16)
332         {
333           log_error ("PIN is too large; maximum length is 16\n");
334           xfree (pinvalue);
335           return gpg_error (GPG_ERR_BAD_PIN);
336         }
337
338       /* Also it is possible to use a local PIN, we use the gloabl
339          PIN for this application.  */
340       rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
341       if (rc)
342         {
343           if ( gpg_error (rc) == GPG_ERR_USE_CONDITIONS )
344             log_error (_("the NullPIN has not yet been changed\n"));
345           else
346             log_error ("verify PIN failed\n");
347           xfree (pinvalue);
348           return rc;
349         }
350       app->did_chv1 = 1;
351       xfree (pinvalue);
352     }
353
354   return 0;
355 }
356
357
358
359 /* Create the signature and return the allocated result in OUTDATA.
360    If a PIN is required the PINCB will be used to ask for the PIN;
361    that callback should return the PIN in an allocated buffer and
362    store that in the 3rd argument.  */
363 static gpg_error_t 
364 do_sign (app_t app, const char *keyidstr, int hashalgo,
365          gpg_error_t (*pincb)(void*, const char *, char **),
366          void *pincb_arg,
367          const void *indata, size_t indatalen,
368          unsigned char **outdata, size_t *outdatalen )
369 {
370   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
371     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
372       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
373   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
374     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
375       0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
376   int rc, i;
377   int fid;
378   unsigned char data[35];   /* Must be large enough for a SHA-1 digest
379                                + the largest OID _prefix above. */
380
381   if (!keyidstr || !*keyidstr)
382     return gpg_error (GPG_ERR_INV_VALUE);
383   if (indatalen != 20 && indatalen != 16 && indatalen != 35)
384     return gpg_error (GPG_ERR_INV_VALUE);
385
386   /* Check that the provided ID is vaid.  This is not really needed
387      but we do it to to enforce correct usage by the caller. */
388   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
389     return gpg_error (GPG_ERR_INV_ID);
390   keyidstr += 9;
391   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
392       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
393       || keyidstr[4])
394     return gpg_error (GPG_ERR_INV_ID);
395   fid = xtoi_4 (keyidstr);
396   for (i=0; filelist[i].fid; i++)
397     if (filelist[i].iskeypair && filelist[i].fid == fid)
398       break;
399   if (!filelist[i].fid)
400     return gpg_error (GPG_ERR_NOT_FOUND);
401   if (!filelist[i].issignkey)
402     return gpg_error (GPG_ERR_INV_ID);
403
404   /* Prepare the DER object from INDATA. */
405   if (indatalen == 35)
406     {
407       /* Alright, the caller was so kind to send us an already
408          prepared DER object.  Check that it is waht we want and that
409          it matches the hash algorithm. */
410       if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
411         ;
412       else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15))
413         ;
414       else 
415         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
416       memcpy (data, indata, indatalen);
417     }
418   else
419     {
420       if (hashalgo == GCRY_MD_SHA1)
421         memcpy (data, sha1_prefix, 15);
422       else if (hashalgo == GCRY_MD_RMD160)
423         memcpy (data, rmd160_prefix, 15);
424       else 
425         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
426       memcpy (data+15, indata, indatalen);
427     }
428
429   rc = verify_pin (app, pincb, pincb_arg);
430   if (!rc)
431     rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
432   return rc;
433 }
434
435
436
437
438 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
439    If a PIN is required the PINCB will be used to ask for the PIN; it
440    should return the PIN in an allocated buffer and put it into PIN.  */
441 static gpg_error_t 
442 do_decipher (app_t app, const char *keyidstr,
443              gpg_error_t (*pincb)(void*, const char *, char **),
444              void *pincb_arg,
445              const void *indata, size_t indatalen,
446              unsigned char **outdata, size_t *outdatalen )
447 {
448   static const unsigned char mse_parm[] = {
449     0x80, 1, 0x10, /* Select algorithm RSA. */
450     0x84, 1, 0x81  /* Select local secret key 1 for decryption. */
451   };
452   int rc, i;
453   int fid;
454
455   if (!keyidstr || !*keyidstr || !indatalen)
456     return gpg_error (GPG_ERR_INV_VALUE);
457
458   /* Check that the provided ID is vaid.  This is not really needed
459      but we do it to to enforce correct usage by the caller. */
460   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
461     return gpg_error (GPG_ERR_INV_ID);
462   keyidstr += 9;
463   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
464       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
465       || keyidstr[4])
466     return gpg_error (GPG_ERR_INV_ID);
467   fid = xtoi_4 (keyidstr);
468   for (i=0; filelist[i].fid; i++)
469     if (filelist[i].iskeypair && filelist[i].fid == fid)
470       break;
471   if (!filelist[i].fid)
472     return gpg_error (GPG_ERR_NOT_FOUND);
473   if (!filelist[i].isenckey)
474     return gpg_error (GPG_ERR_INV_ID);
475
476   /* Do the TCOS specific MSE. */
477   rc = iso7816_manage_security_env (app->slot, 
478                                     0xC1, 0xB8,
479                                     mse_parm, sizeof mse_parm);
480   if (!rc)
481     rc = verify_pin (app, pincb, pincb_arg);
482   if (!rc)
483     rc = iso7816_decipher (app->slot, indata, indatalen, 0x81,
484                            outdata, outdatalen);
485   return rc;
486 }
487
488
489
490 /* Select the NKS 2.0 application on the card in SLOT.  */
491 gpg_error_t
492 app_select_nks (APP app)
493 {
494   static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
495   int slot = app->slot;
496   int rc;
497   
498   rc = iso7816_select_application (slot, aid, sizeof aid, 0);
499   if (!rc)
500     {
501       app->apptype = "NKS";
502
503       app->fnc.learn_status = do_learn_status;
504       app->fnc.readcert = do_readcert;
505       app->fnc.getattr = NULL;
506       app->fnc.setattr = NULL;
507       app->fnc.genkey = NULL;
508       app->fnc.sign = do_sign;
509       app->fnc.auth = NULL;
510       app->fnc.decipher = do_decipher;
511       app->fnc.change_pin = NULL;
512       app->fnc.check_pin = NULL;
513    }
514
515   return rc;
516 }
517
518