* configure.ac: Do not build gpg by default.
[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
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 int
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 int
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 int
303 verify_pin (app_t app,
304             int (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 euse 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 follwoing 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           log_error ("verify PIN failed\n");
344           xfree (pinvalue);
345           return rc;
346         }
347       app->did_chv1 = 1;
348       xfree (pinvalue);
349     }
350
351   return 0;
352 }
353
354
355
356 /* Create the signature and return the allocated result in OUTDATA.
357    If a PIN is required the PINCB will be used to ask for the PIN;
358    that callback should return the PIN in an allocated buffer and
359    store that in the 3rd argument.  */
360 static int 
361 do_sign (app_t app, const char *keyidstr, int hashalgo,
362          int (pincb)(void*, const char *, char **),
363            void *pincb_arg,
364            const void *indata, size_t indatalen,
365            unsigned char **outdata, size_t *outdatalen )
366 {
367   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
368     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
369       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
370   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
371     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
372       0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
373   int rc, i;
374   int fid;
375   unsigned char data[35];   /* Must be large enough for a SHA-1 digest
376                                + the largest OID _prefix above. */
377
378   if (!keyidstr || !*keyidstr)
379     return gpg_error (GPG_ERR_INV_VALUE);
380   if (indatalen != 20 && indatalen != 16 && indatalen != 35)
381     return gpg_error (GPG_ERR_INV_VALUE);
382
383   /* Check that the provided ID is vaid.  This is not really needed
384      but we do it to to enforce correct usage by the caller. */
385   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
386     return gpg_error (GPG_ERR_INV_ID);
387   keyidstr += 9;
388   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
389       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
390       || keyidstr[4])
391     return gpg_error (GPG_ERR_INV_ID);
392   fid = xtoi_4 (keyidstr);
393   for (i=0; filelist[i].fid; i++)
394     if (filelist[i].iskeypair && filelist[i].fid == fid)
395       break;
396   if (!filelist[i].fid)
397     return gpg_error (GPG_ERR_NOT_FOUND);
398   if (!filelist[i].issignkey)
399     return gpg_error (GPG_ERR_INV_ID);
400
401   /* Prepare the DER object from INDATA. */
402   if (indatalen == 35)
403     {
404       /* Alright, the caller was so kind to send us an already
405          prepared DER object.  Check that it is waht we want and that
406          it matches the hash algorithm. */
407       if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
408         ;
409       else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15))
410         ;
411       else 
412         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
413       memcpy (data, indata, indatalen);
414     }
415   else
416     {
417       if (hashalgo == GCRY_MD_SHA1)
418         memcpy (data, sha1_prefix, 15);
419       else if (hashalgo == GCRY_MD_RMD160)
420         memcpy (data, rmd160_prefix, 15);
421       else 
422         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
423       memcpy (data+15, indata, indatalen);
424     }
425
426   rc = verify_pin (app, pincb, pincb_arg);
427   if (!rc)
428     rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
429   return rc;
430 }
431
432
433
434
435 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
436    If a PIN is required the PINCB will be used to ask for the PIN; it
437    should return the PIN in an allocated buffer and put it into PIN.  */
438 static int 
439 do_decipher (app_t app, const char *keyidstr,
440              int (pincb)(void*, const char *, char **),
441              void *pincb_arg,
442              const void *indata, size_t indatalen,
443              unsigned char **outdata, size_t *outdatalen )
444 {
445   static const unsigned char mse_parm[] = {
446     0x80, 1, 0x10, /* Select algorithm RSA. */
447     0x84, 1, 0x81  /* Select locak secret key 1 for descryption. */
448   };
449   int rc, i;
450   int fid;
451
452   if (!keyidstr || !*keyidstr || !indatalen)
453     return gpg_error (GPG_ERR_INV_VALUE);
454
455   /* Check that the provided ID is vaid.  This is not really needed
456      but we do it to to enforce correct usage by the caller. */
457   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
458     return gpg_error (GPG_ERR_INV_ID);
459   keyidstr += 9;
460   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
461       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
462       || keyidstr[4])
463     return gpg_error (GPG_ERR_INV_ID);
464   fid = xtoi_4 (keyidstr);
465   for (i=0; filelist[i].fid; i++)
466     if (filelist[i].iskeypair && filelist[i].fid == fid)
467       break;
468   if (!filelist[i].fid)
469     return gpg_error (GPG_ERR_NOT_FOUND);
470   if (!filelist[i].isenckey)
471     return gpg_error (GPG_ERR_INV_ID);
472
473   /* Do the TCOS specific MSE. */
474   rc = iso7816_manage_security_env (app->slot, 
475                                     0xC1, 0xB8,
476                                     mse_parm, sizeof mse_parm);
477   if (!rc)
478     rc = verify_pin (app, pincb, pincb_arg);
479   if (!rc)
480     rc = iso7816_decipher (app->slot, indata, indatalen, 0x81,
481                            outdata, outdatalen);
482   return rc;
483 }
484
485
486
487 /* Select the NKS 2.0 application on the card in SLOT.  */
488 int
489 app_select_nks (APP app)
490 {
491   static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
492   int slot = app->slot;
493   int rc;
494   
495   rc = iso7816_select_application (slot, aid, sizeof aid);
496   if (!rc)
497     {
498       app->apptype = "NKS";
499
500       app->fnc.learn_status = do_learn_status;
501       app->fnc.readcert = do_readcert;
502       app->fnc.getattr = NULL;
503       app->fnc.setattr = NULL;
504       app->fnc.genkey = NULL;
505       app->fnc.sign = do_sign;
506       app->fnc.auth = NULL;
507       app->fnc.decipher = do_decipher;
508       app->fnc.change_pin = NULL;
509       app->fnc.check_pin = NULL;
510    }
511
512   return rc;
513 }
514
515