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 <https://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, int advanced, const char *keyid,
622 : unsigned char **pk, size_t *pklen)
623 : {
624 : gpg_error_t err;
625 : unsigned char *buffer[2];
626 : size_t buflen[2];
627 0 : unsigned short path[1] = { 0x4500 };
628 :
629 0 : if (advanced)
630 0 : return GPG_ERR_NOT_SUPPORTED;
631 :
632 : /* We use a generic name to retrieve PK.AUT.IFD-SPK. */
633 0 : if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
634 : ;
635 : else /* Return the error code expected by cmd_readkey. */
636 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
637 :
638 : /* Access the KEYD file which is always in the master directory. */
639 0 : err = iso7816_select_path (app->slot, path, DIM (path), NULL, NULL);
640 0 : if (err)
641 0 : return err;
642 : /* Due to the above select we need to re-select our application. */
643 0 : app->app_local->need_app_select = 1;
644 : /* Get the two records. */
645 0 : err = iso7816_read_record (app->slot, 5, 1, 0, &buffer[0], &buflen[0]);
646 0 : if (err)
647 0 : return err;
648 0 : if (all_zero_p (buffer[0], buflen[0]))
649 : {
650 0 : xfree (buffer[0]);
651 0 : return gpg_error (GPG_ERR_NOT_FOUND);
652 : }
653 0 : err = iso7816_read_record (app->slot, 6, 1, 0, &buffer[1], &buflen[1]);
654 0 : if (err)
655 : {
656 0 : xfree (buffer[0]);
657 0 : return err;
658 : }
659 :
660 0 : if (pk && pklen)
661 : {
662 0 : *pk = make_canon_sexp_from_rsa_pk (buffer[0], buflen[0],
663 0 : buffer[1], buflen[1],
664 : pklen);
665 0 : if (!*pk)
666 0 : err = gpg_error_from_syserror ();
667 : }
668 :
669 0 : xfree (buffer[0]);
670 0 : xfree (buffer[1]);
671 0 : return err;
672 : }
673 :
674 :
675 : /* Handle the WRITEKEY command for NKS. This function expects a
676 : canonical encoded S-expression with the public key in KEYDATA and
677 : its length in KEYDATALEN. The only supported KEYID is
678 : "$IFDAUTHKEY" to store the terminal key on the card. Bit 0 of
679 : FLAGS indicates whether an existing key shall get overwritten.
680 : PINCB and PINCB_ARG are the usual arguments for the pinentry
681 : callback. */
682 : static gpg_error_t
683 0 : do_writekey (app_t app, ctrl_t ctrl,
684 : const char *keyid, unsigned int flags,
685 : gpg_error_t (*pincb)(void*, const char *, char **),
686 : void *pincb_arg,
687 : const unsigned char *keydata, size_t keydatalen)
688 : {
689 : gpg_error_t err;
690 0 : int force = (flags & 1);
691 0 : const unsigned char *rsa_n = NULL;
692 0 : const unsigned char *rsa_e = NULL;
693 : size_t rsa_n_len, rsa_e_len;
694 : unsigned int nbits;
695 :
696 : (void)ctrl;
697 : (void)pincb;
698 : (void)pincb_arg;
699 :
700 0 : if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
701 : ;
702 : else
703 0 : return gpg_error (GPG_ERR_INV_ID);
704 :
705 0 : if (!force && !do_readkey (app, 0, keyid, NULL, NULL))
706 0 : return gpg_error (GPG_ERR_EEXIST);
707 :
708 : /* Parse the S-expression. */
709 0 : err = get_rsa_pk_from_canon_sexp (keydata, keydatalen,
710 : &rsa_n, &rsa_n_len, &rsa_e, &rsa_e_len);
711 0 : if (err)
712 0 : goto leave;
713 :
714 : /* Check that the parameters match the requirements. */
715 0 : nbits = app_help_count_bits (rsa_n, rsa_n_len);
716 0 : if (nbits != 1024)
717 : {
718 0 : log_error (_("RSA modulus missing or not of size %d bits\n"), 1024);
719 0 : err = gpg_error (GPG_ERR_BAD_PUBKEY);
720 0 : goto leave;
721 : }
722 :
723 0 : nbits = app_help_count_bits (rsa_e, rsa_e_len);
724 0 : if (nbits < 2 || nbits > 32)
725 : {
726 0 : log_error (_("RSA public exponent missing or larger than %d bits\n"),
727 : 32);
728 0 : err = gpg_error (GPG_ERR_BAD_PUBKEY);
729 0 : goto leave;
730 : }
731 :
732 : /* /\* Store them. *\/ */
733 : /* err = verify_pin (app, 0, NULL, pincb, pincb_arg); */
734 : /* if (err) */
735 : /* goto leave; */
736 :
737 : /* Send the MSE:Store_Public_Key. */
738 0 : err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
739 : /* mse = xtrymalloc (1000); */
740 :
741 : /* mse[0] = 0x80; /\* Algorithm reference. *\/ */
742 : /* mse[1] = 1; */
743 : /* mse[2] = 0x17; */
744 : /* mse[3] = 0x84; /\* Private key reference. *\/ */
745 : /* mse[4] = 1; */
746 : /* mse[5] = 0x77; */
747 : /* mse[6] = 0x7F; /\* Public key parameter. *\/ */
748 : /* mse[7] = 0x49; */
749 : /* mse[8] = 0x81; */
750 : /* mse[9] = 3 + 0x80 + 2 + rsa_e_len; */
751 : /* mse[10] = 0x81; /\* RSA modulus of 128 byte. *\/ */
752 : /* mse[11] = 0x81; */
753 : /* mse[12] = rsa_n_len; */
754 : /* memcpy (mse+12, rsa_n, rsa_n_len); */
755 : /* mse[10] = 0x82; /\* RSA public exponent of up to 4 bytes. *\/ */
756 : /* mse[12] = rsa_e_len; */
757 : /* memcpy (mse+12, rsa_e, rsa_e_len); */
758 : /* err = iso7816_manage_security_env (app->slot, 0x81, 0xB6, */
759 : /* mse, sizeof mse); */
760 :
761 : leave:
762 0 : return err;
763 : }
764 :
765 :
766 : static gpg_error_t
767 0 : basic_pin_checks (const char *pinvalue, int minlen, int maxlen)
768 : {
769 0 : if (strlen (pinvalue) < minlen)
770 : {
771 0 : log_error ("PIN is too short; minimum length is %d\n", minlen);
772 0 : return gpg_error (GPG_ERR_BAD_PIN);
773 : }
774 0 : if (strlen (pinvalue) > maxlen)
775 : {
776 0 : log_error ("PIN is too large; maximum length is %d\n", maxlen);
777 0 : return gpg_error (GPG_ERR_BAD_PIN);
778 : }
779 0 : return 0;
780 : }
781 :
782 :
783 : /* Verify the PIN if required. */
784 : static gpg_error_t
785 0 : verify_pin (app_t app, int pwid, const char *desc,
786 : gpg_error_t (*pincb)(void*, const char *, char **),
787 : void *pincb_arg)
788 : {
789 : pininfo_t pininfo;
790 : int rc;
791 :
792 0 : if (!desc)
793 0 : desc = "PIN";
794 :
795 0 : memset (&pininfo, 0, sizeof pininfo);
796 0 : pininfo.fixedlen = -1;
797 0 : pininfo.minlen = 6;
798 0 : pininfo.maxlen = 16;
799 :
800 0 : if (!opt.disable_pinpad
801 0 : && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
802 : {
803 0 : rc = pincb (pincb_arg, desc, NULL);
804 0 : if (rc)
805 : {
806 0 : log_info (_("PIN callback returned error: %s\n"),
807 : gpg_strerror (rc));
808 0 : return rc;
809 : }
810 :
811 0 : rc = iso7816_verify_kp (app->slot, pwid, &pininfo);
812 0 : pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */
813 : }
814 : else
815 : {
816 : char *pinvalue;
817 :
818 0 : rc = pincb (pincb_arg, desc, &pinvalue);
819 0 : if (rc)
820 : {
821 0 : log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
822 0 : return rc;
823 : }
824 :
825 0 : rc = basic_pin_checks (pinvalue, pininfo.minlen, pininfo.maxlen);
826 0 : if (rc)
827 : {
828 0 : xfree (pinvalue);
829 0 : return rc;
830 : }
831 :
832 0 : rc = iso7816_verify (app->slot, pwid, pinvalue, strlen (pinvalue));
833 0 : xfree (pinvalue);
834 : }
835 :
836 0 : if (rc)
837 : {
838 0 : if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
839 0 : log_error (_("the NullPIN has not yet been changed\n"));
840 : else
841 0 : log_error ("verify PIN failed\n");
842 0 : return rc;
843 : }
844 :
845 0 : return 0;
846 : }
847 :
848 :
849 : /* Create the signature and return the allocated result in OUTDATA.
850 : If a PIN is required the PINCB will be used to ask for the PIN;
851 : that callback should return the PIN in an allocated buffer and
852 : store that in the 3rd argument. */
853 : static gpg_error_t
854 0 : do_sign (app_t app, const char *keyidstr, int hashalgo,
855 : gpg_error_t (*pincb)(void*, const char *, char **),
856 : void *pincb_arg,
857 : const void *indata, size_t indatalen,
858 : unsigned char **outdata, size_t *outdatalen )
859 : {
860 : static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
861 : { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
862 : 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
863 : static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
864 : { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
865 : 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
866 : int rc, i;
867 0 : int is_sigg = 0;
868 : int fid;
869 : unsigned char kid;
870 : unsigned char data[83]; /* Must be large enough for a SHA-1 digest
871 : + the largest OID prefix. */
872 : size_t datalen;
873 :
874 0 : if (!keyidstr || !*keyidstr)
875 0 : return gpg_error (GPG_ERR_INV_VALUE);
876 0 : switch (indatalen)
877 : {
878 0 : case 16: case 20: case 35: case 47: case 51: case 67: case 83: break;
879 0 : default: return gpg_error (GPG_ERR_INV_VALUE);
880 : }
881 :
882 : /* Check that the provided ID is valid. This is not really needed
883 : but we do it to enforce correct usage by the caller. */
884 0 : if (!strncmp (keyidstr, "NKS-NKS3.", 9) )
885 : ;
886 0 : else if (!strncmp (keyidstr, "NKS-DF01.", 9) )
887 : ;
888 0 : else if (!strncmp (keyidstr, "NKS-SIGG.", 9) )
889 0 : is_sigg = 1;
890 : else
891 0 : return gpg_error (GPG_ERR_INV_ID);
892 0 : keyidstr += 9;
893 :
894 0 : rc = switch_application (app, is_sigg);
895 0 : if (rc)
896 0 : return rc;
897 :
898 0 : if (is_sigg && app->app_local->sigg_is_msig)
899 : {
900 0 : log_info ("mass signature cards are not allowed\n");
901 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
902 : }
903 :
904 0 : if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
905 0 : || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
906 0 : || keyidstr[4])
907 0 : return gpg_error (GPG_ERR_INV_ID);
908 0 : fid = xtoi_4 (keyidstr);
909 0 : for (i=0; filelist[i].fid; i++)
910 0 : if (filelist[i].iskeypair && filelist[i].fid == fid)
911 0 : break;
912 0 : if (!filelist[i].fid)
913 0 : return gpg_error (GPG_ERR_NOT_FOUND);
914 0 : if (!filelist[i].issignkey)
915 0 : return gpg_error (GPG_ERR_INV_ID);
916 0 : kid = filelist[i].kid;
917 :
918 : /* Prepare the DER object from INDATA. */
919 0 : if (app->app_local->nks_version > 2 && (indatalen == 35
920 0 : || indatalen == 47
921 0 : || indatalen == 51
922 0 : || indatalen == 67
923 0 : || indatalen == 83))
924 : {
925 : /* The caller send data matching the length of the ASN.1 encoded
926 : hash for SHA-{1,224,256,384,512}. Assume that is okay. */
927 0 : assert (indatalen <= sizeof data);
928 0 : memcpy (data, indata, indatalen);
929 0 : datalen = indatalen;
930 : }
931 0 : else if (indatalen == 35)
932 : {
933 : /* Alright, the caller was so kind to send us an already
934 : prepared DER object. This is for TCOS 2. */
935 0 : if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15))
936 : ;
937 0 : else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata,rmd160_prefix,15))
938 : ;
939 : else
940 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
941 0 : memcpy (data, indata, indatalen);
942 0 : datalen = 35;
943 : }
944 0 : else if (indatalen == 20)
945 : {
946 0 : if (hashalgo == GCRY_MD_SHA1)
947 0 : memcpy (data, sha1_prefix, 15);
948 0 : else if (hashalgo == GCRY_MD_RMD160)
949 0 : memcpy (data, rmd160_prefix, 15);
950 : else
951 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
952 0 : memcpy (data+15, indata, indatalen);
953 0 : datalen = 35;
954 : }
955 : else
956 0 : return gpg_error (GPG_ERR_INV_VALUE);
957 :
958 :
959 : /* Send an MSE for PSO:Computer_Signature. */
960 0 : if (app->app_local->nks_version > 2)
961 : {
962 : unsigned char mse[6];
963 :
964 0 : mse[0] = 0x80; /* Algorithm reference. */
965 0 : mse[1] = 1;
966 0 : mse[2] = 2; /* RSA, card does pkcs#1 v1.5 padding, no ASN.1 check. */
967 0 : mse[3] = 0x84; /* Private key reference. */
968 0 : mse[4] = 1;
969 0 : mse[5] = kid;
970 0 : rc = iso7816_manage_security_env (app->slot, 0x41, 0xB6,
971 : mse, sizeof mse);
972 : }
973 : /* Verify using PW1.CH. */
974 0 : if (!rc)
975 0 : rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
976 : /* Compute the signature. */
977 0 : if (!rc)
978 0 : rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0,
979 : outdata, outdatalen);
980 0 : return rc;
981 : }
982 :
983 :
984 :
985 : /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
986 : If a PIN is required the PINCB will be used to ask for the PIN; it
987 : should return the PIN in an allocated buffer and put it into PIN. */
988 : static gpg_error_t
989 0 : do_decipher (app_t app, const char *keyidstr,
990 : gpg_error_t (*pincb)(void*, const char *, char **),
991 : void *pincb_arg,
992 : const void *indata, size_t indatalen,
993 : unsigned char **outdata, size_t *outdatalen,
994 : unsigned int *r_info)
995 : {
996 : int rc, i;
997 0 : int is_sigg = 0;
998 : int fid;
999 : int kid;
1000 :
1001 : (void)r_info;
1002 :
1003 0 : if (!keyidstr || !*keyidstr || !indatalen)
1004 0 : return gpg_error (GPG_ERR_INV_VALUE);
1005 :
1006 : /* Check that the provided ID is valid. This is not really needed
1007 : but we do it to to enforce correct usage by the caller. */
1008 0 : if (!strncmp (keyidstr, "NKS-NKS3.", 9) )
1009 : ;
1010 0 : else if (!strncmp (keyidstr, "NKS-DF01.", 9) )
1011 : ;
1012 0 : else if (!strncmp (keyidstr, "NKS-SIGG.", 9) )
1013 0 : is_sigg = 1;
1014 : else
1015 0 : return gpg_error (GPG_ERR_INV_ID);
1016 0 : keyidstr += 9;
1017 :
1018 0 : rc = switch_application (app, is_sigg);
1019 0 : if (rc)
1020 0 : return rc;
1021 :
1022 0 : if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1)
1023 0 : || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3)
1024 0 : || keyidstr[4])
1025 0 : return gpg_error (GPG_ERR_INV_ID);
1026 0 : fid = xtoi_4 (keyidstr);
1027 0 : for (i=0; filelist[i].fid; i++)
1028 0 : if (filelist[i].iskeypair && filelist[i].fid == fid)
1029 0 : break;
1030 0 : if (!filelist[i].fid)
1031 0 : return gpg_error (GPG_ERR_NOT_FOUND);
1032 0 : if (!filelist[i].isenckey)
1033 0 : return gpg_error (GPG_ERR_INV_ID);
1034 0 : kid = filelist[i].kid;
1035 :
1036 0 : if (app->app_local->nks_version > 2)
1037 : {
1038 : unsigned char mse[6];
1039 0 : mse[0] = 0x80; /* Algorithm reference. */
1040 0 : mse[1] = 1;
1041 0 : mse[2] = 0x0a; /* RSA no padding. (0x1A is pkcs#1.5 padding.) */
1042 0 : mse[3] = 0x84; /* Private key reference. */
1043 0 : mse[4] = 1;
1044 0 : mse[5] = kid;
1045 0 : rc = iso7816_manage_security_env (app->slot, 0x41, 0xB8,
1046 : mse, sizeof mse);
1047 : }
1048 : else
1049 : {
1050 : static const unsigned char mse[] =
1051 : {
1052 : 0x80, 1, 0x10, /* Select algorithm RSA. */
1053 : 0x84, 1, 0x81 /* Select local secret key 1 for decryption. */
1054 : };
1055 0 : rc = iso7816_manage_security_env (app->slot, 0xC1, 0xB8,
1056 : mse, sizeof mse);
1057 :
1058 : }
1059 :
1060 0 : if (!rc)
1061 0 : rc = verify_pin (app, 0, NULL, pincb, pincb_arg);
1062 :
1063 : /* Note that we need to use extended length APDUs for TCOS 3 cards.
1064 : Command chaining does not work. */
1065 0 : if (!rc)
1066 0 : rc = iso7816_decipher (app->slot, app->app_local->nks_version > 2? 1:0,
1067 : indata, indatalen, 0, 0x81,
1068 : outdata, outdatalen);
1069 0 : return rc;
1070 : }
1071 :
1072 :
1073 :
1074 : /* Parse a password ID string. Returns NULL on error or a string
1075 : suitable as passphrase prompt on success. On success stores the
1076 : reference value for the password at R_PWID and a flag indicating
1077 : that the SigG application is to be used at R_SIGG. If NEW_MODE is
1078 : true, the returned description is suitable for a new Password.
1079 : Supported values for PWIDSTR are:
1080 :
1081 : PW1.CH - Global password 1
1082 : PW2.CH - Global password 2
1083 : PW1.CH.SIG - SigG password 1
1084 : PW2.CH.SIG - SigG password 2
1085 : */
1086 : static const char *
1087 0 : parse_pwidstr (const char *pwidstr, int new_mode, int *r_sigg, int *r_pwid)
1088 : {
1089 : const char *desc;
1090 :
1091 0 : if (!pwidstr)
1092 0 : desc = NULL;
1093 0 : else if (!strcmp (pwidstr, "PW1.CH"))
1094 : {
1095 0 : *r_sigg = 0;
1096 0 : *r_pwid = 0x00;
1097 : /* TRANSLATORS: Do not translate the "|*|" prefixes but keep
1098 : them verbatim at the start of the string. */
1099 0 : desc = (new_mode
1100 : ? _("|N|Please enter a new PIN for the standard keys.")
1101 : : _("||Please enter the PIN for the standard keys."));
1102 : }
1103 0 : else if (!strcmp (pwidstr, "PW2.CH"))
1104 : {
1105 0 : *r_pwid = 0x01;
1106 0 : desc = (new_mode
1107 : ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
1108 : "for the standard keys.")
1109 : : _("|P|Please enter the PIN Unblocking Code (PUK) "
1110 : "for the standard keys."));
1111 : }
1112 0 : else if (!strcmp (pwidstr, "PW1.CH.SIG"))
1113 : {
1114 0 : *r_pwid = 0x81;
1115 0 : *r_sigg = 1;
1116 0 : desc = (new_mode
1117 : ? _("|N|Please enter a new PIN for the key to create "
1118 : "qualified signatures.")
1119 : : _("||Please enter the PIN for the key to create "
1120 : "qualified signatures."));
1121 : }
1122 0 : else if (!strcmp (pwidstr, "PW2.CH.SIG"))
1123 : {
1124 0 : *r_pwid = 0x83; /* Yes, that is 83 and not 82. */
1125 0 : *r_sigg = 1;
1126 0 : desc = (new_mode
1127 : ? _("|NP|Please enter a new PIN Unblocking Code (PUK) "
1128 : "for the key to create qualified signatures.")
1129 : : _("|P|Please enter the PIN Unblocking Code (PUK) "
1130 : "for the key to create qualified signatures."));
1131 : }
1132 : else
1133 : {
1134 0 : *r_pwid = 0; /* Only to avoid gcc warning in calling function. */
1135 0 : desc = NULL; /* Error. */
1136 : }
1137 :
1138 0 : return desc;
1139 : }
1140 :
1141 :
1142 : /* Handle the PASSWD command. See parse_pwidstr() for allowed values
1143 : for CHVNOSTR. */
1144 : static gpg_error_t
1145 0 : do_change_pin (app_t app, ctrl_t ctrl, const char *pwidstr,
1146 : unsigned int flags,
1147 : gpg_error_t (*pincb)(void*, const char *, char **),
1148 : void *pincb_arg)
1149 : {
1150 : gpg_error_t err;
1151 0 : char *newpin = NULL;
1152 0 : char *oldpin = NULL;
1153 : size_t newpinlen;
1154 : size_t oldpinlen;
1155 : int is_sigg;
1156 : const char *newdesc;
1157 : int pwid;
1158 : pininfo_t pininfo;
1159 :
1160 : (void)ctrl;
1161 :
1162 : /* The minimum length is enforced by TCOS, the maximum length is
1163 : just a reasonable value. */
1164 0 : memset (&pininfo, 0, sizeof pininfo);
1165 0 : pininfo.minlen = 6;
1166 0 : pininfo.maxlen = 16;
1167 :
1168 0 : newdesc = parse_pwidstr (pwidstr, 1, &is_sigg, &pwid);
1169 0 : if (!newdesc)
1170 0 : return gpg_error (GPG_ERR_INV_ID);
1171 :
1172 0 : err = switch_application (app, is_sigg);
1173 0 : if (err)
1174 0 : return err;
1175 :
1176 0 : if ((flags & APP_CHANGE_FLAG_NULLPIN))
1177 : {
1178 : /* With the nullpin flag, we do not verify the PIN - it would
1179 : fail if the Nullpin is still set. */
1180 0 : oldpin = xtrycalloc (1, 6);
1181 0 : if (!oldpin)
1182 : {
1183 0 : err = gpg_error_from_syserror ();
1184 0 : goto leave;
1185 : }
1186 0 : oldpinlen = 6;
1187 : }
1188 : else
1189 : {
1190 : const char *desc;
1191 : int dummy1, dummy2;
1192 :
1193 0 : if ((flags & APP_CHANGE_FLAG_RESET))
1194 : {
1195 : /* Reset mode: Ask for the alternate PIN. */
1196 : const char *altpwidstr;
1197 :
1198 0 : if (!strcmp (pwidstr, "PW1.CH"))
1199 0 : altpwidstr = "PW2.CH";
1200 0 : else if (!strcmp (pwidstr, "PW2.CH"))
1201 0 : altpwidstr = "PW1.CH";
1202 0 : else if (!strcmp (pwidstr, "PW1.CH.SIG"))
1203 0 : altpwidstr = "PW2.CH.SIG";
1204 0 : else if (!strcmp (pwidstr, "PW2.CH.SIG"))
1205 0 : altpwidstr = "PW1.CH.SIG";
1206 : else
1207 : {
1208 0 : err = gpg_error (GPG_ERR_BUG);
1209 0 : goto leave;
1210 : }
1211 0 : desc = parse_pwidstr (altpwidstr, 0, &dummy1, &dummy2);
1212 : }
1213 : else
1214 : {
1215 : /* Regular change mode: Ask for the old PIN. */
1216 0 : desc = parse_pwidstr (pwidstr, 0, &dummy1, &dummy2);
1217 : }
1218 0 : err = pincb (pincb_arg, desc, &oldpin);
1219 0 : if (err)
1220 : {
1221 0 : log_error ("error getting old PIN: %s\n", gpg_strerror (err));
1222 0 : goto leave;
1223 : }
1224 0 : oldpinlen = strlen (oldpin);
1225 0 : err = basic_pin_checks (oldpin, pininfo.minlen, pininfo.maxlen);
1226 0 : if (err)
1227 0 : goto leave;
1228 : }
1229 :
1230 0 : err = pincb (pincb_arg, newdesc, &newpin);
1231 0 : if (err)
1232 : {
1233 0 : log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
1234 0 : goto leave;
1235 : }
1236 0 : newpinlen = strlen (newpin);
1237 :
1238 0 : err = basic_pin_checks (newpin, pininfo.minlen, pininfo.maxlen);
1239 0 : if (err)
1240 0 : goto leave;
1241 :
1242 0 : if ((flags & APP_CHANGE_FLAG_RESET))
1243 : {
1244 : char *data;
1245 0 : size_t datalen = oldpinlen + newpinlen;
1246 :
1247 0 : data = xtrymalloc (datalen);
1248 0 : if (!data)
1249 : {
1250 0 : err = gpg_error_from_syserror ();
1251 0 : goto leave;
1252 : }
1253 0 : memcpy (data, oldpin, oldpinlen);
1254 0 : memcpy (data+oldpinlen, newpin, newpinlen);
1255 0 : err = iso7816_reset_retry_counter_with_rc (app->slot, pwid,
1256 : data, datalen);
1257 0 : wipememory (data, datalen);
1258 0 : xfree (data);
1259 : }
1260 : else
1261 0 : err = iso7816_change_reference_data (app->slot, pwid,
1262 : oldpin, oldpinlen,
1263 : newpin, newpinlen);
1264 : leave:
1265 0 : xfree (oldpin);
1266 0 : xfree (newpin);
1267 0 : return err;
1268 : }
1269 :
1270 :
1271 : /* Perform a simple verify operation. KEYIDSTR should be NULL or empty. */
1272 : static gpg_error_t
1273 0 : do_check_pin (app_t app, const char *pwidstr,
1274 : gpg_error_t (*pincb)(void*, const char *, char **),
1275 : void *pincb_arg)
1276 : {
1277 : gpg_error_t err;
1278 : int pwid;
1279 : int is_sigg;
1280 : const char *desc;
1281 :
1282 0 : desc = parse_pwidstr (pwidstr, 0, &is_sigg, &pwid);
1283 0 : if (!desc)
1284 0 : return gpg_error (GPG_ERR_INV_ID);
1285 :
1286 0 : err = switch_application (app, is_sigg);
1287 0 : if (err)
1288 0 : return err;
1289 :
1290 0 : return verify_pin (app, pwid, desc, pincb, pincb_arg);
1291 : }
1292 :
1293 :
1294 : /* Return the version of the NKS application. */
1295 : static int
1296 0 : get_nks_version (int slot)
1297 : {
1298 0 : unsigned char *result = NULL;
1299 : size_t resultlen;
1300 : int type;
1301 :
1302 0 : if (iso7816_apdu_direct (slot, "\x80\xaa\x06\x00\x00", 5, 0,
1303 : &result, &resultlen))
1304 0 : return 2; /* NKS 2 does not support this command. */
1305 :
1306 : /* Example value: 04 11 19 22 21 6A 20 80 03 03 01 01 01 00 00 00
1307 : vv tt ccccccccccccccccc aa bb cc vvvvvvvvvvv xx
1308 : vendor (Philips) -+ | | | | | | |
1309 : chip type -----------+ | | | | | |
1310 : chip id ----------------+ | | | | |
1311 : card type (3 - tcos 3) -------------------+ | | | |
1312 : OS version of card type ---------------------+ | | |
1313 : OS release of card type ------------------------+ | |
1314 : OS vendor internal version ------------------------+ |
1315 : RFU -----------------------------------------------------------+
1316 : */
1317 0 : if (resultlen < 16)
1318 0 : type = 0; /* Invalid data returned. */
1319 : else
1320 0 : type = result[8];
1321 0 : xfree (result);
1322 :
1323 0 : return type;
1324 : }
1325 :
1326 :
1327 : /* If ENABLE_SIGG is true switch to the SigG application if not yet
1328 : active. If false switch to the NKS application if not yet active.
1329 : Returns 0 on success. */
1330 : static gpg_error_t
1331 0 : switch_application (app_t app, int enable_sigg)
1332 : {
1333 : gpg_error_t err;
1334 :
1335 0 : if (((app->app_local->sigg_active && enable_sigg)
1336 0 : || (!app->app_local->sigg_active && !enable_sigg))
1337 0 : && !app->app_local->need_app_select)
1338 0 : return 0; /* Already switched. */
1339 :
1340 0 : log_info ("app-nks: switching to %s\n", enable_sigg? "SigG":"NKS");
1341 0 : if (enable_sigg)
1342 0 : err = iso7816_select_application (app->slot, aid_sigg, sizeof aid_sigg, 0);
1343 : else
1344 0 : err = iso7816_select_application (app->slot, aid_nks, sizeof aid_nks, 0);
1345 :
1346 0 : if (!err && enable_sigg && app->app_local->nks_version >= 3
1347 0 : && !app->app_local->sigg_msig_checked)
1348 : {
1349 : /* Check whether this card is a mass signature card. */
1350 : unsigned char *buffer;
1351 : size_t buflen;
1352 : const unsigned char *tmpl;
1353 : size_t tmpllen;
1354 :
1355 0 : app->app_local->sigg_msig_checked = 1;
1356 0 : app->app_local->sigg_is_msig = 1;
1357 0 : err = iso7816_select_file (app->slot, 0x5349, 0, NULL, NULL);
1358 0 : if (!err)
1359 0 : err = iso7816_read_record (app->slot, 1, 1, 0, &buffer, &buflen);
1360 0 : if (!err)
1361 : {
1362 0 : tmpl = find_tlv (buffer, buflen, 0x7a, &tmpllen);
1363 0 : if (tmpl && tmpllen == 12
1364 0 : && !memcmp (tmpl,
1365 : "\x93\x02\x00\x01\xA4\x06\x83\x01\x81\x83\x01\x83",
1366 : 12))
1367 0 : app->app_local->sigg_is_msig = 0;
1368 0 : xfree (buffer);
1369 : }
1370 0 : if (app->app_local->sigg_is_msig)
1371 0 : log_info ("This is a mass signature card\n");
1372 : }
1373 :
1374 0 : if (!err)
1375 : {
1376 0 : app->app_local->need_app_select = 0;
1377 0 : app->app_local->sigg_active = enable_sigg;
1378 : }
1379 : else
1380 0 : log_error ("app-nks: error switching to %s: %s\n",
1381 : enable_sigg? "SigG":"NKS", gpg_strerror (err));
1382 :
1383 0 : return err;
1384 : }
1385 :
1386 :
1387 : /* Select the NKS application. */
1388 : gpg_error_t
1389 0 : app_select_nks (app_t app)
1390 : {
1391 0 : int slot = app->slot;
1392 : int rc;
1393 :
1394 0 : rc = iso7816_select_application (slot, aid_nks, sizeof aid_nks, 0);
1395 0 : if (!rc)
1396 : {
1397 0 : app->apptype = "NKS";
1398 :
1399 0 : app->app_local = xtrycalloc (1, sizeof *app->app_local);
1400 0 : if (!app->app_local)
1401 : {
1402 0 : rc = gpg_error (gpg_err_code_from_errno (errno));
1403 0 : goto leave;
1404 : }
1405 :
1406 0 : app->app_local->nks_version = get_nks_version (slot);
1407 0 : if (opt.verbose)
1408 0 : log_info ("Detected NKS version: %d\n", app->app_local->nks_version);
1409 :
1410 0 : app->fnc.deinit = do_deinit;
1411 0 : app->fnc.learn_status = do_learn_status;
1412 0 : app->fnc.readcert = do_readcert;
1413 0 : app->fnc.readkey = do_readkey;
1414 0 : app->fnc.getattr = do_getattr;
1415 0 : app->fnc.setattr = NULL;
1416 0 : app->fnc.writekey = do_writekey;
1417 0 : app->fnc.genkey = NULL;
1418 0 : app->fnc.sign = do_sign;
1419 0 : app->fnc.auth = NULL;
1420 0 : app->fnc.decipher = do_decipher;
1421 0 : app->fnc.change_pin = do_change_pin;
1422 0 : app->fnc.check_pin = do_check_pin;
1423 : }
1424 :
1425 : leave:
1426 0 : if (rc)
1427 0 : do_deinit (app);
1428 0 : return rc;
1429 : }
|