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