1 /* cardglue.c - mainly dispatcher for card related functions.
2 * Copyright (C) 2003, 2004, 2005, 2006, 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 #include <config.h>
21 #ifndef ENABLE_CARD_SUPPORT
22 #error not configured for card support.
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <stdarg.h>
29 #include <assert.h>
30 #include "options.h"
31 #include "packet.h"
32 #include "errors.h"
33 #include "memory.h"
34 #include "util.h"
35 #include "main.h"
36 #include "status.h"
37 #include "ttyio.h"
38 #include "i18n.h"
39
40 #include "cardglue.h"
41 #include "apdu.h"
42 #include "app-common.h"
43
44
45
46 struct ctrl_ctx_s
47 {
48 assuan_error_t (*status_cb)(void *opaque, const char *line);
49 void *status_cb_arg;
50 };
51
52
53 struct pincb_parm_s
54 {
55 const char *sn;
56 };
57
58
59 struct writekey_parm_s
60 {
61 assuan_context_t ctx;
62 const unsigned char *keydata;
63 size_t keydatalen;
64 };
65
66
67
68 static char *default_reader_port;
69 static app_t current_app;
70
71
72 /* Local prototypes. */
73 static assuan_error_t learn_status_cb (void *opaque, const char *line);
74
75
76 /* To avoid cluttering the code with bunches of ifdefs we use a few
77 dummy functions instead and defines. */
78 #ifndef ENABLE_AGENT_SUPPORT
79
80 #define ASSUAN_LINELENGTH 100
81
82 static assuan_context_t
agent_open(int try,const char * orig_codeset)83 agent_open (int try, const char *orig_codeset)
84 {
85 return NULL;
86 }
87
88 void
agent_close(assuan_context_t ctx)89 agent_close (assuan_context_t ctx)
90 {
91 }
92
93 const char *
assuan_strerror(assuan_error_t err)94 assuan_strerror (assuan_error_t err)
95 {
96 return "no Assuan support";
97 }
98
99 assuan_error_t
assuan_transact(assuan_context_t ctx,const char * command,assuan_error_t (* data_cb)(void *,const void *,size_t),void * data_cb_arg,assuan_error_t (* inquire_cb)(void *,const char *),void * inquire_cb_arg,assuan_error_t (* status_cb)(void *,const char *),void * status_cb_arg)100 assuan_transact (assuan_context_t ctx,
101 const char *command,
102 assuan_error_t (*data_cb)(void *, const void *, size_t),
103 void *data_cb_arg,
104 assuan_error_t (*inquire_cb)(void*, const char *),
105 void *inquire_cb_arg,
106 assuan_error_t (*status_cb)(void*, const char *),
107 void *status_cb_arg)
108 {
109 return 100; /* ASSUAN_NOT_IMPLEMENTED */
110 }
111 assuan_error_t
assuan_send_data(assuan_context_t ctx,const void * buffer,size_t length)112 assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
113 {
114 return 100; /* ASSUAN_NOT_IMPLEMENTED */
115 }
116 #endif /*!ENABLE_AGENT_SUPPORT*/
117
118
119 /* Create a serialno/fpr string from the serial number and the secret
120 key. caller must free the returned string. There is no error
121 return. [Taken from 1.9's keyid.c]*/
122 char *
serialno_and_fpr_from_sk(const unsigned char * sn,size_t snlen,PKT_secret_key * sk)123 serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
124 PKT_secret_key *sk)
125 {
126 unsigned char fpr[MAX_FINGERPRINT_LEN];
127 size_t fprlen;
128 char *buffer, *p;
129 int i;
130
131 fingerprint_from_sk (sk, fpr, &fprlen);
132 buffer = p = xmalloc (snlen*2 + 1 + fprlen*2 + 1);
133 for (i=0; i < snlen; i++, p+=2)
134 sprintf (p, "%02X", sn[i]);
135 *p++ = '/';
136 for (i=0; i < fprlen; i++, p+=2)
137 sprintf (p, "%02X", fpr[i]);
138 *p = 0;
139 return buffer;
140 }
141
142
143 /* Send a line with status information via assuan and escape all given
144 buffers. The variable elements are pairs of (char *, size_t),
145 terminated with a (NULL, 0). */
146 void
send_status_info(ctrl_t ctrl,const char * keyword,...)147 send_status_info (ctrl_t ctrl, const char *keyword, ...)
148 {
149 va_list arg_ptr;
150 const unsigned char *value;
151 size_t valuelen;
152 char buf[950], *p;
153 size_t n;
154
155 va_start (arg_ptr, keyword);
156
157 p = buf;
158 n = 0;
159 valuelen = strlen (keyword);
160 for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, keyword++)
161 *p++ = *keyword;
162
163 while ( (value = va_arg (arg_ptr, const unsigned char *)) )
164 {
165 valuelen = va_arg (arg_ptr, size_t);
166 if (!valuelen)
167 continue; /* empty buffer */
168 if (n)
169 {
170 *p++ = ' ';
171 n++;
172 }
173 for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
174 {
175 if (*value < ' ' || *value == '+')
176 {
177 sprintf (p, "%%%02X", *value);
178 p += 3;
179 }
180 else if (*value == ' ')
181 *p++ = '+';
182 else
183 *p++ = *value;
184 }
185 }
186 *p = 0;
187 if (ctrl && ctrl->status_cb)
188 ctrl->status_cb (ctrl->status_cb_arg, buf);
189
190 va_end (arg_ptr);
191 }
192
193 /* Send a ready formatted status line via assuan. */
194 void
send_status_direct(ctrl_t ctrl,const char * keyword,const char * args)195 send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
196 {
197 char buf[950];
198
199 if (strchr (args, '\n'))
200 log_error ("error: LF detected in status line - not sending\n");
201 else
202 {
203 snprintf (buf, sizeof buf, "%s%s%s",
204 keyword, args? " ":"", args? args:"");
205 if (ctrl && ctrl->status_cb)
206 ctrl->status_cb (ctrl->status_cb_arg, buf);
207 }
208 }
209
210
211
212 void
gcry_mpi_release(MPI a)213 gcry_mpi_release (MPI a)
214 {
215 mpi_free (a);
216 }
217
218 MPI
gcry_mpi_set_opaque(MPI a,void * p,unsigned int len)219 gcry_mpi_set_opaque (MPI a, void *p, unsigned int len)
220 {
221 return mpi_set_opaque (a, p, len);
222 }
223
224
225 /* Replacement function of the Libgcrypt onewhich is used in gnupg
226 1.9. Thus function computes the digest of ALGO from the data in
227 BUFFER of LENGTH. ALGO must be supported. */
228 void
gcry_md_hash_buffer(int algo,void * digest,const void * buffer,size_t length)229 gcry_md_hash_buffer (int algo, void *digest,
230 const void *buffer, size_t length)
231 {
232 MD_HANDLE h = md_open (algo, 0);
233 if (!h)
234 BUG();
235 md_write (h, (byte *) buffer, length);
236 md_final (h);
237 memcpy (digest, md_read (h, algo), md_digest_length (algo));
238 md_close (h);
239 }
240
241
242 /* This function simply returns the name of the algorithm or some
243 constant string when there is no algo. It will never return
244 NULL. */
245 const char *
gcry_md_algo_name(int algorithm)246 gcry_md_algo_name (int algorithm)
247 {
248 const char *s = digest_algo_to_string (algorithm);
249 return s ? s : "?";
250 }
251
252
253 /* This is a limited version of the one in 1.9 but it should be
254 sufficient here. */
255 void
log_printf(const char * fmt,...)256 log_printf (const char *fmt, ...)
257 {
258 va_list arg_ptr;
259
260 va_start (arg_ptr, fmt);
261 vfprintf (log_stream (), fmt, arg_ptr);
262 va_end (arg_ptr);
263 }
264
265
266
267 /* Print a hexdump of BUFFER. With TEXT of NULL print just the raw
268 dump, with TEXT just an empty string, print a trailing linefeed,
269 otherwise print an entire debug line. */
270 void
log_printhex(const char * text,const void * buffer,size_t length)271 log_printhex (const char *text, const void *buffer, size_t length)
272 {
273 if (text && *text)
274 log_debug ("%s ", text);
275 if (length)
276 {
277 const unsigned char *p = buffer;
278 log_printf ("%02X", *p);
279 for (length--, p++; length--; p++)
280 log_printf (" %02X", *p);
281 }
282 if (text)
283 log_printf ("\n");
284 }
285
286
287
288 void
app_set_default_reader_port(const char * portstr)289 app_set_default_reader_port (const char *portstr)
290 {
291 xfree (default_reader_port);
292 default_reader_port = portstr? xstrdup (portstr): NULL;
293 }
294
295
296 void
card_set_reader_port(const char * portstr)297 card_set_reader_port (const char *portstr)
298 {
299 app_set_default_reader_port (portstr);
300 }
301
302
303 /* Retrieve the serial number and the time of the last update of the
304 card. The serial number is returned as a malloced string (hex
305 encoded) in SERIAL and the time of update is returned in STAMP. If
306 no update time is available the returned value is 0. Caller must
307 free SERIAL unless the function returns an error. */
308 int
app_get_serial_and_stamp(app_t app,char ** serial,time_t * stamp)309 app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp)
310 {
311 unsigned char *buf, *p;
312 int i;
313
314 if (!app || !serial || !stamp)
315 return gpg_error (GPG_ERR_INV_VALUE);
316
317 *serial = NULL;
318 *stamp = 0; /* not available */
319
320 buf = xtrymalloc (app->serialnolen * 2 + 1);
321 if (!buf)
322 return gpg_error_from_errno (errno);
323 for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
324 sprintf (p, "%02X", app->serialno[i]);
325 *p = 0;
326 *serial = buf;
327 return 0;
328 }
329
330
331
332 /* Release the card info structure. */
333 void
agent_release_card_info(struct agent_card_info_s * info)334 agent_release_card_info (struct agent_card_info_s *info)
335 {
336 int i;
337
338 if (!info)
339 return;
340
341 xfree (info->serialno); info->serialno = NULL;
342 xfree (info->apptype); info->apptype = NULL;
343 xfree (info->disp_name); info->disp_name = NULL;
344 xfree (info->disp_lang); info->disp_lang = NULL;
345 xfree (info->pubkey_url); info->pubkey_url = NULL;
346 xfree (info->login_data); info->login_data = NULL;
347 info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
348 info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
349 for (i=0; i < 4; i++)
350 {
351 xfree (info->private_do[i]);
352 info->private_do[i] = NULL;
353 }
354 }
355
356
357 /* Print an error message for a failed assuan_transact and return a
358 gpg error code. No error is printed if RC is 0. */
359 static gpg_error_t
test_transact(int rc,const char * command)360 test_transact (int rc, const char *command)
361 {
362 if (!rc)
363 return 0;
364 log_error ("sending command `%s' to agent failed: %s\n",
365 command, assuan_strerror (rc));
366 return gpg_error (GPG_ERR_CARD);
367 }
368
369
370 /* Try to open a card using an already running agent. Prepare a
371 proper application context and return it. */
372 static app_t
open_card_via_agent(int * scd_available)373 open_card_via_agent (int *scd_available)
374 {
375 assuan_context_t ctx;
376 app_t app;
377 struct agent_card_info_s info;
378 int rc;
379
380 *scd_available = 0;
381 ctx = agent_open (1, NULL);
382 if (!ctx)
383 return NULL;
384
385 /* Request the serialnumber of the card. If we get
386 NOT_SUPPORTED or NO_SCDAEMON back, the gpg-agent either has
387 disabled scdaemon or it can't be used. We close the connection
388 in this case and use our own code. This may happen if just the
389 gpg-agent has been installed for the sake of passphrase
390 caching. */
391 memset (&info, 0, sizeof info);
392 rc = assuan_transact (ctx, "SCD SERIALNO openpgp",
393 NULL, NULL, NULL, NULL,
394 learn_status_cb, &info);
395 if (rc)
396 {
397 if ((rc & 0xffff) == 60 || (rc & 0xffff) == 119)
398 ; /* No scdaemon available to gpg-agent. */
399 else
400 {
401 write_status_text (STATUS_CARDCTRL, "4");
402 log_info ("selecting openpgp failed: %s\n", assuan_strerror (rc));
403 *scd_available = 1;
404 }
405 agent_release_card_info (&info);
406 agent_close (ctx);
407 return NULL;
408 }
409
410 app = xcalloc (1, sizeof *app);
411 app->assuan_ctx = ctx;
412
413 return app;
414 }
415
416
417
418 /* Open the current card and select the openpgp application. Return
419 an APP context handle to be used for further procesing or NULL on
420 error or if no OpenPGP application exists.*/
421 static app_t
open_card(void)422 open_card (void)
423 {
424 int slot = -1;
425 int rc;
426 app_t app;
427 int did_shutdown = 0;
428 int retry_count = 0;
429
430 /* First check whether we can contact a gpg-agent and divert all
431 operation to it. This is required because gpg as well as the
432 agent require exclusive access to the reader. */
433 if (opt.use_agent)
434 {
435 int scd_available;
436
437 app = open_card_via_agent (&scd_available);
438 if (app)
439 goto ready; /* Yes, there is a agent with a usable card, go that way. */
440 if (scd_available)
441 return NULL; /* Agent available but card problem. */
442 }
443
444
445 /* No agent or usable agent, thus we do it on our own. */
446 card_close ();
447
448 retry:
449 if (did_shutdown)
450 apdu_reset (slot);
451 else
452 {
453 slot = apdu_open_reader (default_reader_port);
454 if (slot == -1)
455 {
456 write_status_text (STATUS_CARDCTRL, "5");
457 log_error (_("card reader not available\n"));
458 return NULL;
459 }
460 }
461
462 app = xcalloc (1, sizeof *app);
463 app->slot = slot;
464 rc = app_select_openpgp (app);
465 if (opt.limit_card_insert_tries
466 && ++retry_count >= opt.limit_card_insert_tries)
467 ;
468 else if (rc && !opt.batch)
469 {
470 write_status_text (STATUS_CARDCTRL, "1");
471
472 did_shutdown = !!apdu_shutdown_reader (slot);
473
474 if ( cpr_get_answer_okay_cancel ("cardctrl.insert_card.okay",
475 _("Please insert the card and hit return or enter 'c' to cancel: "),
476 1) )
477 {
478 if (!did_shutdown)
479 apdu_close_reader (slot);
480 xfree (app);
481 goto retry;
482 }
483 }
484 if (rc)
485 {
486 write_status_text (STATUS_CARDCTRL, "4");
487 log_info (_("selecting openpgp failed: %s\n"), gpg_strerror (rc));
488 apdu_close_reader (slot);
489 xfree (app);
490 return NULL;
491 }
492
493 ready:
494 app->ref_count = 1;
495 current_app = app;
496 if (is_status_enabled () )
497 {
498 int i;
499 char *p, *buf;
500
501 buf = xmalloc (5 + app->serialnolen * 2 + 1);
502 p = stpcpy (buf, "3 ");
503 for (i=0; i < app->serialnolen; p +=2, i++)
504 sprintf (p, "%02X", app->serialno[i]);
505 write_status_text (STATUS_CARDCTRL, buf);
506 xfree (buf);
507 }
508
509 return app;
510 }
511
512
513 void
card_close(void)514 card_close (void)
515 {
516 if (current_app)
517 {
518 app_t app = current_app;
519 current_app = NULL;
520
521 if (app->assuan_ctx)
522 agent_close (app->assuan_ctx);
523 else
524 apdu_close_reader (app->slot);
525 xfree (app);
526 }
527 }
528
529
530 /* Format a cache ID from the serialnumber in SN and return it as an
531 allocated string. In case of an error NULL is returned. */
532 static char *
format_cacheid(const char * sn)533 format_cacheid (const char *sn)
534 {
535 const char *s;
536 size_t snlen;
537 char *cacheid = NULL;
538
539 /* The serialnumber we use for a card is "CARDSN:serialno". Where
540 serialno is the BCD string (i.e. hex string) with the full
541 number. The serial number expect here constsis of hexdigits
542 followed by other characters, we cut off these other
543 characters. */
544 if (sn)
545 {
546 for (s=sn,snlen=0; hexdigitp (s); s++, snlen++)
547 ;
548 if (snlen == 32)
549 {
550 /* Yes, this looks indeed like an OpenPGP card S/N. */
551 cacheid = xtrymalloc (7+snlen+1);
552 if (cacheid)
553 {
554 memcpy (cacheid, "CARDSN:", 7);
555 memcpy (cacheid+7, sn, snlen);
556 cacheid[7+snlen] = 0;
557 }
558 }
559 }
560 return cacheid;
561 }
562
563
564 /* If RC is not 0, write an appropriate status message. */
565 static void
status_sc_op_failure(int rc)566 status_sc_op_failure (int rc)
567 {
568 if (rc == G10ERR_CANCELED)
569 write_status_text (STATUS_SC_OP_FAILURE, "1");
570 else if (rc == G10ERR_BAD_PASS)
571 write_status_text (STATUS_SC_OP_FAILURE, "2");
572 else if (rc)
573 write_status (STATUS_SC_OP_FAILURE);
574 }
575
576
577 /* Check that the serial number of the current card (as described by
578 APP) matches SERIALNO. If there is no match and we are not in
579 batch mode, present a prompt to insert the desired card. The
580 function returnd 0 if the present card is okay, -1 if the user
581 selected to insert a new card or an error value. Note that the
582 card context will be closed in all cases except for 0 as return
583 value and if it was possible to merely shutdown the reader. */
584 static int
check_card_serialno(app_t app,const char * serialno)585 check_card_serialno (app_t app, const char *serialno)
586 {
587 const char *s;
588 int ask = 0;
589 int n;
590
591 for (s = serialno, n=0; *s != '/' && hexdigitp (s); s++, n++)
592 ;
593 if (n != 32)
594 {
595 log_error ("invalid serial number in keyring detected\n");
596 return gpg_error (GPG_ERR_INV_ID);
597 }
598 if (app->serialnolen != 16)
599 ask = 1;
600 for (s = serialno, n=0; !ask && n < 16; s += 2, n++)
601 if (app->serialno[n] != xtoi_2 (s))
602 ask = 1;
603 if (ask)
604 {
605 char buf[5+32+1];
606 int did_shutdown = 0;
607
608 if (current_app && !apdu_shutdown_reader (current_app->slot))
609 did_shutdown = 1;
610 else
611 card_close ();
612
613 if (!opt.batch)
614 tty_printf (_("Please remove the current card and "
615 "insert the one with serial number:\n"
616 " %.*s\n"), 32, serialno);
617
618 sprintf (buf, "1 %.32s", serialno);
619 write_status_text (STATUS_CARDCTRL, buf);
620
621 if ( !opt.batch
622 && cpr_get_answer_okay_cancel ("cardctrl.change_card.okay",
623 _("Hit return when ready "
624 "or enter 'c' to cancel: "),
625 1) )
626 {
627 card_close ();
628 return -1;
629 }
630 if (did_shutdown)
631 apdu_reset (current_app->slot);
632 else
633 card_close ();
634 return gpg_error (GPG_ERR_INV_ID);
635 }
636 return 0;
637 }
638
639
640 /* Take a 20 byte hexencoded string and put it into the the provided
641 20 byte buffer FPR in binary format. */
642 static int
unhexify_fpr(const char * hexstr,unsigned char * fpr)643 unhexify_fpr (const char *hexstr, unsigned char *fpr)
644 {
645 const char *s;
646 int n;
647
648 for (s=hexstr, n=0; hexdigitp (s); s++, n++)
649 ;
650 if (*s || (n != 40))
651 return 0; /* no fingerprint (invalid or wrong length). */
652 n /= 2;
653 for (s=hexstr, n=0; *s; s += 2, n++)
654 fpr[n] = xtoi_2 (s);
655 return 1; /* okay */
656 }
657
658 /* Take the serial number from LINE and return it verbatim in a newly
659 allocated string. We make sure that only hex characters are
660 returned. */
661 static char *
store_serialno(const char * line)662 store_serialno (const char *line)
663 {
664 const char *s;
665 char *p;
666
667 for (s=line; hexdigitp (s); s++)
668 ;
669 p = xmalloc (s + 1 - line);
670 memcpy (p, line, s-line);
671 p[s-line] = 0;
672 return p;
673 }
674
675 /* Return a new malloced string by unescaping the string S. Escaping
676 is percent escaping and '+'/space mapping. A binary nul will
677 silently be replaced by a 0xFF. Function returns NULL to indicate
678 an out of memory status. */
679 static char *
unescape_status_string(const unsigned char * s)680 unescape_status_string (const unsigned char *s)
681 {
682 return unescape_percent_string (s);
683 }
684
685
686 static assuan_error_t
learn_status_cb(void * opaque,const char * line)687 learn_status_cb (void *opaque, const char *line)
688 {
689 struct agent_card_info_s *parm = opaque;
690 const char *keyword = line;
691 int keywordlen;
692 int i;
693
694 /* log_debug ("got status line `%s'\n", line); */
695 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
696 ;
697 while (spacep (line))
698 line++;
699
700 if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
701 {
702 xfree (parm->serialno);
703 parm->serialno = store_serialno (line);
704 parm->is_v2 = (strlen (parm->serialno) >= 16
705 && xtoi_2 (parm->serialno+12) >= 2 );
706 }
707 else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
708 {
709 xfree (parm->apptype);
710 parm->apptype = unescape_status_string (line);
711 }
712 else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
713 {
714 xfree (parm->disp_name);
715 parm->disp_name = unescape_percent_string (line);
716 }
717 else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
718 {
719 xfree (parm->disp_lang);
720 parm->disp_lang = unescape_percent_string (line);
721 }
722 else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
723 {
724 parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
725 }
726 else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
727 {
728 xfree (parm->pubkey_url);
729 parm->pubkey_url = unescape_percent_string (line);
730 }
731 else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
732 {
733 xfree (parm->login_data);
734 parm->login_data = unescape_percent_string (line);
735 }
736 else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
737 {
738 parm->sig_counter = strtoul (line, NULL, 0);
739 }
740 else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
741 {
742 char *p, *buf;
743
744 buf = p = unescape_percent_string (line);
745 if (buf)
746 {
747 while (spacep (p))
748 p++;
749 parm->chv1_cached = atoi (p);
750 while (*p && !spacep (p))
751 p++;
752 while (spacep (p))
753 p++;
754 for (i=0; *p && i < 3; i++)
755 {
756 parm->chvmaxlen[i] = atoi (p);
757 while (*p && !spacep (p))
758 p++;
759 while (spacep (p))
760 p++;
761 }
762 for (i=0; *p && i < 3; i++)
763 {
764 parm->chvretry[i] = atoi (p);
765 while (*p && !spacep (p))
766 p++;
767 while (spacep (p))
768 p++;
769 }
770 xfree (buf);
771 }
772 }
773 else if (keywordlen == 6 && !memcmp (keyword, "EXTCAP", keywordlen))
774 {
775 char *p, *p2, *buf;
776 int abool;
777
778 buf = p = unescape_status_string (line);
779 if (buf)
780 {
781 for (p = strtok (buf, " "); p; p = strtok (NULL, " "))
782 {
783 p2 = strchr (p, '=');
784 if (p2)
785 {
786 *p2++ = 0;
787 abool = (*p2 == '1');
788 if (!strcmp (p, "ki"))
789 parm->extcap.ki = abool;
790 else if (!strcmp (p, "aac"))
791 parm->extcap.aac = abool;
792 }
793 }
794 xfree (buf);
795 }
796 }
797 else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
798 {
799 int no = atoi (line);
800 while (* line && !spacep (line))
801 line++;
802 while (spacep (line))
803 line++;
804 if (no == 1)
805 parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
806 else if (no == 2)
807 parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
808 else if (no == 3)
809 parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
810 }
811 else if (keywordlen == 8 && !memcmp (keyword, "KEY-TIME", keywordlen))
812 {
813 int no = atoi (line);
814 while (* line && !spacep (line))
815 line++;
816 while (spacep (line))
817 line++;
818 if (no == 1)
819 parm->fpr1time = strtoul (line, NULL, 10);
820 else if (no == 2)
821 parm->fpr2time = strtoul (line, NULL, 10);
822 else if (no == 3)
823 parm->fpr3time = strtoul (line, NULL, 10);
824 }
825 else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
826 {
827 int no = atoi (line);
828 while (*line && !spacep (line))
829 line++;
830 while (spacep (line))
831 line++;
832 if (no == 1)
833 parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
834 else if (no == 2)
835 parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
836 else if (no == 3)
837 parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
838 }
839 else if (keywordlen == 12 && !memcmp (keyword, "PRIVATE-DO-", 11)
840 && strchr ("1234", keyword[11]))
841 {
842 int no = keyword[11] - '1';
843 assert (no >= 0 && no <= 3);
844 xfree (parm->private_do[no]);
845 parm->private_do[no] = unescape_percent_string (line);
846 }
847 else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
848 {
849 int keyno, algo, nbits;
850
851 sscanf (line, "%d %d %d", &keyno, &algo, &nbits);
852 keyno--;
853 if (keyno >= 0 && keyno < DIM (parm->key_attr))
854 {
855 parm->key_attr[keyno].algo = algo;
856 parm->key_attr[keyno].nbits = nbits;
857 }
858 }
859
860 return 0;
861 }
862
863
864 /* Return card info. */
865 int
agent_learn(struct agent_card_info_s * info)866 agent_learn (struct agent_card_info_s *info)
867 {
868 app_t app;
869 int rc;
870 struct ctrl_ctx_s ctrl;
871 time_t stamp;
872 char *serial;
873
874 app = current_app? current_app : open_card ();
875 if (!app)
876 return gpg_error (GPG_ERR_CARD);
877
878 memset (info, 0, sizeof *info);
879
880 if (app->assuan_ctx)
881 {
882 rc = assuan_transact (app->assuan_ctx, "SCD LEARN --force",
883 NULL, NULL, NULL, NULL,
884 learn_status_cb, info);
885 rc = test_transact (rc, "SCD LEARN");
886 }
887 else
888 {
889 memset (&ctrl, 0, sizeof ctrl);
890 ctrl.status_cb = learn_status_cb;
891 ctrl.status_cb_arg = info;
892
893 rc = app_get_serial_and_stamp (app, &serial, &stamp);
894 if (!rc)
895 {
896 send_status_info (&ctrl, "SERIALNO",
897 serial, strlen(serial), NULL, 0);
898 xfree (serial);
899 rc = app->fnc.learn_status (app, &ctrl, 0);
900 }
901 }
902
903 if (!rc)
904 agent_scd_getattr ("KEY-ATTR", info);
905
906 return rc;
907 }
908
909
910 /* Get an attribute from the card. Make sure info is initialized. */
911 int
agent_scd_getattr(const char * name,struct agent_card_info_s * info)912 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
913 {
914 int rc;
915 app_t app;
916 struct ctrl_ctx_s ctrl;
917
918 app = current_app? current_app : open_card ();
919 if (!app)
920 return gpg_error (GPG_ERR_CARD);
921
922 if (app->assuan_ctx)
923 {
924 char line[ASSUAN_LINELENGTH];
925
926 /* We assume that NAME does not need escaping. */
927 if (12 + strlen (name) > DIM(line)-1)
928 return gpg_error (GPG_ERR_CARD);
929 stpcpy (stpcpy (line, "SCD GETATTR "), name);
930
931 rc = test_transact (assuan_transact (app->assuan_ctx, line,
932 NULL, NULL, NULL, NULL,
933 learn_status_cb, info),
934 "SCD GETATTR");
935 }
936 else
937 {
938 ctrl.status_cb = learn_status_cb;
939 ctrl.status_cb_arg = info;
940 rc = app->fnc.getattr (app, &ctrl, name);
941 }
942
943 return rc;
944 }
945
946
947
948 static int
pin_cb(void * opaque,const char * info,char ** retstr)949 pin_cb (void *opaque, const char *info, char **retstr)
950 {
951 struct pincb_parm_s *parm = opaque;
952 char *value;
953 int canceled;
954 int isadmin = 0;
955 int newpin = 0;
956 const char *again_text = NULL;
957 const char *ends, *s;
958 char *cacheid = NULL;
959
960 *retstr = NULL;
961 /* log_debug ("asking for PIN '%s'\n", info); */
962
963 /* We use a special prefix to check whether the Admin PIN has been
964 requested. */
965 if (info && *info =='|' && (ends=strchr (info+1, '|')))
966 {
967 for (s=info+1; s < ends; s++)
968 {
969 if (*s == 'A')
970 isadmin = 1;
971 else if (*s == 'N')
972 newpin = 1;
973 }
974 info = ends+1;
975 }
976 else if (info && *info == '|')
977 log_debug ("pin_cb called without proper PIN info hack\n");
978
979 /* If we are not requesting a new PIN and we are not requesting an
980 AdminPIN, compute a string to be used as the cacheID for
981 gpg-agent. */
982 if (!newpin && !isadmin && parm)
983 {
984 cacheid = format_cacheid (parm->sn);
985 }
986 else if (newpin && parm)
987 {
988 /* Make really sure that it is not cached anymore. */
989 agent_clear_pin_cache (parm->sn);
990 }
991
992
993 again:
994 if (is_status_enabled())
995 {
996 if (parm && parm->sn && *parm->sn)
997 {
998 char *buf = xmalloc ( 10 + strlen (parm->sn) + 1);
999 strcpy (stpcpy (buf, isadmin? "OPENPGP 3 ":"OPENPGP 1 "), parm->sn);
1000 write_status_text (STATUS_NEED_PASSPHRASE_PIN, buf);
1001 xfree (buf);
1002 }
1003 else
1004 write_status_text (STATUS_NEED_PASSPHRASE_PIN,
1005 isadmin? "OPENPGP 3" : "OPENPGP 1");
1006 }
1007
1008 value = ask_passphrase (info, again_text,
1009 newpin && isadmin? "passphrase.adminpin.new.ask" :
1010 newpin? "passphrase.pin.new.ask" :
1011 isadmin? "passphrase.adminpin.ask" :
1012 "passphrase.pin.ask",
1013 newpin && isadmin? _("Enter New Admin PIN: ") :
1014 newpin? _("Enter New PIN: ") :
1015 isadmin? _("Enter Admin PIN: ")
1016 : _("Enter PIN: "),
1017 cacheid,
1018 &canceled);
1019 xfree (cacheid);
1020 cacheid = NULL;
1021 again_text = NULL;
1022 if (!value && canceled)
1023 return G10ERR_CANCELED;
1024 else if (!value)
1025 return G10ERR_GENERAL;
1026
1027 if (newpin)
1028 {
1029 char *value2;
1030
1031 value2 = ask_passphrase (info, NULL,
1032 "passphrase.pin.repeat",
1033 _("Repeat this PIN: "),
1034 NULL,
1035 &canceled);
1036 if (!value2 && canceled)
1037 {
1038 xfree (value);
1039 return G10ERR_CANCELED;
1040 }
1041 else if (!value2)
1042 {
1043 xfree (value);
1044 return G10ERR_GENERAL;
1045 }
1046 if (strcmp (value, value2))
1047 {
1048 again_text = N_("PIN not correctly repeated; try again");
1049 xfree (value2);
1050 xfree (value);
1051 value = NULL;
1052 goto again;
1053 }
1054 xfree (value2);
1055 }
1056
1057 *retstr = value;
1058 return 0;
1059 }
1060
1061
1062
1063 /* Send a SETATTR command to the SCdaemon. */
1064 int
agent_scd_setattr(const char * name,const unsigned char * value,size_t valuelen,const char * serialno)1065 agent_scd_setattr (const char *name,
1066 const unsigned char *value, size_t valuelen,
1067 const char *serialno)
1068 {
1069 app_t app;
1070 int rc;
1071 struct pincb_parm_s parm;
1072
1073 memset (&parm, 0, sizeof parm);
1074 parm.sn = serialno;
1075
1076 app = current_app? current_app : open_card ();
1077 if (!app)
1078 return gpg_error (GPG_ERR_CARD);
1079
1080 if (app->assuan_ctx)
1081 {
1082 char line[ASSUAN_LINELENGTH];
1083 char *p;
1084
1085 /* We assume that NAME does not need escaping. */
1086 if (12 + strlen (name) > DIM(line)-1)
1087 return gpg_error (GPG_ERR_CARD);
1088 p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
1089 *p++ = ' ';
1090 for (; valuelen; value++, valuelen--)
1091 {
1092 if (p >= line + DIM(line)-5 )
1093 return gpg_error (GPG_ERR_CARD);
1094 if (*value < ' ' || *value == '+' || *value == '%')
1095 {
1096 sprintf (p, "%%%02X", *value);
1097 p += 3;
1098 }
1099 else if (*value == ' ')
1100 *p++ = '+';
1101 else
1102 *p++ = *value;
1103 }
1104 *p = 0;
1105
1106 rc = test_transact (assuan_transact (app->assuan_ctx, line,
1107 NULL, NULL, NULL, NULL, NULL, NULL),
1108 "SCD SETATTR");
1109 }
1110 else
1111 {
1112 rc = app->fnc.setattr (app, name, pin_cb, &parm, value, valuelen);
1113 }
1114
1115 status_sc_op_failure (rc);
1116 return rc;
1117 }
1118
1119
1120 /* Handle a KEYDATA inquiry. Note, we only send the data,
1121 assuan_transact takes care of flushing and writing the end */
1122 static assuan_error_t
inq_writekey_parms(void * opaque,const char * keyword)1123 inq_writekey_parms (void *opaque, const char *keyword)
1124 {
1125 struct writekey_parm_s *parm = opaque;
1126
1127 return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
1128 }
1129
1130
1131 /* Send a WRITEKEY command to the SCdaemon. */
1132 int
agent_scd_writekey(int keyno,const char * serialno,const unsigned char * keydata,size_t keydatalen)1133 agent_scd_writekey (int keyno, const char *serialno,
1134 const unsigned char *keydata, size_t keydatalen)
1135 {
1136 app_t app;
1137 int rc;
1138 char line[ASSUAN_LINELENGTH];
1139 struct pincb_parm_s parm;
1140
1141 memset (&parm, 0, sizeof parm);
1142 parm.sn = serialno;
1143
1144 app = current_app? current_app : open_card ();
1145 if (!app)
1146 return gpg_error (GPG_ERR_CARD);
1147
1148 if (app->assuan_ctx)
1149 {
1150 struct writekey_parm_s parms;
1151
1152 snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
1153 line[DIM(line)-1] = 0;
1154 parms.ctx = app->assuan_ctx;
1155 parms.keydata = keydata;
1156 parms.keydatalen = keydatalen;
1157 rc = test_transact (assuan_transact (app->assuan_ctx, line,
1158 NULL, NULL,
1159 inq_writekey_parms, &parms,
1160 NULL, NULL),
1161 "SCD WRITEKEY");
1162 }
1163 else
1164 {
1165 snprintf (line, DIM(line)-1, "OPENPGP.%d", keyno);
1166 line[DIM(line)-1] = 0;
1167 rc = app->fnc.writekey (app, NULL, line, 0x0001,
1168 pin_cb, &parm,
1169 keydata, keydatalen);
1170 }
1171
1172 status_sc_op_failure (rc);
1173 return rc;
1174 }
1175
1176
1177
1178 static assuan_error_t
genkey_status_cb(void * opaque,const char * line)1179 genkey_status_cb (void *opaque, const char *line)
1180 {
1181 struct agent_card_genkey_s *parm = opaque;
1182 const char *keyword = line;
1183 int keywordlen;
1184
1185 /* log_debug ("got status line `%s'\n", line); */
1186 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
1187 ;
1188 while (spacep (line))
1189 line++;
1190
1191 if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
1192 {
1193 parm->fprvalid = unhexify_fpr (line, parm->fpr);
1194 }
1195 if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
1196 {
1197 MPI a;
1198 const char *name = line;
1199 char *buf;
1200
1201 while (*line && !spacep (line))
1202 line++;
1203 while (spacep (line))
1204 line++;
1205
1206 buf = xmalloc ( 2 + strlen (line) + 1);
1207 strcpy (stpcpy (buf, "0x"), line);
1208 a = mpi_alloc (300);
1209 if( mpi_fromstr (a, buf) )
1210 log_error ("error parsing received key data\n");
1211 else if (*name == 'n' && spacep (name+1))
1212 parm->n = a;
1213 else if (*name == 'e' && spacep (name+1))
1214 parm->e = a;
1215 else
1216 {
1217 log_info ("unknown parameter name in received key data\n");
1218 mpi_free (a);
1219 }
1220 xfree (buf);
1221 }
1222 else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
1223 {
1224 parm->created_at = (u32)strtoul (line, NULL, 10);
1225 }
1226
1227 return 0;
1228 }
1229
1230 /* Send a GENKEY command to the SCdaemon. */
1231 int
agent_scd_genkey(struct agent_card_genkey_s * info,int keyno,int force,const char * serialno,u32 * createtime)1232 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
1233 const char *serialno, u32 *createtime)
1234 {
1235 app_t app;
1236 char line[ASSUAN_LINELENGTH];
1237 struct ctrl_ctx_s ctrl;
1238 int rc;
1239 struct pincb_parm_s parm;
1240
1241 memset (&parm, 0, sizeof parm);
1242 parm.sn = serialno;
1243
1244 app = current_app? current_app : open_card ();
1245 if (!app)
1246 return gpg_error (GPG_ERR_CARD);
1247
1248 memset (info, 0, sizeof *info);
1249
1250 if (app->assuan_ctx)
1251 {
1252 snprintf (line, DIM(line)-1, "SCD GENKEY %s%d",
1253 force? "--force ":"", keyno);
1254 line[DIM(line)-1] = 0;
1255 rc = test_transact (assuan_transact (app->assuan_ctx, line,
1256 NULL, NULL, NULL, NULL,
1257 genkey_status_cb, info),
1258 "SCD GENKEY");
1259 }
1260 else
1261 {
1262 snprintf (line, DIM(line)-1, "%d", keyno);
1263 ctrl.status_cb = genkey_status_cb;
1264 ctrl.status_cb_arg = info;
1265 rc = app->fnc.genkey (app, &ctrl, line,
1266 force? 1:0,
1267 *createtime,
1268 pin_cb, &parm);
1269 }
1270
1271 status_sc_op_failure (rc);
1272 return rc;
1273 }
1274
1275
1276 static assuan_error_t
membuf_data_cb(void * opaque,const void * buffer,size_t length)1277 membuf_data_cb (void *opaque, const void *buffer, size_t length)
1278 {
1279 membuf_t *data = opaque;
1280
1281 if (buffer)
1282 put_membuf (data, buffer, length);
1283 return 0;
1284 }
1285
1286
1287 /* Send a PKSIGN command to the SCdaemon. */
1288 int
agent_scd_pksign(const char * serialno,int hashalgo,const unsigned char * indata,size_t indatalen,unsigned char ** r_buf,size_t * r_buflen)1289 agent_scd_pksign (const char *serialno, int hashalgo,
1290 const unsigned char *indata, size_t indatalen,
1291 unsigned char **r_buf, size_t *r_buflen)
1292 {
1293 struct pincb_parm_s parm;
1294 app_t app;
1295 int rc;
1296
1297 *r_buf = NULL;
1298 *r_buflen = 0;
1299 memset (&parm, 0, sizeof parm);
1300 parm.sn = serialno;
1301 retry:
1302 app = current_app? current_app : open_card ();
1303 if (!app)
1304 return gpg_error (GPG_ERR_CARD);
1305
1306 if (app->assuan_ctx)
1307 {
1308 char *p, line[ASSUAN_LINELENGTH];
1309 membuf_t data;
1310 size_t len;
1311 int i;
1312
1313 if (indatalen*2 + 50 > DIM(line))
1314 return gpg_error (GPG_ERR_GENERAL);
1315
1316 p = stpcpy (line, "SCD SETDATA ");
1317 for (i=0; i < indatalen ; i++, p += 2 )
1318 sprintf (p, "%02X", indata[i]);
1319 rc = test_transact (assuan_transact (app->assuan_ctx, line,
1320 NULL, NULL, NULL, NULL, NULL, NULL),
1321 "SCD SETDATA");
1322 if (!rc)
1323 {
1324 init_membuf (&data, 1024);
1325 snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
1326 hashalgo == GCRY_MD_SHA1? "--hash=sha1 ":
1327 hashalgo == GCRY_MD_SHA224? "--hash=sha224 ":
1328 hashalgo == GCRY_MD_SHA256? "--hash=sha256 ":
1329 hashalgo == GCRY_MD_SHA384? "--hash=sha384 ":
1330 hashalgo == GCRY_MD_SHA512? "--hash=sha512 ":
1331 hashalgo == GCRY_MD_RMD160? "--hash=rmd160 ":
1332 hashalgo == GCRY_MD_MD5? "--hash=md5 " : "",
1333 serialno);
1334 line[DIM(line)-1] = 0;
1335 rc = test_transact (assuan_transact (app->assuan_ctx, line,
1336 membuf_data_cb, &data,
1337 NULL, NULL, NULL, NULL),
1338 "SCD PKSIGN");
1339 if (rc)
1340 xfree (get_membuf (&data, &len));
1341 else
1342 *r_buf = get_membuf (&data, r_buflen);
1343 }
1344 }
1345 else
1346 {
1347 /* Check that the card's serialnumber is as required.*/
1348 rc = check_card_serialno (app, serialno);
1349 if (rc == -1)
1350 goto retry;
1351
1352 if (!rc)
1353 rc = app->fnc.sign (app, serialno, hashalgo,
1354 pin_cb, &parm,
1355 indata, indatalen,
1356 r_buf, r_buflen);
1357 }
1358
1359 if (rc)
1360 {
1361 status_sc_op_failure (rc);
1362 if (!app->assuan_ctx)
1363 agent_clear_pin_cache (serialno);
1364 }
1365 return rc;
1366 }
1367
1368
1369 /* Send a PKDECRYPT command to the SCdaemon. */
1370 int
agent_scd_pkdecrypt(const char * serialno,const unsigned char * indata,size_t indatalen,unsigned char ** r_buf,size_t * r_buflen)1371 agent_scd_pkdecrypt (const char *serialno,
1372 const unsigned char *indata, size_t indatalen,
1373 unsigned char **r_buf, size_t *r_buflen)
1374 {
1375 struct pincb_parm_s parm;
1376 app_t app;
1377 int rc;
1378
1379 *r_buf = NULL;
1380 *r_buflen = 0;
1381 memset (&parm, 0, sizeof parm);
1382 parm.sn = serialno;
1383 retry:
1384 app = current_app? current_app : open_card ();
1385 if (!app)
1386 return gpg_error (GPG_ERR_CARD);
1387
1388 if (app->assuan_ctx)
1389 {
1390 char *p, line[ASSUAN_LINELENGTH];
1391 membuf_t data;
1392 size_t len;
1393 int i;
1394
1395 if (indatalen*2 + 50 > DIM(line))
1396 return gpg_error (GPG_ERR_GENERAL);
1397
1398 p = stpcpy (line, "SCD SETDATA ");
1399 for (i=0; i < indatalen ; i++, p += 2 )
1400 sprintf (p, "%02X", indata[i]);
1401 rc = test_transact (assuan_transact (app->assuan_ctx, line,
1402 NULL, NULL, NULL, NULL, NULL, NULL),
1403 "SCD SETDATA");
1404 if (!rc)
1405 {
1406 init_membuf (&data, 1024);
1407 snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
1408 line[DIM(line)-1] = 0;
1409 rc = test_transact (assuan_transact (app->assuan_ctx, line,
1410 membuf_data_cb, &data,
1411 NULL, NULL, NULL, NULL),
1412 "SCD PKDECRYPT");
1413 if (rc)
1414 xfree (get_membuf (&data, &len));
1415 else
1416 *r_buf = get_membuf (&data, r_buflen);
1417 }
1418 }
1419 else
1420 {
1421 /* Check that the card's serialnumber is as required.*/
1422 rc = check_card_serialno (app, serialno);
1423 if (rc == -1)
1424 goto retry;
1425
1426 if (!rc)
1427 rc = app->fnc.decipher (app, serialno,
1428 pin_cb, &parm,
1429 indata, indatalen,
1430 r_buf, r_buflen);
1431 }
1432
1433 if (rc)
1434 {
1435 status_sc_op_failure (rc);
1436 if (!app->assuan_ctx)
1437 agent_clear_pin_cache (serialno);
1438 }
1439 return rc;
1440 }
1441
1442 /* Change the PIN of an OpenPGP card or reset the retry
1443 counter. SERIALNO may be NULL or a hex string finally passed to the
1444 passphrase callback. */
1445 int
agent_scd_change_pin(int chvno,const char * serialno)1446 agent_scd_change_pin (int chvno, const char *serialno)
1447 {
1448 app_t app;
1449 int reset = 0;
1450 int rc;
1451 struct pincb_parm_s parm;
1452
1453 memset (&parm, 0, sizeof parm);
1454 parm.sn = serialno;
1455
1456 reset = (chvno >= 100);
1457 chvno %= 100;
1458
1459 app = current_app? current_app : open_card ();
1460 if (!app)
1461 return gpg_error (GPG_ERR_CARD);
1462
1463 if (app->assuan_ctx)
1464 {
1465 char line[ASSUAN_LINELENGTH];
1466
1467 snprintf (line, DIM(line)-1, "SCD PASSWD%s %d",
1468 reset? " --reset":"", chvno);
1469 line[DIM(line)-1] = 0;
1470 rc = test_transact (assuan_transact (app->assuan_ctx, line,
1471 NULL, NULL, NULL, NULL, NULL, NULL),
1472 "SCD PASSWD");
1473 }
1474 else
1475 {
1476 char chvnostr[50];
1477
1478 sprintf (chvnostr, "%d", chvno);
1479 rc = app->fnc.change_pin (app, NULL, chvnostr, reset,
1480 pin_cb, &parm);
1481 }
1482
1483 status_sc_op_failure (rc);
1484 return rc;
1485 }
1486
1487 /* Perform a CHECKPIN operation. SERIALNO should be the serial
1488 number of the card - optionally followed by the fingerprint;
1489 however the fingerprint is ignored here. */
1490 int
agent_scd_checkpin(const char * serialnobuf)1491 agent_scd_checkpin (const char *serialnobuf)
1492 {
1493 app_t app;
1494 int rc;
1495 struct pincb_parm_s parm;
1496
1497 memset (&parm, 0, sizeof parm);
1498 parm.sn = serialnobuf;
1499
1500 app = current_app? current_app : open_card ();
1501 if (!app)
1502 return gpg_error (GPG_ERR_CARD);
1503
1504 if (app->assuan_ctx)
1505 {
1506 char line[ASSUAN_LINELENGTH];
1507
1508 if (15 + strlen (serialnobuf) > DIM(line)-1)
1509 return gpg_error (GPG_ERR_CARD);
1510 stpcpy (stpcpy (line, "SCD CHECKPIN "), serialnobuf);
1511 rc = test_transact (assuan_transact (app->assuan_ctx, line,
1512 NULL, NULL, NULL, NULL, NULL, NULL),
1513 "SCD CHECKPIN");
1514 }
1515 else
1516 {
1517 rc = app->fnc.check_pin (app, serialnobuf, pin_cb, &parm);
1518 }
1519
1520 status_sc_op_failure (rc);
1521 return rc;
1522 }
1523
1524
1525
1526 void
agent_clear_pin_cache(const char * sn)1527 agent_clear_pin_cache (const char *sn)
1528 {
1529 char *cacheid = format_cacheid (sn);
1530 if (cacheid)
1531 {
1532 passphrase_clear_cache (NULL, cacheid, 0);
1533 xfree (cacheid);
1534 }
1535 }
1536
1537
1538 int
agent_scd_writecert(const char * certidstr,const unsigned char * certdata,size_t certdatalen)1539 agent_scd_writecert (const char *certidstr,
1540 const unsigned char *certdata, size_t certdatalen)
1541 {
1542 /* It does not make sense to implement this rarely used and mainly
1543 interactive command in GPG-1. GPG-2 is better suited for this. */
1544 not_in_gpg1_notice ();
1545 return gpg_error (GPG_ERR_NOT_SUPPORTED);
1546 }
1547
1548
1549 int
agent_scd_readcert(const char * certidstr,void ** r_buf,size_t * r_buflen)1550 agent_scd_readcert (const char *certidstr,
1551 void **r_buf, size_t *r_buflen)
1552 {
1553 /* It does not make sense to implement this rarely used and mainly
1554 interactive command in GPG-1. GPG-2 is better suited for this. */
1555 *r_buf = NULL;
1556 not_in_gpg1_notice ();
1557 return gpg_error (GPG_ERR_NOT_SUPPORTED);
1558 }
1559