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