Line data Source code
1 : /* app-dinsig.c - The DINSIG (DIN V 66291-1) card application.
2 : * Copyright (C) 2002, 2004, 2005, 2007, 2008 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 3 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, see <https://www.gnu.org/licenses/>.
18 : */
19 :
20 :
21 : /* The German signature law and its bylaw (SigG and SigV) is currently
22 : used with an interface specification described in DIN V 66291-1.
23 : The AID to be used is: 'D27600006601'.
24 :
25 : The file IDs for certificates utilize the generic format:
26 : Cxyz
27 : C being the hex digit 'C' (12).
28 : x being the service indicator:
29 : '0' := SigG conform digital signature.
30 : '1' := entity authentication.
31 : '2' := key encipherment.
32 : '3' := data encipherment.
33 : '4' := key agreement.
34 : other values are reserved for future use.
35 : y being the security environment number using '0' for cards
36 : not supporting a SE number.
37 : z being the certificate type:
38 : '0' := C.CH (base certificate of card holder) or C.ICC.
39 : '1' .. '7' := C.CH (business or professional certificate
40 : of card holder.
41 : '8' .. 'D' := C.CA (certificate of a CA issue by the Root-CA).
42 : 'E' := C.RCA (self certified certificate of the Root-CA).
43 : 'F' := reserved.
44 :
45 : The file IDs used by default are:
46 : '1F00' EF.SSD (security service descriptor). [o,o]
47 : '2F02' EF.GDO (global data objects) [m,m]
48 : 'A000' EF.PROT (signature log). Cyclic file with 20 records of 53 byte.
49 : Read and update after user authentication. [o,o]
50 : 'B000' EF.PK.RCA.DS (public keys of Root-CA). Size is 512b or size
51 : of keys. [m (unless a 'C00E' is present),m]
52 : 'B001' EF.PK.CA.DS (public keys of CAs). Size is 512b or size
53 : of keys. [o,o]
54 : 'C00n' EF.C.CH.DS (digital signature certificate of card holder)
55 : with n := 0 .. 7. Size is 2k or size of cert. Read and
56 : update allowed after user authentication. [m,m]
57 : 'C00m' EF.C.CA.DS (digital signature certificate of CA)
58 : with m := 8 .. E. Size is 1k or size of cert. Read always
59 : allowed, update after user authentication. [o,o]
60 : 'C100' EF.C.ICC.AUT (AUT certificate of ICC) [o,m]
61 : 'C108' EF.C.CA.AUT (AUT certificate of CA) [o,m]
62 : 'D000' EF.DM (display message) [-,m]
63 :
64 : The letters in brackets indicate optional or mandatory files: The
65 : first for card terminals under full control and the second for
66 : "business" card terminals.
67 : */
68 :
69 :
70 :
71 :
72 : #include <config.h>
73 : #include <errno.h>
74 : #include <stdio.h>
75 : #include <stdlib.h>
76 : #include <string.h>
77 : #include <assert.h>
78 : #include <time.h>
79 :
80 : #include "scdaemon.h"
81 :
82 : #include "i18n.h"
83 : #include "iso7816.h"
84 : #include "app-common.h"
85 : #include "tlv.h"
86 :
87 :
88 : static gpg_error_t
89 0 : do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
90 : {
91 : gpg_error_t err;
92 : char ct_buf[100], id_buf[100];
93 : char hexkeygrip[41];
94 : size_t len, certoff;
95 : unsigned char *der;
96 : size_t derlen;
97 : ksba_cert_t cert;
98 : int fid;
99 :
100 : (void)flags;
101 :
102 : /* Return the certificate of the card holder. */
103 0 : fid = 0xC000;
104 0 : len = app_help_read_length_of_cert (app->slot, fid, &certoff);
105 0 : if (!len)
106 0 : return 0; /* Card has not been personalized. */
107 :
108 0 : sprintf (ct_buf, "%d", 101);
109 0 : sprintf (id_buf, "DINSIG.%04X", fid);
110 0 : send_status_info (ctrl, "CERTINFO",
111 : ct_buf, strlen (ct_buf),
112 : id_buf, strlen (id_buf),
113 : NULL, (size_t)0);
114 :
115 : /* Now we need to read the certificate, so that we can get the
116 : public key out of it. */
117 0 : err = iso7816_read_binary (app->slot, certoff, len-certoff, &der, &derlen);
118 0 : if (err)
119 : {
120 0 : log_info ("error reading entire certificate from FID 0x%04X: %s\n",
121 : fid, gpg_strerror (err));
122 0 : return 0;
123 : }
124 :
125 0 : err = ksba_cert_new (&cert);
126 0 : if (err)
127 : {
128 0 : xfree (der);
129 0 : return err;
130 : }
131 0 : err = ksba_cert_init_from_mem (cert, der, derlen);
132 0 : xfree (der); der = NULL;
133 0 : if (err)
134 : {
135 0 : log_error ("failed to parse the certificate at FID 0x%04X: %s\n",
136 : fid, gpg_strerror (err));
137 0 : ksba_cert_release (cert);
138 0 : return err;
139 : }
140 0 : err = app_help_get_keygrip_string (cert, hexkeygrip);
141 0 : if (err)
142 : {
143 0 : log_error ("failed to calculate the keygrip for FID 0x%04X\n", fid);
144 0 : ksba_cert_release (cert);
145 0 : return gpg_error (GPG_ERR_CARD);
146 : }
147 0 : ksba_cert_release (cert);
148 :
149 0 : sprintf (id_buf, "DINSIG.%04X", fid);
150 0 : send_status_info (ctrl, "KEYPAIRINFO",
151 : hexkeygrip, 40,
152 : id_buf, strlen (id_buf),
153 : NULL, (size_t)0);
154 0 : return 0;
155 : }
156 :
157 :
158 :
159 :
160 : /* Read the certificate with id CERTID (as returned by learn_status in
161 : the CERTINFO status lines) and return it in the freshly allocated
162 : buffer put into CERT and the length of the certificate put into
163 : CERTLEN.
164 :
165 : FIXME: This needs some cleanups and caching with do_learn_status.
166 : */
167 : static gpg_error_t
168 0 : do_readcert (app_t app, const char *certid,
169 : unsigned char **cert, size_t *certlen)
170 : {
171 : int fid;
172 : gpg_error_t err;
173 : unsigned char *buffer;
174 : const unsigned char *p;
175 : size_t buflen, n;
176 : int class, tag, constructed, ndef;
177 : size_t totobjlen, objlen, hdrlen;
178 0 : int rootca = 0;
179 :
180 0 : *cert = NULL;
181 0 : *certlen = 0;
182 0 : if (strncmp (certid, "DINSIG.", 7) )
183 0 : return gpg_error (GPG_ERR_INV_ID);
184 0 : certid += 7;
185 0 : if (!hexdigitp (certid) || !hexdigitp (certid+1)
186 0 : || !hexdigitp (certid+2) || !hexdigitp (certid+3)
187 0 : || certid[4])
188 0 : return gpg_error (GPG_ERR_INV_ID);
189 0 : fid = xtoi_4 (certid);
190 0 : if (fid != 0xC000 )
191 0 : return gpg_error (GPG_ERR_NOT_FOUND);
192 :
193 : /* Read the entire file. fixme: This could be optimized by first
194 : reading the header to figure out how long the certificate
195 : actually is. */
196 0 : err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
197 0 : if (err)
198 : {
199 0 : log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
200 0 : return err;
201 : }
202 :
203 0 : err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
204 0 : if (err)
205 : {
206 0 : log_error ("error reading certificate from FID 0x%04X: %s\n",
207 : fid, gpg_strerror (err));
208 0 : return err;
209 : }
210 :
211 0 : if (!buflen || *buffer == 0xff)
212 : {
213 0 : log_info ("no certificate contained in FID 0x%04X\n", fid);
214 0 : err = gpg_error (GPG_ERR_NOT_FOUND);
215 0 : goto leave;
216 : }
217 :
218 : /* Now figure something out about the object. */
219 0 : p = buffer;
220 0 : n = buflen;
221 0 : err = parse_ber_header (&p, &n, &class, &tag, &constructed,
222 : &ndef, &objlen, &hdrlen);
223 0 : if (err)
224 0 : goto leave;
225 0 : if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed )
226 : ;
227 0 : else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed )
228 0 : rootca = 1;
229 : else
230 0 : return gpg_error (GPG_ERR_INV_OBJ);
231 0 : totobjlen = objlen + hdrlen;
232 0 : assert (totobjlen <= buflen);
233 :
234 0 : err = parse_ber_header (&p, &n, &class, &tag, &constructed,
235 : &ndef, &objlen, &hdrlen);
236 0 : if (err)
237 0 : goto leave;
238 :
239 0 : if (rootca)
240 : ;
241 0 : else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
242 : {
243 : const unsigned char *save_p;
244 :
245 : /* The certificate seems to be contained in a userCertificate
246 : container. Skip this and assume the following sequence is
247 : the certificate. */
248 0 : if (n < objlen)
249 : {
250 0 : err = gpg_error (GPG_ERR_INV_OBJ);
251 0 : goto leave;
252 : }
253 0 : p += objlen;
254 0 : n -= objlen;
255 0 : save_p = p;
256 0 : err = parse_ber_header (&p, &n, &class, &tag, &constructed,
257 : &ndef, &objlen, &hdrlen);
258 0 : if (err)
259 0 : goto leave;
260 0 : if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) )
261 0 : return gpg_error (GPG_ERR_INV_OBJ);
262 0 : totobjlen = objlen + hdrlen;
263 0 : assert (save_p + totobjlen <= buffer + buflen);
264 0 : memmove (buffer, save_p, totobjlen);
265 : }
266 :
267 0 : *cert = buffer;
268 0 : buffer = NULL;
269 0 : *certlen = totobjlen;
270 :
271 : leave:
272 0 : xfree (buffer);
273 0 : return err;
274 : }
275 :
276 :
277 : /* Verify the PIN if required. */
278 : static gpg_error_t
279 0 : verify_pin (app_t app,
280 : gpg_error_t (*pincb)(void*, const char *, char **),
281 : void *pincb_arg)
282 : {
283 : const char *s;
284 : int rc;
285 : pininfo_t pininfo;
286 :
287 0 : if ( app->did_chv1 && !app->force_chv1 )
288 0 : return 0; /* No need to verify it again. */
289 :
290 0 : memset (&pininfo, 0, sizeof pininfo);
291 0 : pininfo.fixedlen = -1;
292 0 : pininfo.minlen = 6;
293 0 : pininfo.maxlen = 8;
294 :
295 0 : if (!opt.disable_pinpad
296 0 : && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
297 : {
298 0 : rc = pincb (pincb_arg,
299 0 : _("||Please enter your PIN at the reader's pinpad"),
300 : NULL);
301 0 : if (rc)
302 : {
303 0 : log_info (_("PIN callback returned error: %s\n"),
304 : gpg_strerror (rc));
305 0 : return rc;
306 : }
307 0 : rc = iso7816_verify_kp (app->slot, 0x81, &pininfo);
308 : /* Dismiss the prompt. */
309 0 : pincb (pincb_arg, NULL, NULL);
310 : }
311 : else /* No Pinpad. */
312 : {
313 : char *pinvalue;
314 :
315 0 : rc = pincb (pincb_arg, "PIN", &pinvalue);
316 0 : if (rc)
317 : {
318 0 : log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
319 0 : return rc;
320 : }
321 :
322 : /* We require the PIN to be at least 6 and at max 8 bytes.
323 : According to the specs, this should all be ASCII. */
324 0 : for (s=pinvalue; digitp (s); s++)
325 : ;
326 0 : if (*s)
327 : {
328 0 : log_error ("Non-numeric digits found in PIN\n");
329 0 : xfree (pinvalue);
330 0 : return gpg_error (GPG_ERR_BAD_PIN);
331 : }
332 :
333 0 : if (strlen (pinvalue) < pininfo.minlen)
334 : {
335 0 : log_error ("PIN is too short; minimum length is %d\n",
336 : pininfo.minlen);
337 0 : xfree (pinvalue);
338 0 : return gpg_error (GPG_ERR_BAD_PIN);
339 : }
340 0 : else if (strlen (pinvalue) > pininfo.maxlen)
341 : {
342 0 : log_error ("PIN is too large; maximum length is %d\n",
343 : pininfo.maxlen);
344 0 : xfree (pinvalue);
345 0 : return gpg_error (GPG_ERR_BAD_PIN);
346 : }
347 :
348 0 : rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
349 0 : if (gpg_err_code (rc) == GPG_ERR_INV_VALUE)
350 : {
351 : /* We assume that ISO 9564-1 encoding is used and we failed
352 : because the first nibble we passed was 3 and not 2. DIN
353 : says something about looking up such an encoding in the
354 : SSD but I was not able to find any tag relevant to
355 : this. */
356 : char paddedpin[8];
357 : int i, ndigits;
358 :
359 0 : for (ndigits=0, s=pinvalue; *s; ndigits++, s++)
360 : ;
361 0 : i = 0;
362 0 : paddedpin[i++] = 0x20 | (ndigits & 0x0f);
363 0 : for (s=pinvalue; i < sizeof paddedpin && *s && s[1]; s = s+2 )
364 0 : paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f));
365 0 : if (i < sizeof paddedpin && *s)
366 0 : paddedpin[i++] = (((*s - '0') << 4) | 0x0f);
367 0 : while (i < sizeof paddedpin)
368 0 : paddedpin[i++] = 0xff;
369 0 : rc = iso7816_verify (app->slot, 0x81, paddedpin, sizeof paddedpin);
370 : }
371 0 : xfree (pinvalue);
372 : }
373 :
374 0 : if (rc)
375 : {
376 0 : log_error ("verify PIN failed\n");
377 0 : return rc;
378 : }
379 0 : app->did_chv1 = 1;
380 0 : return 0;
381 : }
382 :
383 :
384 :
385 : /* Create the signature and return the allocated result in OUTDATA.
386 : If a PIN is required the PINCB will be used to ask for the PIN;
387 : that callback should return the PIN in an allocated buffer and
388 : store that in the 3rd argument. */
389 : static gpg_error_t
390 0 : do_sign (app_t app, const char *keyidstr, int hashalgo,
391 : gpg_error_t (*pincb)(void*, const char *, char **),
392 : void *pincb_arg,
393 : const void *indata, size_t indatalen,
394 : unsigned char **outdata, size_t *outdatalen )
395 : {
396 : static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
397 : { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
398 : 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
399 : static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
400 : { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
401 : 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
402 : static unsigned char sha256_prefix[19] = /* OID is 2.16.840.1.101.3.4.2.1 */
403 : { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
404 : 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
405 : 0x00, 0x04, 0x20 };
406 : int rc;
407 : int fid;
408 : unsigned char data[19+32]; /* Must be large enough for a SHA-256 digest
409 : + the largest OID _prefix above. */
410 : int datalen;
411 :
412 0 : if (!keyidstr || !*keyidstr)
413 0 : return gpg_error (GPG_ERR_INV_VALUE);
414 0 : if (indatalen != 20 && indatalen != 16 && indatalen != 32
415 0 : && indatalen != (15+20) && indatalen != (19+32))
416 0 : return gpg_error (GPG_ERR_INV_VALUE);
417 :
418 : /* Check that the provided ID is vaid. This is not really needed
419 : but we do it to to enforce correct usage by the caller. */
420 0 : if (strncmp (keyidstr, "DINSIG.", 7) )
421 0 : return gpg_error (GPG_ERR_INV_ID);
422 0 : keyidstr += 7;
423 0 : if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
424 0 : || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
425 0 : || keyidstr[4])
426 0 : return gpg_error (GPG_ERR_INV_ID);
427 0 : fid = xtoi_4 (keyidstr);
428 0 : if (fid != 0xC000)
429 0 : return gpg_error (GPG_ERR_NOT_FOUND);
430 :
431 : /* Prepare the DER object from INDATA. */
432 0 : datalen = 35;
433 0 : if (indatalen == 15+20)
434 : {
435 : /* Alright, the caller was so kind to send us an already
436 : prepared DER object. Check that it is what we want and that
437 : it matches the hash algorithm. */
438 0 : if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
439 : ;
440 0 : else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15))
441 : ;
442 : else
443 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
444 0 : memcpy (data, indata, indatalen);
445 : }
446 0 : else if (indatalen == 19+32)
447 : {
448 : /* Alright, the caller was so kind to send us an already
449 : prepared DER object. Check that it is what we want and that
450 : it matches the hash algorithm. */
451 0 : datalen = indatalen;
452 0 : if (hashalgo == GCRY_MD_SHA256 && !memcmp (indata, sha256_prefix, 19))
453 : ;
454 0 : else if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha256_prefix, 19))
455 : {
456 : /* Fixme: This is a kludge. A better solution is not to use
457 : SHA1 as default but use an autodetection. However this
458 : needs changes in all app-*.c */
459 0 : hashalgo = GCRY_MD_SHA256;
460 0 : datalen = indatalen;
461 : }
462 : else
463 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
464 0 : memcpy (data, indata, indatalen);
465 : }
466 : else
467 : {
468 0 : int len = 15;
469 0 : if (hashalgo == GCRY_MD_SHA1)
470 0 : memcpy (data, sha1_prefix, len);
471 0 : else if (hashalgo == GCRY_MD_RMD160)
472 0 : memcpy (data, rmd160_prefix, len);
473 0 : else if (hashalgo == GCRY_MD_SHA256)
474 : {
475 0 : len = 19;
476 0 : datalen = len + indatalen;
477 0 : memcpy (data, sha256_prefix, len);
478 : }
479 : else
480 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
481 0 : memcpy (data+len, indata, indatalen);
482 : }
483 :
484 0 : rc = verify_pin (app, pincb, pincb_arg);
485 0 : if (!rc)
486 0 : rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0,
487 : outdata, outdatalen);
488 0 : return rc;
489 : }
490 :
491 :
492 : #if 0
493 : #warning test function - works but may brick your card
494 : /* Handle the PASSWD command. CHVNOSTR is currently ignored; we
495 : always use VHV0. RESET_MODE is not yet implemented. */
496 : static gpg_error_t
497 : do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
498 : unsigned int flags,
499 : gpg_error_t (*pincb)(void*, const char *, char **),
500 : void *pincb_arg)
501 : {
502 : gpg_error_t err;
503 : char *pinvalue;
504 : const char *oldpin;
505 : size_t oldpinlen;
506 :
507 : if ((flags & APP_CHANGE_FLAG_RESET))
508 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
509 :
510 : if ((flags & APP_CHANGE_FLAG_NULLPIN))
511 : {
512 : /* With the nullpin flag, we do not verify the PIN - it would fail
513 : if the Nullpin is still set. */
514 : oldpin = "\0\0\0\0\0";
515 : oldpinlen = 6;
516 : }
517 : else
518 : {
519 : err = verify_pin (app, pincb, pincb_arg);
520 : if (err)
521 : return err;
522 : oldpin = NULL;
523 : oldpinlen = 0;
524 : }
525 :
526 : /* TRANSLATORS: Do not translate the "|*|" prefixes but
527 : keep it at the start of the string. We need this elsewhere
528 : to get some infos on the string. */
529 : err = pincb (pincb_arg, _("|N|Initial New PIN"), &pinvalue);
530 : if (err)
531 : {
532 : log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
533 : return err;
534 : }
535 :
536 : err = iso7816_change_reference_data (app->slot, 0x81,
537 : oldpin, oldpinlen,
538 : pinvalue, strlen (pinvalue));
539 : xfree (pinvalue);
540 : return err;
541 : }
542 : #endif /*0*/
543 :
544 :
545 : /* Select the DINSIG application on the card in SLOT. This function
546 : must be used before any other DINSIG application functions. */
547 : gpg_error_t
548 0 : app_select_dinsig (app_t app)
549 : {
550 : static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 };
551 0 : int slot = app->slot;
552 : int rc;
553 :
554 0 : rc = iso7816_select_application (slot, aid, sizeof aid, 0);
555 0 : if (!rc)
556 : {
557 0 : app->apptype = "DINSIG";
558 :
559 0 : app->fnc.learn_status = do_learn_status;
560 0 : app->fnc.readcert = do_readcert;
561 0 : app->fnc.getattr = NULL;
562 0 : app->fnc.setattr = NULL;
563 0 : app->fnc.genkey = NULL;
564 0 : app->fnc.sign = do_sign;
565 0 : app->fnc.auth = NULL;
566 0 : app->fnc.decipher = NULL;
567 0 : app->fnc.change_pin = NULL /*do_change_pin*/;
568 0 : app->fnc.check_pin = NULL;
569 :
570 0 : app->force_chv1 = 1;
571 : }
572 :
573 0 : return rc;
574 : }
|