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