Make gpgconf aware of --p12-charset.
[gnupg.git] / scd / app-nks.c
1 /* app-nks.c - The Telesec NKS 2.0 card application.
2  * Copyright (C) 2004, 2007 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   iso7816_pininfo_t pininfo;
310   int rc;
311
312   /* Note that force_chv1 is never set but we do it here anyway so
313      that other applications may reuse this function.  For example it
314      makes sense to set force_chv1 for German signature law cards.
315      NKS is very similar to the DINSIG draft standard. */
316   if ( app->did_chv1 && !app->force_chv1 ) 
317     return 0;  /* No need to verify it again.  */
318
319   memset (&pininfo, 0, sizeof pininfo);
320   pininfo.mode = 1;
321   pininfo.minlen = 6;
322   pininfo.maxlen = 16;
323
324   if (!opt.disable_keypad
325       && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
326     {
327       rc = pincb (pincb_arg,
328                   _("||Please enter your PIN at the reader's keypad"),
329                   NULL);
330       if (rc)
331         {
332           log_info (_("PIN callback returned error: %s\n"),
333                     gpg_strerror (rc));
334           return rc;
335         }
336  
337       /* Although it is possible to use a local PIN, we use the global
338          PIN for this application.  */
339       rc = iso7816_verify_kp (app->slot, 0, "", 0, &pininfo); 
340       /* Dismiss the prompt. */
341       pincb (pincb_arg, NULL, NULL);
342     }
343   else
344     {
345       char *pinvalue;
346
347       rc = pincb (pincb_arg, "PIN", &pinvalue); 
348       if (rc)
349         {
350           log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
351           return rc;
352         }
353
354       /* The following limits are due to TCOS but also defined in the
355          NKS specs. */
356       if (strlen (pinvalue) < pininfo.minlen)
357         {
358           log_error ("PIN is too short; minimum length is %d\n",
359                      pininfo.minlen);
360           xfree (pinvalue);
361           return gpg_error (GPG_ERR_BAD_PIN);
362         }
363       else if (strlen (pinvalue) > pininfo.maxlen)
364         {
365           log_error ("PIN is too large; maximum length is %d\n",
366                      pininfo.maxlen);
367           xfree (pinvalue);
368           return gpg_error (GPG_ERR_BAD_PIN);
369         }
370
371       /* Although it is possible to use a local PIN, we use the global
372          PIN for this application.  */
373       rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
374       xfree (pinvalue);
375     }
376
377   if (rc)
378     {
379       if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
380         log_error (_("the NullPIN has not yet been changed\n"));
381       else
382         log_error ("verify PIN failed\n");
383       return rc;
384     }
385   app->did_chv1 = 1;
386
387   return 0;
388 }
389
390
391
392 /* Create the signature and return the allocated result in OUTDATA.
393    If a PIN is required the PINCB will be used to ask for the PIN;
394    that callback should return the PIN in an allocated buffer and
395    store that in the 3rd argument.  */
396 static gpg_error_t 
397 do_sign (app_t app, const char *keyidstr, int hashalgo,
398          gpg_error_t (*pincb)(void*, const char *, char **),
399          void *pincb_arg,
400          const void *indata, size_t indatalen,
401          unsigned char **outdata, size_t *outdatalen )
402 {
403   static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
404     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
405       0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
406   static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
407     { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
408       0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
409   int rc, i;
410   int fid;
411   unsigned char data[35];   /* Must be large enough for a SHA-1 digest
412                                + the largest OID _prefix above. */
413
414   if (!keyidstr || !*keyidstr)
415     return gpg_error (GPG_ERR_INV_VALUE);
416   if (indatalen != 20 && indatalen != 16 && indatalen != 35)
417     return gpg_error (GPG_ERR_INV_VALUE);
418
419   /* Check that the provided ID is vaid.  This is not really needed
420      but we do it to enforce correct usage by the caller. */
421   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
422     return gpg_error (GPG_ERR_INV_ID);
423   keyidstr += 9;
424   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
425       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
426       || keyidstr[4])
427     return gpg_error (GPG_ERR_INV_ID);
428   fid = xtoi_4 (keyidstr);
429   for (i=0; filelist[i].fid; i++)
430     if (filelist[i].iskeypair && filelist[i].fid == fid)
431       break;
432   if (!filelist[i].fid)
433     return gpg_error (GPG_ERR_NOT_FOUND);
434   if (!filelist[i].issignkey)
435     return gpg_error (GPG_ERR_INV_ID);
436
437   /* Prepare the DER object from INDATA. */
438   if (indatalen == 35)
439     {
440       /* Alright, the caller was so kind to send us an already
441          prepared DER object.  Check that it is waht we want and that
442          it matches the hash algorithm. */
443       if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
444         ;
445       else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15))
446         ;
447       else 
448         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
449       memcpy (data, indata, indatalen);
450     }
451   else
452     {
453       if (hashalgo == GCRY_MD_SHA1)
454         memcpy (data, sha1_prefix, 15);
455       else if (hashalgo == GCRY_MD_RMD160)
456         memcpy (data, rmd160_prefix, 15);
457       else 
458         return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
459       memcpy (data+15, indata, indatalen);
460     }
461
462   rc = verify_pin (app, pincb, pincb_arg);
463   if (!rc)
464     rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
465   return rc;
466 }
467
468
469
470
471 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
472    If a PIN is required the PINCB will be used to ask for the PIN; it
473    should return the PIN in an allocated buffer and put it into PIN.  */
474 static gpg_error_t 
475 do_decipher (app_t app, const char *keyidstr,
476              gpg_error_t (*pincb)(void*, const char *, char **),
477              void *pincb_arg,
478              const void *indata, size_t indatalen,
479              unsigned char **outdata, size_t *outdatalen )
480 {
481   static const unsigned char mse_parm[] = {
482     0x80, 1, 0x10, /* Select algorithm RSA. */
483     0x84, 1, 0x81  /* Select local secret key 1 for decryption. */
484   };
485   int rc, i;
486   int fid;
487
488   if (!keyidstr || !*keyidstr || !indatalen)
489     return gpg_error (GPG_ERR_INV_VALUE);
490
491   /* Check that the provided ID is valid.  This is not really needed
492      but we do it to to enforce correct usage by the caller. */
493   if (strncmp (keyidstr, "NKS-DF01.", 9) ) 
494     return gpg_error (GPG_ERR_INV_ID);
495   keyidstr += 9;
496   if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
497       || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) 
498       || keyidstr[4])
499     return gpg_error (GPG_ERR_INV_ID);
500   fid = xtoi_4 (keyidstr);
501   for (i=0; filelist[i].fid; i++)
502     if (filelist[i].iskeypair && filelist[i].fid == fid)
503       break;
504   if (!filelist[i].fid)
505     return gpg_error (GPG_ERR_NOT_FOUND);
506   if (!filelist[i].isenckey)
507     return gpg_error (GPG_ERR_INV_ID);
508
509   /* Do the TCOS specific MSE. */
510   rc = iso7816_manage_security_env (app->slot, 
511                                     0xC1, 0xB8,
512                                     mse_parm, sizeof mse_parm);
513   if (!rc)
514     rc = verify_pin (app, pincb, pincb_arg);
515   if (!rc)
516     rc = iso7816_decipher (app->slot, indata, indatalen, 0x81,
517                            outdata, outdatalen);
518   return rc;
519 }
520
521
522
523 /* Select the NKS 2.0 application.  */
524 gpg_error_t
525 app_select_nks (app_t app)
526 {
527   static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
528   int slot = app->slot;
529   int rc;
530   
531   rc = iso7816_select_application (slot, aid, sizeof aid, 0);
532   if (!rc)
533     {
534       app->apptype = "NKS";
535
536       app->fnc.learn_status = do_learn_status;
537       app->fnc.readcert = do_readcert;
538       app->fnc.getattr = NULL;
539       app->fnc.setattr = NULL;
540       app->fnc.genkey = NULL;
541       app->fnc.sign = do_sign;
542       app->fnc.auth = NULL;
543       app->fnc.decipher = do_decipher;
544       app->fnc.change_pin = NULL;
545       app->fnc.check_pin = NULL;
546    }
547
548   return rc;
549 }
550
551