Line data Source code
1 : /* app-nks.c - The Telesec NKS card application.
2 : * Copyright (C) 2004, 2007, 2008, 2009 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 <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : /* Notes:
21 :
22 : - We are now targeting TCOS 3 cards and it may happen that there is
23 : a regression towards TCOS 2 cards. Please report.
24 :
25 : - The TKS3 AUT key is not used. It seems that it is only useful for
26 : the internal authentication command and not accessible by other
27 : applications. The key itself is in the encryption class but the
28 : corresponding certificate has only the digitalSignature
29 : capability.
30 :
31 : - If required, we automagically switch between the NKS application
32 : and the SigG application. This avoids to use the DINSIG
33 : application which is somewhat limited, has no support for Secure
34 : Messaging as required by TCOS 3 and has no way to change the PIN
35 : or even set the NullPIN.
36 :
37 : - We use the prefix NKS-DF01 for TCOS 2 cards and NKS-NKS3 for newer
38 : cards. This is because the NKS application has moved to DF02 with
39 : TCOS 3 and thus we better use a DF independent tag.
40 :
41 : - We use only the global PINs for the NKS application.
42 :
43 : */
44 :
45 : #include <config.h>
46 : #include <errno.h>
47 : #include <stdio.h>
48 : #include <stdlib.h>
49 : #include <string.h>
50 : #include <assert.h>
51 : #include <time.h>
52 :
53 : #include "scdaemon.h"
54 : #include "i18n.h"
55 : #include "iso7816.h"
56 : #include "app-common.h"
57 : #include "tlv.h"
58 : #include "apdu.h"
59 : #include "host2net.h"
60 :
61 : static char const aid_nks[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
62 : static char const aid_sigg[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 };
63 :
64 :
65 : static struct
66 : {
67 : int is_sigg; /* Valid for SigG application. */
68 : int fid; /* File ID. */
69 : int nks_ver; /* 0 for NKS version 2, 3 for version 3. */
70 : int certtype; /* Type of certificate or 0 if it is not a certificate. */
71 : int iskeypair; /* If true has the FID of the corresponding certificate. */
72 : int issignkey; /* True if file is a key usable for signing. */
73 : int isenckey; /* True if file is a key usable for decryption. */
74 : unsigned char kid; /* Corresponding key references. */
75 : } filelist[] = {
76 : { 0, 0x4531, 0, 0, 0xC000, 1, 0, 0x80 }, /* EF_PK.NKS.SIG */
77 : { 0, 0xC000, 0, 101 }, /* EF_C.NKS.SIG */
78 : { 0, 0x4331, 0, 100 },
79 : { 0, 0x4332, 0, 100 },
80 : { 0, 0xB000, 0, 110 }, /* EF_PK.RCA.NKS */
81 : { 0, 0x45B1, 0, 0, 0xC200, 0, 1, 0x81 }, /* EF_PK.NKS.ENC */
82 : { 0, 0xC200, 0, 101 }, /* EF_C.NKS.ENC */
83 : { 0, 0x43B1, 0, 100 },
84 : { 0, 0x43B2, 0, 100 },
85 : /* The authentication key is not used. */
86 : /* { 0, 0x4571, 3, 0, 0xC500, 0, 0, 0x82 }, /\* EF_PK.NKS.AUT *\/ */
87 : /* { 0, 0xC500, 3, 101 }, /\* EF_C.NKS.AUT *\/ */
88 : { 0, 0x45B2, 3, 0, 0xC201, 0, 1, 0x83 }, /* EF_PK.NKS.ENC1024 */
89 : { 0, 0xC201, 3, 101 }, /* EF_C.NKS.ENC1024 */
90 : { 1, 0x4531, 3, 0, 0xC000, 1, 1, 0x84 }, /* EF_PK.CH.SIG */
91 : { 1, 0xC000, 0, 101 }, /* EF_C.CH.SIG */
92 : { 1, 0xC008, 3, 101 }, /* EF_C.CA.SIG */
93 : { 1, 0xC00E, 3, 111 }, /* EF_C.RCA.SIG */
94 : { 0, 0 }
95 : };
96 :
97 :
98 :
99 : /* Object with application (i.e. NKS) specific data. */
100 : struct app_local_s {
101 : int nks_version; /* NKS version. */
102 :
103 : int sigg_active; /* True if switched to the SigG application. */
104 : int sigg_msig_checked;/* True if we checked for a mass signature card. */
105 : int sigg_is_msig; /* True if this is a mass signature card. */
106 :
107 : int need_app_select; /* Need to re-select the application. */
108 :
109 : };
110 :
111 :
112 :
113 : static gpg_error_t switch_application (app_t app, int enable_sigg);
114 :
115 :
116 :
117 : /* Release local data. */
118 : static void
119 0 : do_deinit (app_t app)
120 : {
121 0 : if (app && app->app_local)
122 : {
123 0 : xfree (app->app_local);
124 0 : app->app_local = NULL;
125 : }
126 0 : }
127 :
128 :
129 : static int
130 0 : all_zero_p (void *buffer, size_t length)
131 : {
132 : char *p;
133 :
134 0 : for (p=buffer; length; length--, p++)
135 0 : if (*p)
136 0 : return 0;
137 0 : return 1;
138 : }
139 :
140 :
141 : /* Read the file with FID, assume it contains a public key and return
142 : its keygrip in the caller provided 41 byte buffer R_GRIPSTR. */
143 : static gpg_error_t
144 0 : keygripstr_from_pk_file (app_t app, int fid, char *r_gripstr)
145 : {
146 : gpg_error_t err;
147 : unsigned char grip[20];
148 : unsigned char *buffer[2];
149 : size_t buflen[2];
150 : gcry_sexp_t sexp;
151 : int i;
152 0 : int offset[2] = { 0, 0 };
153 :
154 0 : err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
155 0 : if (err)
156 0 : return err;
157 0 : err = iso7816_read_record (app->slot, 1, 1, 0, &buffer[0], &buflen[0]);
158 0 : if (err)
159 0 : return err;
160 0 : err = iso7816_read_record (app->slot, 2, 1, 0, &buffer[1], &buflen[1]);
161 0 : if (err)
162 : {
163 0 : xfree (buffer[0]);
164 0 : return err;
165 : }
166 :
167 0 : if (app->app_local->nks_version < 3)
168 : {
169 : /* Old versions of NKS store the values in a TLV encoded format.
170 : We need to do some checks. */
171 0 : for (i=0; i < 2; i++)
172 : {
173 : /* Check that the value appears like an integer encoded as
174 : Simple-TLV. We don't check the tag because the tests cards I
175 : have use 1 for both, the modulus and the exponent - the
176 : example in the documentation gives 2 for the exponent. */
177 0 : if (buflen[i] < 3)
178 0 : err = gpg_error (GPG_ERR_TOO_SHORT);
179 0 : else if (buffer[i][1] != buflen[i]-2 )
180 0 : err = gpg_error (GPG_ERR_INV_OBJ);
181 : else
182 0 : offset[i] = 2;
183 : }
184 : }
185 : else
186 : {
187 : /* Remove leading zeroes to get a correct keygrip. Take care of
188 : negative numbers. We should also fix it the same way in
189 : libgcrypt but we can't yet rely on it yet. */
190 0 : for (i=0; i < 2; i++)
191 : {
192 0 : while (buflen[i]-offset[i] > 1
193 0 : && !buffer[i][offset[i]]
194 0 : && !(buffer[i][offset[i]+1] & 0x80))
195 0 : offset[i]++;
196 : }
197 : }
198 :
199 : /* Check whether negative values are not prefixed with a zero and
200 : fix that. */
201 0 : for (i=0; i < 2; i++)
202 : {
203 0 : if ((buflen[i]-offset[i]) && (buffer[i][offset[i]] & 0x80))
204 : {
205 : unsigned char *newbuf;
206 : size_t newlen;
207 :
208 0 : newlen = 1 + buflen[i] - offset[i];
209 0 : newbuf = xtrymalloc (newlen);
210 0 : if (!newlen)
211 : {
212 0 : xfree (buffer[0]);
213 0 : xfree (buffer[1]);
214 0 : return gpg_error_from_syserror ();
215 : }
216 0 : newbuf[0] = 0;
217 0 : memcpy (newbuf+1, buffer[i]+offset[i], buflen[i] - offset[i]);
218 0 : xfree (buffer[i]);
219 0 : buffer[i] = newbuf;
220 0 : buflen[i] = newlen;
221 0 : offset[i] = 0;
222 : }
223 : }
224 :
225 0 : if (!err)
226 0 : err = gcry_sexp_build (&sexp, NULL,
227 : "(public-key (rsa (n %b) (e %b)))",
228 0 : (int)buflen[0]-offset[0], buffer[0]+offset[0],
229 0 : (int)buflen[1]-offset[1], buffer[1]+offset[1]);
230 :
231 0 : xfree (buffer[0]);
232 0 : xfree (buffer[1]);
233 0 : if (err)
234 0 : return err;
235 :
236 0 : if (!gcry_pk_get_keygrip (sexp, grip))
237 : {
238 0 : err = gpg_error (GPG_ERR_INTERNAL); /* i.e. RSA not supported by
239 : libgcrypt. */
240 : }
241 : else
242 : {
243 0 : bin2hex (grip, 20, r_gripstr);
244 : }
245 0 : gcry_sexp_release (sexp);
246 0 : return err;
247 : }
248 :
249 :
250 : /* TCOS responds to a verify with empty data (i.e. without the Lc
251 : byte) with the status of the PIN. PWID is the PIN ID, If SIGG is
252 : true, the application is switched into SigG mode.
253 : Returns:
254 : -1 = Error retrieving the data,
255 : -2 = No such PIN,
256 : -3 = PIN blocked,
257 : -4 = NullPIN activ,
258 : n >= 0 = Number of verification attempts left. */
259 : static int
260 0 : get_chv_status (app_t app, int sigg, int pwid)
261 : {
262 0 : unsigned char *result = NULL;
263 : size_t resultlen;
264 : char command[4];
265 : int rc;
266 :
267 0 : if (switch_application (app, sigg))
268 0 : return sigg? -2 : -1; /* No such PIN / General error. */
269 :
270 0 : command[0] = 0x00;
271 0 : command[1] = 0x20;
272 0 : command[2] = 0x00;
273 0 : command[3] = pwid;
274 :
275 0 : if (apdu_send_direct (app->slot, 0, (unsigned char *)command,
276 : 4, 0, &result, &resultlen))
277 0 : rc = -1; /* Error. */
278 0 : else if (resultlen < 2)
279 0 : rc = -1; /* Error. */
280 : else
281 : {
282 0 : unsigned int sw = buf16_to_uint (result+resultlen-2);
283 :
284 0 : if (sw == 0x6a88)
285 0 : rc = -2; /* No such PIN. */
286 0 : else if (sw == 0x6983)
287 0 : rc = -3; /* PIN is blocked. */
288 0 : else if (sw == 0x6985)
289 0 : rc = -4; /* NullPIN is activ. */
290 0 : else if ((sw & 0xfff0) == 0x63C0)
291 0 : rc = (sw & 0x000f); /* PIN has N tries left. */
292 : else
293 0 : rc = -1; /* Other error. */
294 : }
295 0 : xfree (result);
296 :
297 0 : return rc;
298 : }
299 :
300 :
301 : /* Implement the GETATTR command. This is similar to the LEARN
302 : command but returns just one value via the status interface. */
303 : static gpg_error_t
304 0 : do_getattr (app_t app, ctrl_t ctrl, const char *name)
305 : {
306 : static struct {
307 : const char *name;
308 : int special;
309 : } table[] = {
310 : { "$AUTHKEYID", 1 },
311 : { "NKS-VERSION", 2 },
312 : { "CHV-STATUS", 3 },
313 : { NULL, 0 }
314 : };
315 0 : gpg_error_t err = 0;
316 : int idx;
317 : char buffer[100];
318 :
319 0 : err = switch_application (app, 0);
320 0 : if (err)
321 0 : return err;
322 :
323 0 : for (idx=0; table[idx].name && strcmp (table[idx].name, name); idx++)
324 : ;
325 0 : if (!table[idx].name)
326 0 : return gpg_error (GPG_ERR_INV_NAME);
327 :
328 0 : switch (table[idx].special)
329 : {
330 : case 1: /* $AUTHKEYID */
331 : {
332 : /* NetKey 3.0 cards define an authentication key but according
333 : to the specs this key is only usable for encryption and not
334 : signing. it might work anyway but it has not yet been
335 : tested - fixme. Thus for now we use the NKS signature key
336 : for authentication. */
337 0 : char const tmp[] = "NKS-NKS3.4531";
338 0 : send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
339 : }
340 0 : break;
341 :
342 : case 2: /* NKS-VERSION */
343 0 : snprintf (buffer, sizeof buffer, "%d", app->app_local->nks_version);
344 0 : send_status_info (ctrl, table[idx].name,
345 : buffer, strlen (buffer), NULL, 0);
346 0 : break;
347 :
348 : case 3: /* CHV-STATUS */
349 : {
350 : /* Returns: PW1.CH PW2.CH PW1.CH.SIG PW2.CH.SIG That are the
351 : two global passwords followed by the two SigG passwords.
352 : For the values, see the function get_chv_status. */
353 : int tmp[4];
354 :
355 : /* We use a helper array so that we can control that there is
356 : no superfluous application switch. Note that PW2.CH.SIG
357 : really has the identifier 0x83 and not 0x82 as one would
358 : expect. */
359 0 : tmp[0] = get_chv_status (app, 0, 0x00);
360 0 : tmp[1] = get_chv_status (app, 0, 0x01);
361 0 : tmp[2] = get_chv_status (app, 1, 0x81);
362 0 : tmp[3] = get_chv_status (app, 1, 0x83);
363 0 : snprintf (buffer, sizeof buffer,
364 : "%d %d %d %d", tmp[0], tmp[1], tmp[2], tmp[3]);
365 0 : send_status_info (ctrl, table[idx].name,
366 : buffer, strlen (buffer), NULL, 0);
367 : }
368 0 : break;
369 :
370 :
371 : default:
372 0 : err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
373 0 : break;
374 : }
375 :
376 0 : return err;
377 : }
378 :
379 :
380 :
381 : static void
382 0 : do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags, int is_sigg)
383 : {
384 : gpg_error_t err;
385 : char ct_buf[100], id_buf[100];
386 : int i;
387 : const char *tag;
388 :
389 0 : if (is_sigg)
390 0 : tag = "SIGG";
391 0 : else if (app->app_local->nks_version < 3)
392 0 : tag = "DF01";
393 : else
394 0 : tag = "NKS3";
395 :
396 : /* Output information about all useful objects in the NKS application. */
397 0 : for (i=0; filelist[i].fid; i++)
398 : {
399 0 : if (filelist[i].nks_ver > app->app_local->nks_version)
400 0 : continue;
401 :
402 0 : if (!!filelist[i].is_sigg != !!is_sigg)
403 0 : continue;
404 :
405 0 : if (filelist[i].certtype && !(flags &1))
406 0 : {
407 : size_t len;
408 :
409 0 : len = app_help_read_length_of_cert (app->slot,
410 : filelist[i].fid, NULL);
411 0 : if (len)
412 : {
413 : /* FIXME: We should store the length in the application's
414 : context so that a following readcert does only need to
415 : read that many bytes. */
416 0 : snprintf (ct_buf, sizeof ct_buf, "%d", filelist[i].certtype);
417 0 : snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X",
418 : tag, filelist[i].fid);
419 0 : send_status_info (ctrl, "CERTINFO",
420 : ct_buf, strlen (ct_buf),
421 : id_buf, strlen (id_buf),
422 : NULL, (size_t)0);
423 : }
424 : }
425 0 : else if (filelist[i].iskeypair)
426 : {
427 : char gripstr[40+1];
428 :
429 0 : err = keygripstr_from_pk_file (app, filelist[i].fid, gripstr);
430 0 : if (err)
431 0 : log_error ("can't get keygrip from FID 0x%04X: %s\n",
432 : filelist[i].fid, gpg_strerror (err));
433 : else
434 : {
435 0 : snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X",
436 : tag, filelist[i].fid);
437 0 : send_status_info (ctrl, "KEYPAIRINFO",
438 : gripstr, 40,
439 : id_buf, strlen (id_buf),
440 : NULL, (size_t)0);
441 : }
442 : }
443 : }
444 :
445 :
446 0 : }
447 :
448 :
449 : static gpg_error_t
450 0 : do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
451 : {
452 : gpg_error_t err;
453 :
454 0 : err = switch_application (app, 0);
455 0 : if (err)
456 0 : return err;
457 :
458 0 : do_learn_status_core (app, ctrl, flags, 0);
459 :
460 0 : err = switch_application (app, 1);
461 0 : if (err)
462 0 : return 0; /* Silently ignore if we can't switch to SigG. */
463 :
464 0 : do_learn_status_core (app, ctrl, flags, 1);
465 :
466 0 : return 0;
467 : }
468 :
469 :
470 :
471 :
472 : /* Read the certificate with id CERTID (as returned by learn_status in
473 : the CERTINFO status lines) and return it in the freshly allocated
474 : buffer put into CERT and the length of the certificate put into
475 : CERTLEN. */
476 : static gpg_error_t
477 0 : do_readcert (app_t app, const char *certid,
478 : unsigned char **cert, size_t *certlen)
479 : {
480 : int i, fid;
481 : gpg_error_t err;
482 : unsigned char *buffer;
483 : const unsigned char *p;
484 : size_t buflen, n;
485 : int class, tag, constructed, ndef;
486 : size_t totobjlen, objlen, hdrlen;
487 0 : int rootca = 0;
488 0 : int is_sigg = 0;
489 :
490 0 : *cert = NULL;
491 0 : *certlen = 0;
492 :
493 0 : if (!strncmp (certid, "NKS-NKS3.", 9))
494 : ;
495 0 : else if (!strncmp (certid, "NKS-DF01.", 9))
496 : ;
497 0 : else if (!strncmp (certid, "NKS-SIGG.", 9))
498 0 : is_sigg = 1;
499 : else
500 0 : return gpg_error (GPG_ERR_INV_ID);
501 :
502 0 : err = switch_application (app, is_sigg);
503 0 : if (err)
504 0 : return err;
505 :
506 0 : certid += 9;
507 0 : if (!hexdigitp (certid) || !hexdigitp (certid+1)
508 0 : || !hexdigitp (certid+2) || !hexdigitp (certid+3)
509 0 : || certid[4])
510 0 : return gpg_error (GPG_ERR_INV_ID);
511 0 : fid = xtoi_4 (certid);
512 0 : for (i=0; filelist[i].fid; i++)
513 0 : if ((filelist[i].certtype || filelist[i].iskeypair)
514 0 : && filelist[i].fid == fid)
515 0 : break;
516 0 : if (!filelist[i].fid)
517 0 : return gpg_error (GPG_ERR_NOT_FOUND);
518 :
519 : /* If the requested objects is a plain public key, redirect it to
520 : the corresponding certificate. The whole system is a bit messy
521 : because we sometime use the key directly or let the caller
522 : retrieve the key from the certificate. The rationale for
523 : that is to support not-yet stored certificates. */
524 0 : if (filelist[i].iskeypair)
525 0 : fid = filelist[i].iskeypair;
526 :
527 :
528 : /* Read the entire file. fixme: This could be optimized by first
529 : reading the header to figure out how long the certificate
530 : actually is. */
531 0 : err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
532 0 : if (err)
533 : {
534 0 : log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err));
535 0 : return err;
536 : }
537 :
538 0 : err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen);
539 0 : if (err)
540 : {
541 0 : log_error ("error reading certificate from FID 0x%04X: %s\n",
542 : fid, gpg_strerror (err));
543 0 : return err;
544 : }
545 :
546 0 : if (!buflen || *buffer == 0xff)
547 : {
548 0 : log_info ("no certificate contained in FID 0x%04X\n", fid);
549 0 : err = gpg_error (GPG_ERR_NOT_FOUND);
550 0 : goto leave;
551 : }
552 :
553 : /* Now figure something out about the object. */
554 0 : p = buffer;
555 0 : n = buflen;
556 0 : err = parse_ber_header (&p, &n, &class, &tag, &constructed,
557 : &ndef, &objlen, &hdrlen);
558 0 : if (err)
559 0 : goto leave;
560 0 : if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed )
561 : ;
562 0 : else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed )
563 0 : rootca = 1;
564 : else
565 0 : return gpg_error (GPG_ERR_INV_OBJ);
566 0 : totobjlen = objlen + hdrlen;
567 0 : assert (totobjlen <= buflen);
568 :
569 0 : err = parse_ber_header (&p, &n, &class, &tag, &constructed,
570 : &ndef, &objlen, &hdrlen);
571 0 : if (err)
572 0 : goto leave;
573 :
574 0 : if (rootca)
575 : ;
576 0 : else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed)
577 : {
578 : const unsigned char *save_p;
579 :
580 : /* The certificate seems to be contained in a userCertificate
581 : container. Skip this and assume the following sequence is
582 : the certificate. */
583 0 : if (n < objlen)
584 : {
585 0 : err = gpg_error (GPG_ERR_INV_OBJ);
586 0 : goto leave;
587 : }
588 0 : p += objlen;
589 0 : n -= objlen;
590 0 : save_p = p;
591 0 : err = parse_ber_header (&p, &n, &class, &tag, &constructed,
592 : &ndef, &objlen, &hdrlen);
593 0 : if (err)
594 0 : goto leave;
595 0 : if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) )
596 0 : return gpg_error (GPG_ERR_INV_OBJ);
597 0 : totobjlen = objlen + hdrlen;
598 0 : assert (save_p + totobjlen <= buffer + buflen);
599 0 : memmove (buffer, save_p, totobjlen);
600 : }
601 :
602 0 : *cert = buffer;
603 0 : buffer = NULL;
604 0 : *certlen = totobjlen;
605 :
606 : leave:
607 0 : xfree (buffer);
608 0 : return err;
609 : }
610 :
611 :
612 : /* Handle the READKEY command. On success a canonical encoded
613 : S-expression with the public key will get stored at PK and its
614 : length at PKLEN; the caller must release that buffer. On error PK
615 : and PKLEN are not changed and an error code is returned. As of now
616 : this function is only useful for the internal authentication key.
617 : Other keys are automagically retrieved via by means of the
618 : certificate parsing code in commands.c:cmd_readkey. For internal
619 : use PK and PKLEN may be NULL to just check for an existing key. */
620 : static gpg_error_t
621 0 : do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
622 : {
623 : gpg_error_t err;
624 : unsigned char *buffer[2];
625 : size_t buflen[2];
626 0 : unsigned short path[1] = { 0x4500 };
627 :
628 : /* We use a generic name to retrieve PK.AUT.IFD-SPK. */
629 0 : if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
630 : ;
631 : else /* Return the error code expected by cmd_readkey. */
632 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
633 :
634 : /* Access the KEYD file which is always in the master directory. */
635 0 : err = iso7816_select_path (app->slot, path, DIM (path), NULL, NULL);
636 0 : if (err)
637 0 : return err;
638 : /* Due to the above select we need to re-select our application. */
639 0 : app->app_local->need_app_select = 1;
640 : /* Get the two records. */
641 0 : err = iso7816_read_record (app->slot, 5, 1, 0, &buffer[0], &buflen[0]);
642 0 : if (err)
643 0 : return err;
644 0 : if (all_zero_p (buffer[0], buflen[0]))
645 : {
646 0 : xfree (buffer[0]);
647 0 : return gpg_error (GPG_ERR_NOT_FOUND);
648 : }
649 0 : err = iso7816_read_record (app->slot, 6, 1, 0, &buffer[1], &buflen[1]);
650 0 : if (err)
651 : {
652 0 : xfree (buffer[0]);
653 0 : return err;
654 : }
655 :
656 0 : if (pk && pklen)
657 : {
658 0 : *pk = make_canon_sexp_from_rsa_pk (buffer[0], buflen[0],
659 0 : buffer[1], buflen[1],
660 : pklen);
661 0 : if (!*pk)
662 0 : err = gpg_error_from_syserror ();
663 : }
664 :
665 0 : xfree (buffer[0]);
666 0 : xfree (buffer[1]);
667 0 : return err;
668 : }
669 :
670 :
671 : /* Handle the WRITEKEY command for NKS. This function expects a
672 : canonical encoded S-expression with the public key in KEYDATA and
673 : its length in KEYDATALEN. The only supported KEYID is
674 : "$IFDAUTHKEY" to store the terminal key on the card. Bit 0 of
675 : FLAGS indicates whether an existing key shall get overwritten.
676 : PINCB and PINCB_ARG are the usual arguments for the pinentry
677 : callback. */
678 : static gpg_error_t
679 0 : do_writekey (app_t app, ctrl_t ctrl,
680 : const char *keyid, unsigned int flags,
681 : gpg_error_t (*pincb)(void*, const char *, char **),
682 : void *pincb_arg,
683 : const unsigned char *keydata, size_t keydatalen)
684 : {
685 : gpg_error_t err;
686 0 : int force = (flags & 1);
687 0 : const unsigned char *rsa_n = NULL;
688 0 : const unsigned char *rsa_e = NULL;
689 : size_t rsa_n_len, rsa_e_len;
690 : unsigned int nbits;
691 :
692 : (void)ctrl;
693 : (void)pincb;
694 : (void)pincb_arg;
695 :
696 0 : if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
697 : ;
698 : else
699 0 : return gpg_error (GPG_ERR_INV_ID);
700 :
701 0 : if (!force && !do_readkey (app, keyid, NULL, NULL))
702 0 : return gpg_error (GPG_ERR_EEXIST);
703 :
704 : /* Parse the S-expression. */
705 0 : err = get_rsa_pk_from_canon_sexp (keydata, keydatalen,
706 : &rsa_n, &rsa_n_len, &rsa_e, &rsa_e_len);
707 0 : if (err)
708 0 : goto leave;
709 :
710 : /* Check that the parameters match the requirements. */
711 0 : nbits = app_help_count_bits (rsa_n, rsa_n_len);
712 0 : if (nbits != 1024)
713 : {
714 0 : log_error (_("RSA modulus missing or not of size %d bits\n"), 1024);
715 0 : err = gpg_error (GPG_ERR_BAD_PUBKEY);
716 0 : goto leave;
717 : }
718 :
719 0 : nbits = app_help_count_bits (rsa_e, rsa_e_len);
720 0 : if (nbits < 2 || nbits > 32)
721 : {
722 0 : log_error (_("RSA public exponent missing or larger than %d bits\n"),
723 : 32);
724 0 : err = gpg_error (GPG_ERR_BAD_PUBKEY);
725 0 : goto leave;
726 : }
727 :
728 : /* /\* Store them. *\/ */
729 : /* err = verify_pin (app, 0, NULL, pincb, pincb_arg); */
730 : /* if (err) */
731 : /* goto leave; */
732 :
733 : /* Send the MSE:Store_Public_Key. */
734 0 : err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
735 : /* mse = xtrymalloc (1000); */
736 :
737 : /* mse[0] = 0x80; /\* Algorithm reference. *\/ */
738 : /* mse[1] = 1; */
739 : /* mse[2] = 0x17; */
740 : /* mse[3] = 0x84; /\* Private key reference. *\/ */
741 : /* mse[4] = 1; */
742 : /* mse[5] = 0x77; */
743 : /* mse[6] = 0x7F; /\* Public key parameter. *\/ */
744 : /* mse[7] = 0x49; */
745 : /* mse[8] = 0x81; */
746 : /* mse[9] = 3 + 0x80 + 2 + rsa_e_len; */
747 : /* mse[10] = 0x81; /\* RSA modulus of 128 byte. *\/ */
748 : /* mse[11] = 0x81; */
749 : /* mse[12] = rsa_n_len; */
750 : /* memcpy (mse+12, rsa_n, rsa_n_len); */
751 : /* mse[10] = 0x82; /\* RSA public exponent of up to 4 bytes. *\/ */
752 : /* mse[12] = rsa_e_len; */
753 : /* memcpy (mse+12, rsa_e, rsa_e_len); */
754 : /* err = iso7816_manage_security_env (app->slot, 0x81, 0xB6, */
755 : /* mse, sizeof mse); */
756 :
757 : leave:
758 0 : return err;
759 : }
760 :
761 :
762 : static gpg_error_t
763 0 : basic_pin_checks (const char *pinvalue, int minlen, int maxlen)
764 : {
765 0 : if (strlen (pinvalue) < minlen)
766 : {
767 0 : log_error ("PIN is too short; minimum length is %d\n", minlen);
768 0 : return gpg_error (GPG_ERR_BAD_PIN);
769 : }
770 0 : if (strlen (pinvalue) > maxlen)
771 : {
772 0 : log_error ("PIN is too large; maximum length is %d\n", maxlen);
773 0 : return gpg_error (GPG_ERR_BAD_PIN);
774 : }
775 0 : return 0;
776 : }
777 :
778 :
779 : /* Verify the PIN if required. */
780 : static gpg_error_t
781 0 : verify_pin (app_t app, int pwid, const char *desc,
782 : gpg_error_t (*pincb)(void*, const char *, char **),
783 : void *pincb_arg)
784 : {
785 : pininfo_t pininfo;
786 : int rc;
787 :
788 0 : if (!desc)
789 0 : desc = "PIN";
790 :
791 0 : memset (&pininfo, 0, sizeof pininfo);
792 0 : pininfo.fixedlen = -1;
793 0 : pininfo.minlen = 6;
794 0 : pininfo.maxlen = 16;
795 :
796 0 : if (!opt.disable_pinpad
797 0 : && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
798 : {
799 0 : rc = pincb (pincb_arg, desc, NULL);
800 0 : if (rc)
801 : {
802 0 : log_info (_("PIN callback returned error: %s\n"),
803 : gpg_strerror (rc));
804 0 : return rc;
805 : }
806 :
807 0 : rc = iso7816_verify_kp (app->slot, pwid, &pininfo);
808 0 : pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */
809 : }
810 : else
811 : {
812 : char *pinvalue;
813 :
814 0 : rc = pincb (pincb_arg, desc, &pinvalue);
815 0 : if (rc)
816 : {
817 0 : log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
818 0 : return rc;
819 : }
820 :
821 0 : rc = basic_pin_checks (pinvalue, pininfo.minlen, pininfo.maxlen);
822 0 : if (rc)
823 : {
824 0 : xfree (pinvalue);
825 0 : return rc;
826 : }
827 :
828 0 : rc = iso7816_verify (app->slot, pwid, pinvalue, strlen (pinvalue));
829 0 : xfree (pinvalue);
830 : }
831 :
832 0 : if (rc)
833 : {
834 0 : if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
835 0 : log_error (_("the NullPIN has not yet been changed\n"));
836 : else
837 0 : log_error ("verify PIN failed\n");
838 0 : return rc;
839 : }
840 :
841 0 : return 0;
842 : }
843 :
844 :
845 : /* Create the signature and return the allocated result in OUTDATA.
846 : If a PIN is required the PINCB will be used to ask for the PIN;
847 : that callback should return the PIN in an allocated buffer and
848 : store that in the 3rd argument. */
849 : static gpg_error_t
850 0 : do_sign (app_t app, const char *keyidstr, int hashalgo,
851 : gpg_error_t (*pincb)(void*, const char *, char **),
852 : void *pincb_arg,
853 : const void *indata, size_t indatalen,
854 : unsigned char **outdata, size_t *outdatalen )
855 : {
856 : static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
857 : { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
858 : 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
859 : static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
860 : { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
861 : 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
862 : int rc, i;
863 0 : int is_sigg = 0;
864 : int fid;
865 : unsigned char kid;
866 : unsigned char data[83]; /* Must be large enough for a SHA-1 digest
867 : + the largest OID prefix. */
868 : size_t datalen;
869 :
870 0 : if (!keyidstr || !*keyidstr)
871 0 : return gpg_error (GPG_ERR_INV_VALUE);
872 0 : switch (indatalen)
873 : {
874 0 : case 16: case 20: case 35: case 47: case 51: case 67: case 83: break;
875 0 : default: return gpg_error (GPG_ERR_INV_VALUE);
876 : }
877 :
878 : /* Check that the provided ID is valid. This is not really needed
879 : but we do it to enforce correct usage by the caller. */
880 0 : if (!strncmp (keyidstr, "NKS-NKS3.", 9) )
881 : ;
882 0 : else if (!strncmp (keyidstr, "NKS-DF01.", 9) )
883 : ;
884 0 : else if (!strncmp (keyidstr, "NKS-SIGG.", 9) )
885 0 : is_sigg = 1;
886 : else
887 0 : return gpg_error (GPG_ERR_INV_ID);
888 0 : keyidstr += 9;
889 :
890 0 : rc = switch_application (app, is_sigg);
891 0 : if (rc)
892 0 : return rc;
893 :
894 0 : if (is_sigg && app->app_local->sigg_is_msig)
895 : {
896 0 : log_info ("mass signature cards are not allowed\n");
897 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
898 : }
899 :
900 0 : if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
901 0 : || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
902 0 : || keyidstr[4])
903 0 : return gpg_error (GPG_ERR_INV_ID);
904 0 : fid = xtoi_4 (keyidstr);
905 0 : for (i=0; filelist[i].fid; i++)
906 0 : if (filelist[i].iskeypair && filelist[i].fid == fid)
907 0 : break;
908 0 : if (!filelist[i].fid)
909 0 : return gpg_error (GPG_ERR_NOT_FOUND);
910 0 : if (!filelist[i].issignkey)
911 0 : return gpg_error (GPG_ERR_INV_ID);
912 0 : kid = filelist[i].kid;
913 :
914 : /* Prepare the DER object from INDATA. */
915 0 : if (app->app_local->nks_version > 2 && (indatalen == 35
916 0 : || indatalen == 47
917 0 : || indatalen == 51
918 0 : || indatalen == 67
919 0 : || indatalen == 83))
920 : {
921 : /* The caller send data matching the length of the ASN.1 encoded
922 : hash for SHA-{1,224,256,384,512}. Assume that is okay. */
923 0 : assert (indatalen <= sizeof data);
924 0 : memcpy (data, indata, indatalen);
925 0 : datalen = indatalen;
926 : }
927 0 : else if (indatalen == 35)
928 : {
929 : /* Alright, the caller was so kind to send us an already
930 : prepared DER object. This is for TCOS 2. */
931 0 : if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
932 : ;
933 0 : else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata,rmd160_prefix,15))
934 : ;
935 : else
936 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
937 0 : memcpy (data, indata, indatalen);
938 0 : datalen = 35;
939 : }
940 0 : else if (indatalen == 20)
941 : {
942 0 : if (hashalgo == GCRY_MD_SHA1)
943 0 : memcpy (data, sha1_prefix, 15);
944 0 : else if (hashalgo == GCRY_MD_RMD160)
945 0 : memcpy (data, rmd160_prefix, 15);
946 : else
947 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
948 0 : memcpy (data+15, indata, indatalen);
949 0 : datalen = 35;
950 : }
951 : else
952 0 : return gpg_error (GPG_ERR_INV_VALUE);
953 :
954 :
955 : /* Send an MSE for PSO:Computer_Signature. */
956 0 : if (app->app_local->nks_version > 2)
957 : {
958 : unsigned char mse[6];
959 :
960 0 : mse[0] = 0x80; /* Algorithm reference. */
961 0 : mse[1] = 1;
962 0 : mse[2] = 2; /* RSA, card does pkcs#1 v1.5 padding, no ASN.1 check. */
963 0 : mse[3] = 0x84; /* Private key reference. */
964 0 : mse[4] = 1;
965 0 : mse[5] = kid;
966 0 : rc = iso7816_manage_security_env (app->slot, 0x41, 0xB6,
967 : mse, sizeof mse);
968 : }
969 : /* Verify using PW1.CH. */
970 0 : if (!rc)
971 0 : rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
972 : /* Compute the signature. */
973 0 : if (!rc)
974 0 : rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0,
975 : outdata, outdatalen);
976 0 : return rc;
977 : }
978 :
979 :
980 :
981 : /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
982 : If a PIN is required the PINCB will be used to ask for the PIN; it
983 : should return the PIN in an allocated buffer and put it into PIN. */
984 : static gpg_error_t
985 0 : do_decipher (app_t app, const char *keyidstr,
986 : gpg_error_t (*pincb)(void*, const char *, char **),
987 : void *pincb_arg,
988 : const void *indata, size_t indatalen,
989 : unsigned char **outdata, size_t *outdatalen,
990 : unsigned int *r_info)
991 : {
992 : int rc, i;
993 0 : int is_sigg = 0;
994 : int fid;
995 : int kid;
996 :
997 : (void)r_info;
998 :
999 0 : if (!keyidstr || !*keyidstr || !indatalen)
1000 0 : return gpg_error (GPG_ERR_INV_VALUE);
1001 :
1002 : /* Check that the provided ID is valid. This is not really needed
1003 : but we do it to to enforce correct usage by the caller. */
1004 0 : if (!strncmp (keyidstr, "NKS-NKS3.", 9) )
1005 : ;
1006 0 : else if (!strncmp (keyidstr, "NKS-DF01.", 9) )
1007 : ;
1008 0 : else if (!strncmp (keyidstr, "NKS-SIGG.", 9) )
1009 0 : is_sigg = 1;
1010 : else
1011 0 : return gpg_error (GPG_ERR_INV_ID);
1012 0 : keyidstr += 9;
1013 :
1014 0 : rc = switch_application (app, is_sigg);
1015 0 : if (rc)
1016 0 : return rc;
1017 :
1018 0 : if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
1019 0 : || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
1020 0 : || keyidstr[4])
1021 0 : return gpg_error (GPG_ERR_INV_ID);
1022 0 : fid = xtoi_4 (keyidstr);
1023 0 : for (i=0; filelist[i].fid; i++)
1024 0 : if (filelist[i].iskeypair && filelist[i].fid == fid)
1025 0 : break;
1026 0 : if (!filelist[i].fid)
1027 0 : return gpg_error (GPG_ERR_NOT_FOUND);
1028 0 : if (!filelist[i].isenckey)
1029 0 : return gpg_error (GPG_ERR_INV_ID);
1030 0 : kid = filelist[i].kid;
1031 :
1032 0 : if (app->app_local->nks_version > 2)
1033 : {
1034 : unsigned char mse[6];
1035 0 : mse[0] = 0x80; /* Algorithm reference. */
1036 0 : mse[1] = 1;
1037 0 : mse[2] = 0x0a; /* RSA no padding. (0x1A is pkcs#1.5 padding.) */
1038 0 : mse[3] = 0x84; /* Private key reference. */
1039 0 : mse[4] = 1;
1040 0 : mse[5] = kid;
1041 0 : rc = iso7816_manage_security_env (app->slot, 0x41, 0xB8,
1042 : mse, sizeof mse);
1043 : }
1044 : else
1045 : {
1046 : static const unsigned char mse[] =
1047 : {
1048 : 0x80, 1, 0x10, /* Select algorithm RSA. */
1049 : 0x84, 1, 0x81 /* Select local secret key 1 for decryption. */
1050 : };
1051 0 : rc = iso7816_manage_security_env (app->slot, 0xC1, 0xB8,
1052 : mse, sizeof mse);
1053 :
1054 : }
1055 :
1056 0 : if (!rc)
1057 0 : rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
1058 :
1059 : /* Note that we need to use extended length APDUs for TCOS 3 cards.
1060 : Command chaining does not work. */
1061 0 : if (!rc)
1062 0 : rc = iso7816_decipher (app->slot, app->app_local->nks_version > 2? 1:0,
1063 : indata, indatalen, 0, 0x81,
1064 : outdata, outdatalen);
1065 0 : return rc;
1066 : }
1067 :
1068 :
1069 :
1070 : /* Parse a password ID string. Returns NULL on error or a string
1071 : suitable as passpahrse prompt on success. On success stores the
1072 : reference value for the password at R_PWID and a flag indicating
1073 : that the SigG application is to be used at R_SIGG. If NEW_MODE is
1074 : true, the returned description is suitable for a new Password.
1075 : Supported values for PWIDSTR are:
1076 :
1077 : PW1.CH - Global password 1
1078 : PW2.CH - Global password 2
1079 : PW1.CH.SIG - SigG password 1
1080 : PW2.CH.SIG - SigG password 2
1081 : */
1082 : static const char *
1083 0 : parse_pwidstr (const char *pwidstr, int new_mode, int *r_sigg, int *r_pwid)
1084 : {
1085 : const char *desc;
1086 :
1087 0 : if (!pwidstr)
1088 0 : desc = NULL;
1089 0 : else if (!strcmp (pwidstr, "PW1.CH"))
1090 : {
1091 0 : *r_sigg = 0;
1092 0 : *r_pwid = 0x00;
1093 : /* TRANSLATORS: Do not translate the "|*|" prefixes but keep
1094 : them verbatim at the start of the string. */
1095 0 : desc = (new_mode
1096 : ? _("|N|Please enter a new PIN for the standard keys.")
1097 : : _("||Please enter the PIN for the standard keys."));
1098 : }
1099 0 : else if (!strcmp (pwidstr, "PW2.CH"))
1100 : {
1101 0 : *r_pwid = 0x01;
1102 0 : desc = (new_mode
1103 : ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
1104 : "for the standard keys.")
1105 : : _("|P|Please enter the PIN Unblocking Code (PUK) "
1106 : "for the standard keys."));
1107 : }
1108 0 : else if (!strcmp (pwidstr, "PW1.CH.SIG"))
1109 : {
1110 0 : *r_pwid = 0x81;
1111 0 : *r_sigg = 1;
1112 0 : desc = (new_mode
1113 : ? _("|N|Please enter a new PIN for the key to create "
1114 : "qualified signatures.")
1115 : : _("||Please enter the PIN for the key to create "
1116 : "qualified signatures."));
1117 : }
1118 0 : else if (!strcmp (pwidstr, "PW2.CH.SIG"))
1119 : {
1120 0 : *r_pwid = 0x83; /* Yes, that is 83 and not 82. */
1121 0 : *r_sigg = 1;
1122 0 : desc = (new_mode
1123 : ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
1124 : "for the key to create qualified signatures.")
1125 : : _("|P|Please enter the PIN Unblocking Code (PUK) "
1126 : "for the key to create qualified signatures."));
1127 : }
1128 : else
1129 : {
1130 0 : *r_pwid = 0; /* Only to avoid gcc warning in calling function. */
1131 0 : desc = NULL; /* Error. */
1132 : }
1133 :
1134 0 : return desc;
1135 : }
1136 :
1137 :
1138 : /* Handle the PASSWD command. See parse_pwidstr() for allowed values
1139 : for CHVNOSTR. */
1140 : static gpg_error_t
1141 0 : do_change_pin (app_t app, ctrl_t ctrl, const char *pwidstr,
1142 : unsigned int flags,
1143 : gpg_error_t (*pincb)(void*, const char *, char **),
1144 : void *pincb_arg)
1145 : {
1146 : gpg_error_t err;
1147 0 : char *newpin = NULL;
1148 0 : char *oldpin = NULL;
1149 : size_t newpinlen;
1150 : size_t oldpinlen;
1151 : int is_sigg;
1152 : const char *newdesc;
1153 : int pwid;
1154 : pininfo_t pininfo;
1155 :
1156 : (void)ctrl;
1157 :
1158 : /* The minimum length is enforced by TCOS, the maximum length is
1159 : just a reasonable value. */
1160 0 : memset (&pininfo, 0, sizeof pininfo);
1161 0 : pininfo.minlen = 6;
1162 0 : pininfo.maxlen = 16;
1163 :
1164 0 : newdesc = parse_pwidstr (pwidstr, 1, &is_sigg, &pwid);
1165 0 : if (!newdesc)
1166 0 : return gpg_error (GPG_ERR_INV_ID);
1167 :
1168 0 : err = switch_application (app, is_sigg);
1169 0 : if (err)
1170 0 : return err;
1171 :
1172 0 : if ((flags & APP_CHANGE_FLAG_NULLPIN))
1173 : {
1174 : /* With the nullpin flag, we do not verify the PIN - it would
1175 : fail if the Nullpin is still set. */
1176 0 : oldpin = xtrycalloc (1, 6);
1177 0 : if (!oldpin)
1178 : {
1179 0 : err = gpg_error_from_syserror ();
1180 0 : goto leave;
1181 : }
1182 0 : oldpinlen = 6;
1183 : }
1184 : else
1185 : {
1186 : const char *desc;
1187 : int dummy1, dummy2;
1188 :
1189 0 : if ((flags & APP_CHANGE_FLAG_RESET))
1190 : {
1191 : /* Reset mode: Ask for the alternate PIN. */
1192 : const char *altpwidstr;
1193 :
1194 0 : if (!strcmp (pwidstr, "PW1.CH"))
1195 0 : altpwidstr = "PW2.CH";
1196 0 : else if (!strcmp (pwidstr, "PW2.CH"))
1197 0 : altpwidstr = "PW1.CH";
1198 0 : else if (!strcmp (pwidstr, "PW1.CH.SIG"))
1199 0 : altpwidstr = "PW2.CH.SIG";
1200 0 : else if (!strcmp (pwidstr, "PW2.CH.SIG"))
1201 0 : altpwidstr = "PW1.CH.SIG";
1202 : else
1203 : {
1204 0 : err = gpg_error (GPG_ERR_BUG);
1205 0 : goto leave;
1206 : }
1207 0 : desc = parse_pwidstr (altpwidstr, 0, &dummy1, &dummy2);
1208 : }
1209 : else
1210 : {
1211 : /* Regular change mode: Ask for the old PIN. */
1212 0 : desc = parse_pwidstr (pwidstr, 0, &dummy1, &dummy2);
1213 : }
1214 0 : err = pincb (pincb_arg, desc, &oldpin);
1215 0 : if (err)
1216 : {
1217 0 : log_error ("error getting old PIN: %s\n", gpg_strerror (err));
1218 0 : goto leave;
1219 : }
1220 0 : oldpinlen = strlen (oldpin);
1221 0 : err = basic_pin_checks (oldpin, pininfo.minlen, pininfo.maxlen);
1222 0 : if (err)
1223 0 : goto leave;
1224 : }
1225 :
1226 0 : err = pincb (pincb_arg, newdesc, &newpin);
1227 0 : if (err)
1228 : {
1229 0 : log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
1230 0 : goto leave;
1231 : }
1232 0 : newpinlen = strlen (newpin);
1233 :
1234 0 : err = basic_pin_checks (newpin, pininfo.minlen, pininfo.maxlen);
1235 0 : if (err)
1236 0 : goto leave;
1237 :
1238 0 : if ((flags & APP_CHANGE_FLAG_RESET))
1239 : {
1240 : char *data;
1241 0 : size_t datalen = oldpinlen + newpinlen;
1242 :
1243 0 : data = xtrymalloc (datalen);
1244 0 : if (!data)
1245 : {
1246 0 : err = gpg_error_from_syserror ();
1247 0 : goto leave;
1248 : }
1249 0 : memcpy (data, oldpin, oldpinlen);
1250 0 : memcpy (data+oldpinlen, newpin, newpinlen);
1251 0 : err = iso7816_reset_retry_counter_with_rc (app->slot, pwid,
1252 : data, datalen);
1253 0 : wipememory (data, datalen);
1254 0 : xfree (data);
1255 : }
1256 : else
1257 0 : err = iso7816_change_reference_data (app->slot, pwid,
1258 : oldpin, oldpinlen,
1259 : newpin, newpinlen);
1260 : leave:
1261 0 : xfree (oldpin);
1262 0 : xfree (newpin);
1263 0 : return err;
1264 : }
1265 :
1266 :
1267 : /* Perform a simple verify operation. KEYIDSTR should be NULL or empty. */
1268 : static gpg_error_t
1269 0 : do_check_pin (app_t app, const char *pwidstr,
1270 : gpg_error_t (*pincb)(void*, const char *, char **),
1271 : void *pincb_arg)
1272 : {
1273 : gpg_error_t err;
1274 : int pwid;
1275 : int is_sigg;
1276 : const char *desc;
1277 :
1278 0 : desc = parse_pwidstr (pwidstr, 0, &is_sigg, &pwid);
1279 0 : if (!desc)
1280 0 : return gpg_error (GPG_ERR_INV_ID);
1281 :
1282 0 : err = switch_application (app, is_sigg);
1283 0 : if (err)
1284 0 : return err;
1285 :
1286 0 : return verify_pin (app, pwid, desc, pincb, pincb_arg);
1287 : }
1288 :
1289 :
1290 : /* Return the version of the NKS application. */
1291 : static int
1292 0 : get_nks_version (int slot)
1293 : {
1294 0 : unsigned char *result = NULL;
1295 : size_t resultlen;
1296 : int type;
1297 :
1298 0 : if (iso7816_apdu_direct (slot, "\x80\xaa\x06\x00\x00", 5, 0,
1299 : &result, &resultlen))
1300 0 : return 2; /* NKS 2 does not support this command. */
1301 :
1302 : /* Example value: 04 11 19 22 21 6A 20 80 03 03 01 01 01 00 00 00
1303 : vv tt ccccccccccccccccc aa bb cc vvvvvvvvvvv xx
1304 : vendor (Philips) -+ | | | | | | |
1305 : chip type -----------+ | | | | | |
1306 : chip id ----------------+ | | | | |
1307 : card type (3 - tcos 3) -------------------+ | | | |
1308 : OS version of card type ---------------------+ | | |
1309 : OS release of card type ------------------------+ | |
1310 : OS vendor internal version ------------------------+ |
1311 : RFU -----------------------------------------------------------+
1312 : */
1313 0 : if (resultlen < 16)
1314 0 : type = 0; /* Invalid data returned. */
1315 : else
1316 0 : type = result[8];
1317 0 : xfree (result);
1318 :
1319 0 : return type;
1320 : }
1321 :
1322 :
1323 : /* If ENABLE_SIGG is true switch to the SigG application if not yet
1324 : active. If false switch to the NKS application if not yet active.
1325 : Returns 0 on success. */
1326 : static gpg_error_t
1327 0 : switch_application (app_t app, int enable_sigg)
1328 : {
1329 : gpg_error_t err;
1330 :
1331 0 : if (((app->app_local->sigg_active && enable_sigg)
1332 0 : || (!app->app_local->sigg_active && !enable_sigg))
1333 0 : && !app->app_local->need_app_select)
1334 0 : return 0; /* Already switched. */
1335 :
1336 0 : log_info ("app-nks: switching to %s\n", enable_sigg? "SigG":"NKS");
1337 0 : if (enable_sigg)
1338 0 : err = iso7816_select_application (app->slot, aid_sigg, sizeof aid_sigg, 0);
1339 : else
1340 0 : err = iso7816_select_application (app->slot, aid_nks, sizeof aid_nks, 0);
1341 :
1342 0 : if (!err && enable_sigg && app->app_local->nks_version >= 3
1343 0 : && !app->app_local->sigg_msig_checked)
1344 : {
1345 : /* Check whether this card is a mass signature card. */
1346 : unsigned char *buffer;
1347 : size_t buflen;
1348 : const unsigned char *tmpl;
1349 : size_t tmpllen;
1350 :
1351 0 : app->app_local->sigg_msig_checked = 1;
1352 0 : app->app_local->sigg_is_msig = 1;
1353 0 : err = iso7816_select_file (app->slot, 0x5349, 0, NULL, NULL);
1354 0 : if (!err)
1355 0 : err = iso7816_read_record (app->slot, 1, 1, 0, &buffer, &buflen);
1356 0 : if (!err)
1357 : {
1358 0 : tmpl = find_tlv (buffer, buflen, 0x7a, &tmpllen);
1359 0 : if (tmpl && tmpllen == 12
1360 0 : && !memcmp (tmpl,
1361 : "\x93\x02\x00\x01\xA4\x06\x83\x01\x81\x83\x01\x83",
1362 : 12))
1363 0 : app->app_local->sigg_is_msig = 0;
1364 0 : xfree (buffer);
1365 : }
1366 0 : if (app->app_local->sigg_is_msig)
1367 0 : log_info ("This is a mass signature card\n");
1368 : }
1369 :
1370 0 : if (!err)
1371 : {
1372 0 : app->app_local->need_app_select = 0;
1373 0 : app->app_local->sigg_active = enable_sigg;
1374 : }
1375 : else
1376 0 : log_error ("app-nks: error switching to %s: %s\n",
1377 : enable_sigg? "SigG":"NKS", gpg_strerror (err));
1378 :
1379 0 : return err;
1380 : }
1381 :
1382 :
1383 : /* Select the NKS application. */
1384 : gpg_error_t
1385 0 : app_select_nks (app_t app)
1386 : {
1387 0 : int slot = app->slot;
1388 : int rc;
1389 :
1390 0 : rc = iso7816_select_application (slot, aid_nks, sizeof aid_nks, 0);
1391 0 : if (!rc)
1392 : {
1393 0 : app->apptype = "NKS";
1394 :
1395 0 : app->app_local = xtrycalloc (1, sizeof *app->app_local);
1396 0 : if (!app->app_local)
1397 : {
1398 0 : rc = gpg_error (gpg_err_code_from_errno (errno));
1399 0 : goto leave;
1400 : }
1401 :
1402 0 : app->app_local->nks_version = get_nks_version (slot);
1403 0 : if (opt.verbose)
1404 0 : log_info ("Detected NKS version: %d\n", app->app_local->nks_version);
1405 :
1406 0 : app->fnc.deinit = do_deinit;
1407 0 : app->fnc.learn_status = do_learn_status;
1408 0 : app->fnc.readcert = do_readcert;
1409 0 : app->fnc.readkey = do_readkey;
1410 0 : app->fnc.getattr = do_getattr;
1411 0 : app->fnc.setattr = NULL;
1412 0 : app->fnc.writekey = do_writekey;
1413 0 : app->fnc.genkey = NULL;
1414 0 : app->fnc.sign = do_sign;
1415 0 : app->fnc.auth = NULL;
1416 0 : app->fnc.decipher = do_decipher;
1417 0 : app->fnc.change_pin = do_change_pin;
1418 0 : app->fnc.check_pin = do_check_pin;
1419 : }
1420 :
1421 : leave:
1422 0 : if (rc)
1423 0 : do_deinit (app);
1424 0 : return rc;
1425 : }
|