Line data Source code
1 : /* app.c - Application selection.
2 : * Copyright (C) 2003, 2004, 2005 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 : #include <config.h>
21 : #include <errno.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <npth.h>
26 :
27 : #include "scdaemon.h"
28 : #include "app-common.h"
29 : #include "iso7816.h"
30 : #include "apdu.h"
31 : #include "tlv.h"
32 :
33 : /* This table is used to keep track of locks on a per reader base.
34 : The index into the table is the slot number of the reader. The
35 : mutex will be initialized on demand (one of the advantages of a
36 : userland threading system). */
37 : static struct
38 : {
39 : int initialized;
40 : npth_mutex_t lock;
41 : app_t app; /* Application context in use or NULL. */
42 : app_t last_app; /* Last application object used as this slot or NULL. */
43 : } lock_table[10];
44 :
45 :
46 :
47 : static void deallocate_app (app_t app);
48 :
49 :
50 :
51 : static void
52 0 : print_progress_line (void *opaque, const char *what, int pc, int cur, int tot)
53 : {
54 0 : ctrl_t ctrl = opaque;
55 : char line[100];
56 :
57 0 : if (ctrl)
58 : {
59 0 : snprintf (line, sizeof line, "%s %c %d %d", what, pc, cur, tot);
60 0 : send_status_direct (ctrl, "PROGRESS", line);
61 : }
62 0 : }
63 :
64 :
65 : /* Lock the reader SLOT. This function shall be used right before
66 : calling any of the actual application functions to serialize access
67 : to the reader. We do this always even if the reader is not
68 : actually used. This allows an actual connection to assume that it
69 : never shares a reader (while performing one command). Returns 0 on
70 : success; only then the unlock_reader function must be called after
71 : returning from the handler. */
72 : static gpg_error_t
73 0 : lock_reader (int slot, ctrl_t ctrl)
74 : {
75 : int res;
76 :
77 0 : if (slot < 0 || slot >= DIM (lock_table))
78 0 : return gpg_error (slot<0? GPG_ERR_INV_VALUE : GPG_ERR_RESOURCE_LIMIT);
79 :
80 0 : if (!lock_table[slot].initialized)
81 : {
82 0 : res = npth_mutex_init (&lock_table[slot].lock, NULL);
83 0 : if (res)
84 : {
85 0 : log_error ("error initializing mutex: %s\n", strerror (res));
86 0 : return gpg_error_from_errno (res);
87 : }
88 0 : lock_table[slot].initialized = 1;
89 0 : lock_table[slot].app = NULL;
90 0 : lock_table[slot].last_app = NULL;
91 : }
92 :
93 0 : res = npth_mutex_lock (&lock_table[slot].lock);
94 0 : if (res)
95 : {
96 0 : log_error ("failed to acquire APP lock for slot %d: %s\n",
97 : slot, strerror (res));
98 0 : return gpg_error_from_errno (res);
99 : }
100 :
101 0 : apdu_set_progress_cb (slot, print_progress_line, ctrl);
102 :
103 0 : return 0;
104 : }
105 :
106 : /* Release a lock on the reader. See lock_reader(). */
107 : static void
108 0 : unlock_reader (int slot)
109 : {
110 : int res;
111 :
112 0 : if (slot < 0 || slot >= DIM (lock_table)
113 0 : || !lock_table[slot].initialized)
114 0 : log_bug ("unlock_reader called for invalid slot %d\n", slot);
115 :
116 0 : apdu_set_progress_cb (slot, NULL, NULL);
117 :
118 0 : res = npth_mutex_unlock (&lock_table[slot].lock);
119 0 : if (res)
120 0 : log_error ("failed to release APP lock for slot %d: %s\n",
121 : slot, strerror (res));
122 0 : }
123 :
124 :
125 : /* This function may be called to print information pertaining to the
126 : current state of this module to the log. */
127 : void
128 0 : app_dump_state (void)
129 : {
130 : int slot;
131 :
132 0 : for (slot=0; slot < DIM (lock_table); slot++)
133 0 : if (lock_table[slot].initialized)
134 : {
135 0 : log_info ("app_dump_state: slot=%d", slot);
136 0 : if (lock_table[slot].app)
137 : {
138 0 : log_printf (" app=%p", lock_table[slot].app);
139 0 : if (lock_table[slot].app->apptype)
140 0 : log_printf (" type='%s'", lock_table[slot].app->apptype);
141 : }
142 0 : if (lock_table[slot].last_app)
143 : {
144 0 : log_printf (" lastapp=%p", lock_table[slot].last_app);
145 0 : if (lock_table[slot].last_app->apptype)
146 0 : log_printf (" type='%s'", lock_table[slot].last_app->apptype);
147 : }
148 0 : log_printf ("\n");
149 : }
150 0 : }
151 :
152 : /* Check wether the application NAME is allowed. This does not mean
153 : we have support for it though. */
154 : static int
155 0 : is_app_allowed (const char *name)
156 : {
157 : strlist_t l;
158 :
159 0 : for (l=opt.disabled_applications; l; l = l->next)
160 0 : if (!strcmp (l->d, name))
161 0 : return 0; /* no */
162 0 : return 1; /* yes */
163 : }
164 :
165 :
166 : /* This may be called to tell this module about a removed or resetted card. */
167 : void
168 0 : application_notify_card_reset (int slot)
169 : {
170 : app_t app;
171 :
172 0 : if (slot < 0 || slot >= DIM (lock_table))
173 0 : return;
174 :
175 : /* FIXME: We are ignoring any error value here. */
176 0 : lock_reader (slot, NULL);
177 :
178 : /* Mark application as non-reusable. */
179 0 : if (lock_table[slot].app)
180 0 : lock_table[slot].app->no_reuse = 1;
181 :
182 : /* Deallocate a saved application for that slot, so that we won't
183 : try to reuse it. If there is no saved application, set a flag so
184 : that we won't save the current state. */
185 0 : app = lock_table[slot].last_app;
186 :
187 0 : if (app)
188 : {
189 0 : lock_table[slot].last_app = NULL;
190 0 : deallocate_app (app);
191 : }
192 0 : unlock_reader (slot);
193 : }
194 :
195 :
196 : /* This function is used by the serialno command to check for an
197 : application conflict which may appear if the serialno command is
198 : used to request a specific application and the connection has
199 : already done a select_application. */
200 : gpg_error_t
201 0 : check_application_conflict (ctrl_t ctrl, int slot, const char *name)
202 : {
203 : app_t app;
204 :
205 : (void)ctrl;
206 :
207 0 : if (slot < 0 || slot >= DIM (lock_table))
208 0 : return gpg_error (GPG_ERR_INV_VALUE);
209 :
210 0 : app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
211 0 : if (app && app->apptype && name)
212 0 : if ( ascii_strcasecmp (app->apptype, name))
213 0 : return gpg_error (GPG_ERR_CONFLICT);
214 0 : return 0;
215 : }
216 :
217 :
218 : /* If called with NAME as NULL, select the best fitting application
219 : and return a context; otherwise select the application with NAME
220 : and return a context. SLOT identifies the reader device. Returns
221 : an error code and stores NULL at R_APP if no application was found
222 : or no card is present. */
223 : gpg_error_t
224 0 : select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
225 : {
226 : gpg_error_t err;
227 0 : app_t app = NULL;
228 0 : unsigned char *result = NULL;
229 : size_t resultlen;
230 : int want_undefined;
231 :
232 : (void)ctrl;
233 :
234 0 : *r_app = NULL;
235 :
236 0 : want_undefined = (name && !strcmp (name, "undefined"));
237 :
238 0 : err = lock_reader (slot, ctrl);
239 0 : if (err)
240 0 : return err;
241 :
242 : /* First check whether we already have an application to share. */
243 0 : app = lock_table[slot].initialized ? lock_table[slot].app : NULL;
244 0 : if (app && name)
245 0 : if (!app->apptype || ascii_strcasecmp (app->apptype, name))
246 : {
247 0 : unlock_reader (slot);
248 0 : if (app->apptype)
249 0 : log_info ("application '%s' in use by reader %d - can't switch\n",
250 : app->apptype, slot);
251 0 : return gpg_error (GPG_ERR_CONFLICT);
252 : }
253 :
254 : /* Don't use a non-reusable marked application. */
255 0 : if (app && app->no_reuse)
256 : {
257 0 : unlock_reader (slot);
258 0 : log_info ("lingering application '%s' in use by reader %d"
259 : " - can't switch\n",
260 0 : app->apptype? app->apptype:"?", slot);
261 0 : return gpg_error (GPG_ERR_CONFLICT);
262 : }
263 :
264 : /* If we don't have an app, check whether we have a saved
265 : application for that slot. This is useful so that a card does
266 : not get reset even if only one session is using the card - this
267 : way the PIN cache and other cached data are preserved. */
268 0 : if (!app && lock_table[slot].initialized && lock_table[slot].last_app)
269 : {
270 0 : app = lock_table[slot].last_app;
271 0 : if (!name || (app->apptype && !ascii_strcasecmp (app->apptype, name)) )
272 : {
273 : /* Yes, we can reuse this application - either the caller
274 : requested an unspecific one or the requested one matches
275 : the saved one. */
276 0 : lock_table[slot].app = app;
277 0 : lock_table[slot].last_app = NULL;
278 : }
279 : else
280 : {
281 : /* No, this saved application can't be used - deallocate it. */
282 0 : lock_table[slot].last_app = NULL;
283 0 : deallocate_app (app);
284 0 : app = NULL;
285 : }
286 : }
287 :
288 : /* If we can reuse an application, bump the reference count and
289 : return it. */
290 0 : if (app)
291 : {
292 0 : if (app->slot != slot)
293 0 : log_bug ("slot mismatch %d/%d\n", app->slot, slot);
294 0 : app->slot = slot;
295 :
296 0 : app->ref_count++;
297 0 : *r_app = app;
298 0 : unlock_reader (slot);
299 0 : return 0; /* Okay: We share that one. */
300 : }
301 :
302 : /* Need to allocate a new one. */
303 0 : app = xtrycalloc (1, sizeof *app);
304 0 : if (!app)
305 : {
306 0 : err = gpg_error_from_syserror ();
307 0 : log_info ("error allocating context: %s\n", gpg_strerror (err));
308 0 : unlock_reader (slot);
309 0 : return err;
310 : }
311 0 : app->slot = slot;
312 :
313 :
314 : /* Fixme: We should now first check whether a card is at all
315 : present. */
316 :
317 : /* Try to read the GDO file first to get a default serial number.
318 : We skip this if the undefined application has been requested. */
319 0 : if (!want_undefined)
320 : {
321 0 : err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
322 0 : if (!err)
323 0 : err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
324 0 : if (!err)
325 0 : err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
326 0 : if (!err)
327 : {
328 : size_t n;
329 : const unsigned char *p;
330 :
331 0 : p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
332 0 : if (p)
333 0 : resultlen -= (p-result);
334 0 : if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
335 : {
336 : /* The object it does not fit into the buffer. This is an
337 : invalid encoding (or the buffer is too short. However, I
338 : have some test cards with such an invalid encoding and
339 : therefore I use this ugly workaround to return something
340 : I can further experiment with. */
341 0 : log_info ("enabling BMI testcard workaround\n");
342 0 : n--;
343 : }
344 :
345 0 : if (p && n <= resultlen)
346 : {
347 : /* The GDO file is pretty short, thus we simply reuse it for
348 : storing the serial number. */
349 0 : memmove (result, p, n);
350 0 : app->serialno = result;
351 0 : app->serialnolen = n;
352 0 : err = app_munge_serialno (app);
353 0 : if (err)
354 0 : goto leave;
355 : }
356 : else
357 0 : xfree (result);
358 0 : result = NULL;
359 : }
360 : }
361 :
362 : /* For certain error codes, there is no need to try more. */
363 0 : if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
364 0 : || gpg_err_code (err) == GPG_ERR_ENODEV)
365 : goto leave;
366 :
367 : /* Figure out the application to use. */
368 0 : if (want_undefined)
369 : {
370 : /* We switch to the "undefined" application only if explicitly
371 : requested. */
372 0 : app->apptype = "UNDEFINED";
373 0 : err = 0;
374 : }
375 : else
376 0 : err = gpg_error (GPG_ERR_NOT_FOUND);
377 :
378 0 : if (err && is_app_allowed ("openpgp")
379 0 : && (!name || !strcmp (name, "openpgp")))
380 0 : err = app_select_openpgp (app);
381 0 : if (err && is_app_allowed ("nks") && (!name || !strcmp (name, "nks")))
382 0 : err = app_select_nks (app);
383 0 : if (err && is_app_allowed ("p15") && (!name || !strcmp (name, "p15")))
384 0 : err = app_select_p15 (app);
385 0 : if (err && is_app_allowed ("geldkarte")
386 0 : && (!name || !strcmp (name, "geldkarte")))
387 0 : err = app_select_geldkarte (app);
388 0 : if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig")))
389 0 : err = app_select_dinsig (app);
390 0 : if (err && is_app_allowed ("sc-hsm") && (!name || !strcmp (name, "sc-hsm")))
391 0 : err = app_select_sc_hsm (app);
392 0 : if (err && name && gpg_err_code (err) != GPG_ERR_OBJ_TERM_STATE)
393 0 : err = gpg_error (GPG_ERR_NOT_SUPPORTED);
394 :
395 : leave:
396 0 : if (err)
397 : {
398 0 : if (name)
399 0 : log_info ("can't select application '%s': %s\n",
400 : name, gpg_strerror (err));
401 : else
402 0 : log_info ("no supported card application found: %s\n",
403 : gpg_strerror (err));
404 0 : xfree (app);
405 0 : unlock_reader (slot);
406 0 : return err;
407 : }
408 :
409 0 : app->ref_count = 1;
410 :
411 0 : lock_table[slot].app = app;
412 0 : *r_app = app;
413 0 : unlock_reader (slot);
414 0 : return 0;
415 : }
416 :
417 :
418 : char *
419 0 : get_supported_applications (void)
420 : {
421 0 : const char *list[] = {
422 : "openpgp",
423 : "nks",
424 : "p15",
425 : "geldkarte",
426 : "dinsig",
427 : "sc-hsm",
428 : /* Note: "undefined" is not listed here because it needs special
429 : treatment by the client. */
430 : NULL
431 : };
432 : int idx;
433 : size_t nbytes;
434 : char *buffer, *p;
435 :
436 0 : for (nbytes=1, idx=0; list[idx]; idx++)
437 0 : nbytes += strlen (list[idx]) + 1 + 1;
438 :
439 0 : buffer = xtrymalloc (nbytes);
440 0 : if (!buffer)
441 0 : return NULL;
442 :
443 0 : for (p=buffer, idx=0; list[idx]; idx++)
444 0 : if (is_app_allowed (list[idx]))
445 0 : p = stpcpy (stpcpy (p, list[idx]), ":\n");
446 0 : *p = 0;
447 :
448 0 : return buffer;
449 : }
450 :
451 :
452 : /* Deallocate the application. */
453 : static void
454 0 : deallocate_app (app_t app)
455 : {
456 0 : if (app->fnc.deinit)
457 : {
458 0 : app->fnc.deinit (app);
459 0 : app->fnc.deinit = NULL;
460 : }
461 :
462 0 : xfree (app->serialno);
463 0 : xfree (app);
464 0 : }
465 :
466 : /* Free the resources associated with the application APP. APP is
467 : allowed to be NULL in which case this is a no-op. Note that we are
468 : using reference counting to track the users of the application and
469 : actually deferring the deallocation to allow for a later reuse by
470 : a new connection. */
471 : void
472 0 : release_application (app_t app)
473 : {
474 : int slot;
475 :
476 0 : if (!app)
477 0 : return;
478 :
479 0 : if (!app->ref_count)
480 0 : log_bug ("trying to release an already released context\n");
481 0 : if (--app->ref_count)
482 0 : return;
483 :
484 : /* Move the reference to the application in the lock table. */
485 0 : slot = app->slot;
486 : /* FIXME: We are ignoring any error value. */
487 0 : lock_reader (slot, NULL);
488 0 : if (lock_table[slot].app != app)
489 : {
490 0 : unlock_reader (slot);
491 0 : log_bug ("app mismatch %p/%p\n", app, lock_table[slot].app);
492 : deallocate_app (app);
493 : return;
494 : }
495 :
496 0 : if (lock_table[slot].last_app)
497 0 : deallocate_app (lock_table[slot].last_app);
498 0 : if (app->no_reuse)
499 : {
500 : /* If we shall not re-use the application we can't save it for
501 : later use. */
502 0 : deallocate_app (app);
503 0 : lock_table[slot].last_app = NULL;
504 : }
505 : else
506 0 : lock_table[slot].last_app = lock_table[slot].app;
507 0 : lock_table[slot].app = NULL;
508 0 : unlock_reader (slot);
509 : }
510 :
511 :
512 :
513 : /* The serial number may need some cosmetics. Do it here. This
514 : function shall only be called once after a new serial number has
515 : been put into APP->serialno.
516 :
517 : Prefixes we use:
518 :
519 : FF 00 00 = For serial numbers starting with an FF
520 : FF 01 00 = Some german p15 cards return an empty serial number so the
521 : serial number from the EF(TokenInfo) is used instead.
522 : FF 7F 00 = No serialno.
523 :
524 : All other serial number not starting with FF are used as they are.
525 : */
526 : gpg_error_t
527 0 : app_munge_serialno (app_t app)
528 : {
529 0 : if (app->serialnolen && app->serialno[0] == 0xff)
530 0 : {
531 : /* The serial number starts with our special prefix. This
532 : requires that we put our default prefix "FF0000" in front. */
533 0 : unsigned char *p = xtrymalloc (app->serialnolen + 3);
534 0 : if (!p)
535 0 : return gpg_error_from_syserror ();
536 0 : memcpy (p, "\xff\0", 3);
537 0 : memcpy (p+3, app->serialno, app->serialnolen);
538 0 : app->serialnolen += 3;
539 0 : xfree (app->serialno);
540 0 : app->serialno = p;
541 : }
542 0 : else if (!app->serialnolen)
543 : {
544 0 : unsigned char *p = xtrymalloc (3);
545 0 : if (!p)
546 0 : return gpg_error_from_syserror ();
547 0 : memcpy (p, "\xff\x7f", 3);
548 0 : app->serialnolen = 3;
549 0 : xfree (app->serialno);
550 0 : app->serialno = p;
551 : }
552 0 : return 0;
553 : }
554 :
555 :
556 :
557 : /* Retrieve the serial number and the time of the last update of the
558 : card. The serial number is returned as a malloced string (hex
559 : encoded) in SERIAL and the time of update is returned in STAMP. If
560 : no update time is available the returned value is 0. Caller must
561 : free SERIAL unless the function returns an error. If STAMP is not
562 : of interest, NULL may be passed. */
563 : gpg_error_t
564 0 : app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp)
565 : {
566 : char *buf;
567 :
568 0 : if (!app || !serial)
569 0 : return gpg_error (GPG_ERR_INV_VALUE);
570 :
571 0 : *serial = NULL;
572 0 : if (stamp)
573 0 : *stamp = 0; /* not available */
574 :
575 0 : if (!app->serialnolen)
576 0 : buf = xtrystrdup ("FF7F00");
577 : else
578 0 : buf = bin2hex (app->serialno, app->serialnolen, NULL);
579 0 : if (!buf)
580 0 : return gpg_error_from_syserror ();
581 :
582 0 : *serial = buf;
583 0 : return 0;
584 : }
585 :
586 :
587 : /* Write out the application specifig status lines for the LEARN
588 : command. */
589 : gpg_error_t
590 0 : app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
591 : {
592 : gpg_error_t err;
593 :
594 0 : if (!app)
595 0 : return gpg_error (GPG_ERR_INV_VALUE);
596 0 : if (!app->ref_count)
597 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
598 0 : if (!app->fnc.learn_status)
599 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
600 :
601 : /* We do not send APPTYPE if only keypairinfo is requested. */
602 0 : if (app->apptype && !(flags & 1))
603 0 : send_status_info (ctrl, "APPTYPE",
604 : app->apptype, strlen (app->apptype), NULL, 0);
605 0 : err = lock_reader (app->slot, ctrl);
606 0 : if (err)
607 0 : return err;
608 0 : err = app->fnc.learn_status (app, ctrl, flags);
609 0 : unlock_reader (app->slot);
610 0 : return err;
611 : }
612 :
613 :
614 : /* Read the certificate with id CERTID (as returned by learn_status in
615 : the CERTINFO status lines) and return it in the freshly allocated
616 : buffer put into CERT and the length of the certificate put into
617 : CERTLEN. */
618 : gpg_error_t
619 0 : app_readcert (app_t app, const char *certid,
620 : unsigned char **cert, size_t *certlen)
621 : {
622 : gpg_error_t err;
623 :
624 0 : if (!app)
625 0 : return gpg_error (GPG_ERR_INV_VALUE);
626 0 : if (!app->ref_count)
627 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
628 0 : if (!app->fnc.readcert)
629 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
630 0 : err = lock_reader (app->slot, NULL/* FIXME*/);
631 0 : if (err)
632 0 : return err;
633 0 : err = app->fnc.readcert (app, certid, cert, certlen);
634 0 : unlock_reader (app->slot);
635 0 : return err;
636 : }
637 :
638 :
639 : /* Read the key with ID KEYID. On success a canonical encoded
640 : S-expression with the public key will get stored at PK and its
641 : length (for assertions) at PKLEN; the caller must release that
642 : buffer. On error NULL will be stored at PK and PKLEN and an error
643 : code returned.
644 :
645 : This function might not be supported by all applications. */
646 : gpg_error_t
647 0 : app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
648 : {
649 : gpg_error_t err;
650 :
651 0 : if (pk)
652 0 : *pk = NULL;
653 0 : if (pklen)
654 0 : *pklen = 0;
655 :
656 0 : if (!app || !keyid || !pk || !pklen)
657 0 : return gpg_error (GPG_ERR_INV_VALUE);
658 0 : if (!app->ref_count)
659 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
660 0 : if (!app->fnc.readkey)
661 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
662 0 : err = lock_reader (app->slot, NULL /*FIXME*/);
663 0 : if (err)
664 0 : return err;
665 0 : err= app->fnc.readkey (app, keyid, pk, pklen);
666 0 : unlock_reader (app->slot);
667 0 : return err;
668 : }
669 :
670 :
671 : /* Perform a GETATTR operation. */
672 : gpg_error_t
673 0 : app_getattr (app_t app, ctrl_t ctrl, const char *name)
674 : {
675 : gpg_error_t err;
676 :
677 0 : if (!app || !name || !*name)
678 0 : return gpg_error (GPG_ERR_INV_VALUE);
679 0 : if (!app->ref_count)
680 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
681 :
682 0 : if (app->apptype && name && !strcmp (name, "APPTYPE"))
683 : {
684 0 : send_status_info (ctrl, "APPTYPE",
685 : app->apptype, strlen (app->apptype), NULL, 0);
686 0 : return 0;
687 : }
688 0 : if (name && !strcmp (name, "SERIALNO"))
689 : {
690 : char *serial;
691 : time_t stamp;
692 : int rc;
693 :
694 0 : rc = app_get_serial_and_stamp (app, &serial, &stamp);
695 0 : if (rc)
696 0 : return rc;
697 0 : send_status_info (ctrl, "SERIALNO", serial, strlen (serial), NULL, 0);
698 0 : xfree (serial);
699 0 : return 0;
700 : }
701 :
702 0 : if (!app->fnc.getattr)
703 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
704 0 : err = lock_reader (app->slot, ctrl);
705 0 : if (err)
706 0 : return err;
707 0 : err = app->fnc.getattr (app, ctrl, name);
708 0 : unlock_reader (app->slot);
709 0 : return err;
710 : }
711 :
712 : /* Perform a SETATTR operation. */
713 : gpg_error_t
714 0 : app_setattr (app_t app, const char *name,
715 : gpg_error_t (*pincb)(void*, const char *, char **),
716 : void *pincb_arg,
717 : const unsigned char *value, size_t valuelen)
718 : {
719 : gpg_error_t err;
720 :
721 0 : if (!app || !name || !*name || !value)
722 0 : return gpg_error (GPG_ERR_INV_VALUE);
723 0 : if (!app->ref_count)
724 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
725 0 : if (!app->fnc.setattr)
726 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
727 0 : err = lock_reader (app->slot, NULL /*FIXME*/);
728 0 : if (err)
729 0 : return err;
730 0 : err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
731 0 : unlock_reader (app->slot);
732 0 : return err;
733 : }
734 :
735 : /* Create the signature and return the allocated result in OUTDATA.
736 : If a PIN is required the PINCB will be used to ask for the PIN; it
737 : should return the PIN in an allocated buffer and put it into PIN. */
738 : gpg_error_t
739 0 : app_sign (app_t app, const char *keyidstr, int hashalgo,
740 : gpg_error_t (*pincb)(void*, const char *, char **),
741 : void *pincb_arg,
742 : const void *indata, size_t indatalen,
743 : unsigned char **outdata, size_t *outdatalen )
744 : {
745 : gpg_error_t err;
746 :
747 0 : if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
748 0 : return gpg_error (GPG_ERR_INV_VALUE);
749 0 : if (!app->ref_count)
750 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
751 0 : if (!app->fnc.sign)
752 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
753 0 : err = lock_reader (app->slot, NULL /*FIXME*/);
754 0 : if (err)
755 0 : return err;
756 0 : err = app->fnc.sign (app, keyidstr, hashalgo,
757 : pincb, pincb_arg,
758 : indata, indatalen,
759 : outdata, outdatalen);
760 0 : unlock_reader (app->slot);
761 0 : if (opt.verbose)
762 0 : log_info ("operation sign result: %s\n", gpg_strerror (err));
763 0 : return err;
764 : }
765 :
766 : /* Create the signature using the INTERNAL AUTHENTICATE command and
767 : return the allocated result in OUTDATA. If a PIN is required the
768 : PINCB will be used to ask for the PIN; it should return the PIN in
769 : an allocated buffer and put it into PIN. */
770 : gpg_error_t
771 0 : app_auth (app_t app, const char *keyidstr,
772 : gpg_error_t (*pincb)(void*, const char *, char **),
773 : void *pincb_arg,
774 : const void *indata, size_t indatalen,
775 : unsigned char **outdata, size_t *outdatalen )
776 : {
777 : gpg_error_t err;
778 :
779 0 : if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
780 0 : return gpg_error (GPG_ERR_INV_VALUE);
781 0 : if (!app->ref_count)
782 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
783 0 : if (!app->fnc.auth)
784 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
785 0 : err = lock_reader (app->slot, NULL /*FIXME*/);
786 0 : if (err)
787 0 : return err;
788 0 : err = app->fnc.auth (app, keyidstr,
789 : pincb, pincb_arg,
790 : indata, indatalen,
791 : outdata, outdatalen);
792 0 : unlock_reader (app->slot);
793 0 : if (opt.verbose)
794 0 : log_info ("operation auth result: %s\n", gpg_strerror (err));
795 0 : return err;
796 : }
797 :
798 :
799 : /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
800 : If a PIN is required the PINCB will be used to ask for the PIN; it
801 : should return the PIN in an allocated buffer and put it into PIN. */
802 : gpg_error_t
803 0 : app_decipher (app_t app, const char *keyidstr,
804 : gpg_error_t (*pincb)(void*, const char *, char **),
805 : void *pincb_arg,
806 : const void *indata, size_t indatalen,
807 : unsigned char **outdata, size_t *outdatalen,
808 : unsigned int *r_info)
809 : {
810 : gpg_error_t err;
811 :
812 0 : *r_info = 0;
813 :
814 0 : if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
815 0 : return gpg_error (GPG_ERR_INV_VALUE);
816 0 : if (!app->ref_count)
817 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
818 0 : if (!app->fnc.decipher)
819 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
820 0 : err = lock_reader (app->slot, NULL /*FIXME*/);
821 0 : if (err)
822 0 : return err;
823 0 : err = app->fnc.decipher (app, keyidstr,
824 : pincb, pincb_arg,
825 : indata, indatalen,
826 : outdata, outdatalen,
827 : r_info);
828 0 : unlock_reader (app->slot);
829 0 : if (opt.verbose)
830 0 : log_info ("operation decipher result: %s\n", gpg_strerror (err));
831 0 : return err;
832 : }
833 :
834 :
835 : /* Perform the WRITECERT operation. */
836 : gpg_error_t
837 0 : app_writecert (app_t app, ctrl_t ctrl,
838 : const char *certidstr,
839 : gpg_error_t (*pincb)(void*, const char *, char **),
840 : void *pincb_arg,
841 : const unsigned char *data, size_t datalen)
842 : {
843 : gpg_error_t err;
844 :
845 0 : if (!app || !certidstr || !*certidstr || !pincb)
846 0 : return gpg_error (GPG_ERR_INV_VALUE);
847 0 : if (!app->ref_count)
848 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
849 0 : if (!app->fnc.writecert)
850 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
851 0 : err = lock_reader (app->slot, ctrl);
852 0 : if (err)
853 0 : return err;
854 0 : err = app->fnc.writecert (app, ctrl, certidstr,
855 : pincb, pincb_arg, data, datalen);
856 0 : unlock_reader (app->slot);
857 0 : if (opt.verbose)
858 0 : log_info ("operation writecert result: %s\n", gpg_strerror (err));
859 0 : return err;
860 : }
861 :
862 :
863 : /* Perform the WRITEKEY operation. */
864 : gpg_error_t
865 0 : app_writekey (app_t app, ctrl_t ctrl,
866 : const char *keyidstr, unsigned int flags,
867 : gpg_error_t (*pincb)(void*, const char *, char **),
868 : void *pincb_arg,
869 : const unsigned char *keydata, size_t keydatalen)
870 : {
871 : gpg_error_t err;
872 :
873 0 : if (!app || !keyidstr || !*keyidstr || !pincb)
874 0 : return gpg_error (GPG_ERR_INV_VALUE);
875 0 : if (!app->ref_count)
876 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
877 0 : if (!app->fnc.writekey)
878 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
879 0 : err = lock_reader (app->slot, ctrl);
880 0 : if (err)
881 0 : return err;
882 0 : err = app->fnc.writekey (app, ctrl, keyidstr, flags,
883 : pincb, pincb_arg, keydata, keydatalen);
884 0 : unlock_reader (app->slot);
885 0 : if (opt.verbose)
886 0 : log_info ("operation writekey result: %s\n", gpg_strerror (err));
887 0 : return err;
888 : }
889 :
890 :
891 : /* Perform a SETATTR operation. */
892 : gpg_error_t
893 0 : app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
894 : time_t createtime,
895 : gpg_error_t (*pincb)(void*, const char *, char **),
896 : void *pincb_arg)
897 : {
898 : gpg_error_t err;
899 :
900 0 : if (!app || !keynostr || !*keynostr || !pincb)
901 0 : return gpg_error (GPG_ERR_INV_VALUE);
902 0 : if (!app->ref_count)
903 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
904 0 : if (!app->fnc.genkey)
905 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
906 0 : err = lock_reader (app->slot, ctrl);
907 0 : if (err)
908 0 : return err;
909 0 : err = app->fnc.genkey (app, ctrl, keynostr, flags,
910 : createtime, pincb, pincb_arg);
911 0 : unlock_reader (app->slot);
912 0 : if (opt.verbose)
913 0 : log_info ("operation genkey result: %s\n", gpg_strerror (err));
914 0 : return err;
915 : }
916 :
917 :
918 : /* Perform a GET CHALLENGE operation. This fucntion is special as it
919 : directly accesses the card without any application specific
920 : wrapper. */
921 : gpg_error_t
922 0 : app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer)
923 : {
924 : gpg_error_t err;
925 :
926 0 : if (!app || !nbytes || !buffer)
927 0 : return gpg_error (GPG_ERR_INV_VALUE);
928 0 : if (!app->ref_count)
929 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
930 0 : err = lock_reader (app->slot, NULL /*FIXME*/);
931 0 : if (err)
932 0 : return err;
933 0 : err = iso7816_get_challenge (app->slot, nbytes, buffer);
934 0 : unlock_reader (app->slot);
935 0 : return err;
936 : }
937 :
938 :
939 :
940 : /* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation. */
941 : gpg_error_t
942 0 : app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
943 : gpg_error_t (*pincb)(void*, const char *, char **),
944 : void *pincb_arg)
945 : {
946 : gpg_error_t err;
947 :
948 0 : if (!app || !chvnostr || !*chvnostr || !pincb)
949 0 : return gpg_error (GPG_ERR_INV_VALUE);
950 0 : if (!app->ref_count)
951 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
952 0 : if (!app->fnc.change_pin)
953 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
954 0 : err = lock_reader (app->slot, ctrl);
955 0 : if (err)
956 0 : return err;
957 0 : err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode,
958 : pincb, pincb_arg);
959 0 : unlock_reader (app->slot);
960 0 : if (opt.verbose)
961 0 : log_info ("operation change_pin result: %s\n", gpg_strerror (err));
962 0 : return err;
963 : }
964 :
965 :
966 : /* Perform a VERIFY operation without doing anything lese. This may
967 : be used to initialze a the PIN cache for long lasting other
968 : operations. Its use is highly application dependent. */
969 : gpg_error_t
970 0 : app_check_pin (app_t app, const char *keyidstr,
971 : gpg_error_t (*pincb)(void*, const char *, char **),
972 : void *pincb_arg)
973 : {
974 : gpg_error_t err;
975 :
976 0 : if (!app || !keyidstr || !*keyidstr || !pincb)
977 0 : return gpg_error (GPG_ERR_INV_VALUE);
978 0 : if (!app->ref_count)
979 0 : return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
980 0 : if (!app->fnc.check_pin)
981 0 : return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
982 0 : err = lock_reader (app->slot, NULL /*FIXME*/);
983 0 : if (err)
984 0 : return err;
985 0 : err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);
986 0 : unlock_reader (app->slot);
987 0 : if (opt.verbose)
988 0 : log_info ("operation check_pin result: %s\n", gpg_strerror (err));
989 0 : return err;
990 : }
|