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