* passphrase.c (agent_get_passphrase): New args CUSTOM_PROMPT and
[gnupg.git] / g10 / cardglue.c
1 /* cardglue.c - mainly dispatcher for card related functions.
2  * Copyright (C) 2003, 2004 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 2 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #ifndef ENABLE_CARD_SUPPORT
23 #error  not configured for card support.
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <stdarg.h>
30 #include <assert.h>
31
32 #include "options.h"
33 #include "packet.h"
34 #include "errors.h"
35 #include "memory.h"
36 #include "util.h"
37 #include "main.h"
38 #include "status.h"
39 #include "ttyio.h"
40 #include "i18n.h"
41
42 #include "cardglue.h"
43 #include "apdu.h"
44 #include "app-common.h"
45
46 struct ctrl_ctx_s {
47   int (*status_cb)(void *opaque, const char *line);
48   void *status_cb_arg;
49 };
50
51
52 static char *default_reader_port;
53 static APP current_app;
54
55
56
57 /* Create a serialno/fpr string from the serial number and the secret
58    key.  caller must free the returned string.  There is no error
59    return. [Taken from 1.9's keyid.c]*/
60 char *
61 serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
62                           PKT_secret_key *sk)
63 {
64   unsigned char fpr[MAX_FINGERPRINT_LEN];
65   size_t fprlen;
66   char *buffer, *p;
67   int i;
68   
69   fingerprint_from_sk (sk, fpr, &fprlen);
70   buffer = p = xmalloc (snlen*2 + 1 + fprlen*2 + 1);
71   for (i=0; i < snlen; i++, p+=2)
72     sprintf (p, "%02X", sn[i]);
73   *p++ = '/';
74   for (i=0; i < fprlen; i++, p+=2)
75     sprintf (p, "%02X", fpr[i]);
76   *p = 0;
77   return buffer;
78 }
79
80
81 /* Send a line with status information via assuan and escape all given
82    buffers. The variable elements are pairs of (char *, size_t),
83    terminated with a (NULL, 0). */
84 void
85 send_status_info (CTRL ctrl, const char *keyword, ...)
86 {
87   va_list arg_ptr;
88   const unsigned char *value;
89   size_t valuelen;
90   char buf[950], *p;
91   size_t n;
92   
93   va_start (arg_ptr, keyword);
94
95   p = buf; 
96   n = 0;
97   valuelen = strlen (keyword);
98   for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, keyword++)
99     *p++ = *keyword;
100
101   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
102     {
103       valuelen = va_arg (arg_ptr, size_t);
104       if (!valuelen)
105         continue; /* empty buffer */
106       if (n)
107         {
108           *p++ = ' ';
109           n++;
110         }
111       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
112         {
113           if (*value < ' ' || *value == '+')
114             {
115               sprintf (p, "%%%02X", *value);
116               p += 3;
117             }
118           else if (*value == ' ')
119             *p++ = '+';
120           else
121             *p++ = *value;
122         }
123     }
124   *p = 0;
125   ctrl->status_cb (ctrl->status_cb_arg, buf);
126
127   va_end (arg_ptr);
128 }
129
130
131 void gcry_md_hash_buffer (int algo, void *digest,
132                           const void *buffer, size_t length)
133 {
134   MD_HANDLE h = md_open (algo, 0);
135   if (!h)
136     BUG();
137   md_write (h, (byte *) buffer, length);
138   md_final (h);
139   memcpy (digest, md_read (h, algo), md_digest_length (algo));
140   md_close (h);
141 }
142
143
144 /* This is a limited version of the one in 1.9 but it should be
145    sufficient here. */
146 void
147 log_printf (const char *fmt, ...)
148 {
149   va_list arg_ptr;
150
151   va_start (arg_ptr, fmt);
152   vfprintf (log_stream (), fmt, arg_ptr);
153   va_end (arg_ptr);
154 }
155
156
157
158 /* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
159    dump, with TEXT just an empty string, print a trailing linefeed,
160    otherwise print an entire debug line. */
161 void
162 log_printhex (const char *text, const void *buffer, size_t length)
163 {
164   if (text && *text)
165     log_debug ("%s ", text);
166   if (length)
167     {
168       const unsigned char *p = buffer;
169       log_printf ("%02X", *p);
170       for (length--, p++; length--; p++)
171         log_printf (" %02X", *p);
172     }
173   if (text)
174     log_printf ("\n");
175 }
176
177
178
179 void
180 app_set_default_reader_port (const char *portstr)
181 {
182   xfree (default_reader_port);
183   default_reader_port = portstr? xstrdup (portstr): NULL;
184 }
185
186
187 void
188 card_set_reader_port (const char *portstr)
189 {
190   app_set_default_reader_port (portstr);
191 }
192
193
194 /* Retrieve the serial number and the time of the last update of the
195    card.  The serial number is returned as a malloced string (hex
196    encoded) in SERIAL and the time of update is returned in STAMP.  If
197    no update time is available the returned value is 0.  Caller must
198    free SERIAL unless the function returns an error. */
199 int 
200 app_get_serial_and_stamp (APP app, char **serial, time_t *stamp)
201 {
202   unsigned char *buf, *p;
203   int i;
204
205   if (!app || !serial || !stamp)
206     return gpg_error (GPG_ERR_INV_VALUE);
207
208   *serial = NULL;
209   *stamp = 0; /* not available */
210
211   buf = xtrymalloc (app->serialnolen * 2 + 1);
212   if (!buf)
213     return gpg_error_from_errno (errno);
214   for (p=buf, i=0; i < app->serialnolen; p +=2, i++)
215     sprintf (p, "%02X", app->serialno[i]);
216   *p = 0;
217   *serial = buf;
218   return 0;
219 }
220
221
222
223
224
225
226 /* Release the card info structure. */
227 void 
228 agent_release_card_info (struct agent_card_info_s *info)
229 {
230   int i;
231
232   if (!info)
233     return;
234
235   xfree (info->serialno); info->serialno = NULL;
236   xfree (info->disp_name); info->disp_name = NULL;
237   xfree (info->disp_lang); info->disp_lang = NULL;
238   xfree (info->pubkey_url); info->pubkey_url = NULL;
239   xfree (info->login_data); info->login_data = NULL;
240   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
241   info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
242   for (i=0; i < 4; i++)
243     {
244       xfree (info->private_do[i]);
245       info->private_do[i] = NULL;
246     }
247 }
248
249
250 /* Open the current card and select the openpgp application.  Return
251    an APP context handle to be used for further procesing or NULL on
252    error or if no OpenPGP application exists.*/
253 static APP
254 open_card (void)
255 {
256   int slot = -1;
257   int rc;
258   APP app;
259   int did_shutdown = 0;
260
261   card_close ();
262
263   
264  retry:
265   if (did_shutdown)
266     apdu_reset (slot);
267   else
268     {
269       slot = apdu_open_reader (default_reader_port);
270       if (slot == -1)
271         {
272           log_error ("card reader not available\n");
273           return NULL;
274         }
275     }
276
277   app = xcalloc (1, sizeof *app);
278   app->slot = slot;
279   rc = app_select_openpgp (app);
280   if (rc && !opt.batch)
281     {
282       write_status_text (STATUS_CARDCTRL, "1");
283       
284       did_shutdown = !!apdu_shutdown_reader (slot);
285
286       if ( cpr_get_answer_okay_cancel ("cardctrl.insert_card.okay",
287            _("Please insert the card and hit return or enter 'c' to cancel: "),
288                                        1) )
289         {
290           if (!did_shutdown)
291             apdu_close_reader (slot);
292           xfree (app);
293           goto retry;
294         }
295     }
296   if (rc)
297     {
298       log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
299       apdu_close_reader (slot);
300       xfree (app);
301       return NULL;
302     }
303
304   app->initialized = 1;
305   current_app = app;
306   if (is_status_enabled () )
307     {
308       int i;
309       char *p, *buf;
310
311       buf = xmalloc (5 + app->serialnolen * 2 + 1);
312       p = stpcpy (buf, "3 ");
313       for (i=0; i < app->serialnolen; p +=2, i++)
314         sprintf (p, "%02X", app->serialno[i]);
315       write_status_text (STATUS_CARDCTRL, buf);
316       xfree (buf);
317     }
318
319   return app;
320 }
321
322 void
323 card_close (void)
324 {
325   if (current_app)
326     {
327       APP app = current_app;
328       current_app = NULL;
329
330       apdu_close_reader (app->slot);
331       xfree (app);
332     }
333 }
334
335
336 /* Check that the serial number of the current card (as described by
337    APP) matches SERIALNO.  If there is no match and we are not in
338    batch mode, present a prompt to insert the desired card.  The
339    function return 0 is the present card is okay, -1 if the user
340    selected to insert a new card or an error value.  Note that the
341    card context will be closed in all cases except for 0 as return
342    value and if it was possible to merely shutdown the reader. */
343 static int
344 check_card_serialno (APP app, const char *serialno)
345 {
346   const char *s;
347   int ask = 0;
348   int n;
349   
350   for (s = serialno, n=0; *s != '/' && hexdigitp (s); s++, n++)
351     ;
352   if (n != 32)
353     {
354       log_error ("invalid serial number in keyring detected\n");
355       return gpg_error (GPG_ERR_INV_ID);
356     }
357   if (app->serialnolen != 16)
358     ask = 1;
359   for (s = serialno, n=0; !ask && n < 16; s += 2, n++)
360     if (app->serialno[n] != xtoi_2 (s))
361       ask = 1;
362   if (ask)
363     {
364       char buf[5+32+1];
365       int did_shutdown = 0;
366
367       if (current_app && !apdu_shutdown_reader (current_app->slot))
368         did_shutdown = 1;
369       else
370         card_close ();
371       tty_printf (_("Please remove the current card and "
372                     "insert the one with serial number:\n"
373                     "   %.*s\n"), 32, serialno);
374
375       sprintf (buf, "1 %.32s", serialno);
376       write_status_text (STATUS_CARDCTRL, buf);
377
378       if ( cpr_get_answer_okay_cancel ("cardctrl.change_card.okay",
379                           _("Hit return when ready "
380                             "or enter 'c' to cancel: "),
381                                        1) )
382         {
383           card_close ();
384           return -1;
385         }
386       if (did_shutdown)
387         apdu_reset (current_app->slot);
388       else
389         card_close ();
390       return gpg_error (GPG_ERR_INV_ID);
391     }
392   return 0;
393 }
394
395
396
397 /* Return a new malloced string by unescaping the string S.  Escaping
398    is percent escaping and '+'/space mapping.  A binary nul will
399    silently be replaced by a 0xFF.  Function returns NULL to indicate
400    an out of memory status. */
401 static char *
402 unescape_status_string (const unsigned char *s)
403 {
404   char *buffer, *d;
405
406   buffer = d = xmalloc (strlen (s)+1);
407   while (*s)
408     {
409       if (*s == '%' && s[1] && s[2])
410         { 
411           s++;
412           *d = xtoi_2 (s);
413           if (!*d)
414             *d = '\xff';
415           d++;
416           s += 2;
417         }
418       else if (*s == '+')
419         {
420           *d++ = ' ';
421           s++;
422         }
423       else
424         *d++ = *s++;
425     }
426   *d = 0; 
427   return buffer;
428 }
429
430 /* Take a 20 byte hexencoded string and put it into the the provided
431    20 byte buffer FPR in binary format. */
432 static int
433 unhexify_fpr (const char *hexstr, unsigned char *fpr)
434 {
435   const char *s;
436   int n;
437
438   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
439     ;
440   if (*s || (n != 40))
441     return 0; /* no fingerprint (invalid or wrong length). */
442   n /= 2;
443   for (s=hexstr, n=0; *s; s += 2, n++)
444     fpr[n] = xtoi_2 (s);
445   return 1; /* okay */
446 }
447
448 /* Take the serial number from LINE and return it verbatim in a newly
449    allocated string.  We make sure that only hex characters are
450    returned. */
451 static char *
452 store_serialno (const char *line)
453 {
454   const char *s;
455   char *p;
456
457   for (s=line; hexdigitp (s); s++)
458     ;
459   p = xmalloc (s + 1 - line);
460   memcpy (p, line, s-line);
461   p[s-line] = 0;
462   return p;
463 }
464
465
466
467 static int
468 learn_status_cb (void *opaque, const char *line)
469 {
470   struct agent_card_info_s *parm = opaque;
471   const char *keyword = line;
472   int keywordlen;
473   int i;
474
475 /*   log_debug ("got status line `%s'\n", line); */
476   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
477     ;
478   while (spacep (line))
479     line++;
480
481   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
482     {
483       xfree (parm->serialno);
484       parm->serialno = store_serialno (line);
485     }
486   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
487     {
488       xfree (parm->disp_name);
489       parm->disp_name = unescape_status_string (line);
490     }
491   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
492     {
493       xfree (parm->disp_lang);
494       parm->disp_lang = unescape_status_string (line);
495     }
496   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
497     {
498       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
499     }
500   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
501     {
502       xfree (parm->pubkey_url);
503       parm->pubkey_url = unescape_status_string (line);
504     }
505   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
506     {
507       xfree (parm->login_data);
508       parm->login_data = unescape_status_string (line);
509     }
510   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
511     {
512       parm->sig_counter = strtoul (line, NULL, 0);
513     }
514   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
515     {
516       char *p, *buf;
517
518       buf = p = unescape_status_string (line);
519       if (buf)
520         {
521           while (spacep (p))
522             p++;
523           parm->chv1_cached = atoi (p);
524           while (*p && !spacep (p))
525             p++;
526           while (spacep (p))
527             p++;
528           for (i=0; *p && i < 3; i++)
529             {
530               parm->chvmaxlen[i] = atoi (p);
531               while (*p && !spacep (p))
532                 p++;
533               while (spacep (p))
534                 p++;
535             }
536           for (i=0; *p && i < 3; i++)
537             {
538               parm->chvretry[i] = atoi (p);
539               while (*p && !spacep (p))
540                 p++;
541               while (spacep (p))
542                 p++;
543             }
544           xfree (buf);
545         }
546     }
547   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
548     {
549       int no = atoi (line);
550       while (* line && !spacep (line))
551         line++;
552       while (spacep (line))
553         line++;
554       if (no == 1)
555         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
556       else if (no == 2)
557         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
558       else if (no == 3)
559         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
560     }
561   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
562     {
563       int no = atoi (line);
564       while (*line && !spacep (line))
565         line++;
566       while (spacep (line))
567         line++;
568       if (no == 1)
569         parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
570       else if (no == 2)
571         parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
572       else if (no == 3)
573         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
574     }
575   else if (keywordlen == 12 && !memcmp (keyword, "PRIVATE-DO-", 11)
576            && strchr ("1234", keyword[11]))
577     {
578       int no = keyword[11] - '1';
579       assert (no >= 0 && no <= 3);
580       xfree (parm->private_do[no]);
581       parm->private_do[no] = unescape_status_string (line);
582     }
583  
584   return 0;
585 }
586
587
588 /* Return card info. */
589 int 
590 agent_learn (struct agent_card_info_s *info)
591 {
592   APP app;
593   int rc;
594   struct ctrl_ctx_s ctrl;
595   time_t stamp;
596   char *serial;
597   
598   app = current_app? current_app : open_card ();
599   if (!app)
600     return gpg_error (GPG_ERR_CARD);
601
602   memset (info, 0, sizeof *info);
603   memset (&ctrl, 0, sizeof ctrl);
604   ctrl.status_cb = learn_status_cb;
605   ctrl.status_cb_arg = info;
606
607   rc = app_get_serial_and_stamp (app, &serial, &stamp);
608   if (!rc)
609     {
610       send_status_info (&ctrl, "SERIALNO", serial, strlen(serial), NULL, 0);
611       xfree (serial);
612       rc = app->fnc.learn_status (app, &ctrl);
613     }
614
615   return rc;
616 }
617
618 /* Get an attribite from the card. Make sure info is initialized. */
619 int 
620 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
621 {
622   APP app;
623   struct ctrl_ctx_s ctrl;
624
625   app = current_app? current_app : open_card ();
626   if (!app)
627     return gpg_error (GPG_ERR_CARD);
628
629   ctrl.status_cb = learn_status_cb;
630   ctrl.status_cb_arg = info;
631   return app->fnc.getattr (app, &ctrl, name);
632 }
633
634
635
636 static int 
637 pin_cb (void *opaque, const char *info, char **retstr)
638 {
639   char *value;
640   int canceled;
641   int isadmin = 0;
642   int newpin = 0;
643   const char *again_text = NULL;
644   const char *ends, *s;
645
646   *retstr = NULL;
647   log_debug ("asking for PIN '%s'\n", info);
648
649   /* We use a special prefix to check whether the Admin PIN has been
650      requested. */
651   if (info && *info =='|' && (ends=strchr (info+1, '|')))
652     {
653       for (s=info+1; s < ends; s++)
654         {
655           if (*s == 'A')
656             isadmin = 1;
657           else if (*s == 'N')
658             newpin = 1;
659         }
660       info = ends+1;
661     }
662
663  again:
664   if (is_status_enabled())
665     write_status_text (STATUS_NEED_PASSPHRASE_PIN,
666                        isadmin? "OPENPGP 3" : "OPENPGP 1");
667
668   value = ask_passphrase (info, again_text,
669                           newpin && isadmin? "passphrase.adminpin.new.ask" :
670                           newpin?  "passphrase.pin.new.ask" :
671                           isadmin? "passphrase.adminpin.ask" :
672                                    "passphrase.pin.ask", 
673                           newpin && isadmin? _("Enter New Admin PIN: ") :
674                           newpin?  _("Enter New PIN: ") :
675                           isadmin? _("Enter Admin PIN: ")
676                                  : _("Enter PIN: "),
677                           &canceled);
678   again_text = NULL;
679   if (!value && canceled)
680     return -1;
681   else if (!value)
682     return G10ERR_GENERAL;
683
684   if (newpin)
685     {
686       char *value2;
687
688       value2 = ask_passphrase (info, NULL,
689                                "passphrase.pin.repeat", 
690                                _("Repeat this PIN: "),
691                               &canceled);
692       if (!value && canceled)
693         {
694           xfree (value);
695           return -1;
696         }
697       else if (!value)
698         {
699           xfree (value);
700           return G10ERR_GENERAL;
701         }
702       if (strcmp (value, value2))
703         {
704           again_text = N_("PIN not correctly repeated; try again");
705           xfree (value2);
706           xfree (value);
707           value = NULL;
708           goto again;
709         }
710       xfree (value2);
711     }
712
713   *retstr = value;
714   return 0;
715 }
716
717
718
719 /* Send a SETATTR command to the SCdaemon. */
720 int 
721 agent_scd_setattr (const char *name,
722                    const unsigned char *value, size_t valuelen)
723 {
724   APP app;
725
726   app = current_app? current_app : open_card ();
727   if (!app)
728     return gpg_error (GPG_ERR_CARD);
729
730   return app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
731 }
732
733
734 static int
735 genkey_status_cb (void *opaque, const char *line)
736 {
737   struct agent_card_genkey_s *parm = opaque;
738   const char *keyword = line;
739   int keywordlen;
740
741 /*   log_debug ("got status line `%s'\n", line); */
742   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
743     ;
744   while (spacep (line))
745     line++;
746
747   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
748     {
749       parm->fprvalid = unhexify_fpr (line, parm->fpr);
750     }
751   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
752     {
753       MPI a;
754       const char *name = line;
755       char *buf;
756
757       while (*line && !spacep (line))
758         line++;
759       while (spacep (line))
760         line++;
761
762       buf = xmalloc ( 2 + strlen (line) + 1);
763       strcpy (stpcpy (buf, "0x"), line);
764       a = mpi_alloc (300);
765       if( mpi_fromstr (a, buf) )
766         log_error ("error parsing received key data\n");
767       else if (*name == 'n' && spacep (name+1))
768         parm->n = a;
769       else if (*name == 'e' && spacep (name+1))
770         parm->e = a;
771       else
772         {
773           log_info ("unknown parameter name in received key data\n");
774           mpi_free (a);
775         }
776       xfree (buf);
777     }
778   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
779     {
780       parm->created_at = (u32)strtoul (line, NULL, 10);
781     }
782
783   return 0;
784 }
785
786 /* Send a GENKEY command to the SCdaemon. */
787 int 
788 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
789 {
790   APP app;
791   char keynostr[20];
792   struct ctrl_ctx_s ctrl;
793
794   app = current_app? current_app : open_card ();
795   if (!app)
796     return gpg_error (GPG_ERR_CARD);
797
798   memset (info, 0, sizeof *info);
799   sprintf (keynostr, "%d", keyno);
800   ctrl.status_cb = genkey_status_cb;
801   ctrl.status_cb_arg = info;
802
803   return app->fnc.genkey (app, &ctrl, keynostr,
804                            force? 1:0,
805                            pin_cb, NULL);
806 }
807
808 /* Send a PKSIGN command to the SCdaemon. */
809 int 
810 agent_scd_pksign (const char *serialno, int hashalgo,
811                   const unsigned char *indata, size_t indatalen,
812                   unsigned char **r_buf, size_t *r_buflen)
813 {
814   APP app;
815   int rc;
816
817   *r_buf = NULL;
818   *r_buflen = 0;
819  retry:
820   app = current_app? current_app : open_card ();
821   if (!app)
822     return gpg_error (GPG_ERR_CARD);
823
824   /* Check that the card's serialnumber is as required.*/
825   rc = check_card_serialno (app, serialno);
826   if (rc == -1)
827     goto retry;
828   if (rc)
829     return rc;
830
831   return app->fnc.sign (app, serialno, hashalgo,
832                         pin_cb, NULL,
833                         indata, indatalen,
834                         r_buf, r_buflen);
835 }
836
837
838 /* Send a PKDECRYPT command to the SCdaemon. */
839 int 
840 agent_scd_pkdecrypt (const char *serialno,
841                      const unsigned char *indata, size_t indatalen,
842                      unsigned char **r_buf, size_t *r_buflen)
843 {
844   APP app;
845   int rc;
846
847   *r_buf = NULL;
848   *r_buflen = 0;
849  retry:
850   app = current_app? current_app : open_card ();
851   if (!app)
852     return gpg_error (GPG_ERR_CARD);
853
854   /* Check that the card's serialnumber is as required.*/
855   rc = check_card_serialno (app, serialno);
856   if (rc == -1)
857     goto retry;
858   if (rc)
859     return rc;
860
861   return app->fnc.decipher (app, serialno, 
862                             pin_cb, NULL,
863                             indata, indatalen,
864                             r_buf, r_buflen);
865 }
866
867 /* Change the PIN of an OpenPGP card or reset the retry counter. */
868 int 
869 agent_scd_change_pin (int chvno)
870 {
871   APP app;
872   char chvnostr[20];
873   int reset = 0;
874
875   reset = (chvno >= 100);
876   chvno %= 100;
877
878   app = current_app? current_app : open_card ();
879   if (!app)
880     return gpg_error (GPG_ERR_CARD);
881
882   sprintf (chvnostr, "%d", chvno);
883   return app->fnc.change_pin (app, NULL, chvnostr, reset,
884                               pin_cb, NULL);
885 }
886
887 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
888    number of the card - optionally followed by the fingerprint;
889    however the fingerprint is ignored here. */
890 int
891 agent_scd_checkpin (const char *serialnobuf)
892 {
893   APP app;
894
895   app = current_app? current_app : open_card ();
896   if (!app)
897     return gpg_error (GPG_ERR_CARD);
898
899   return app->fnc.check_pin (app, serialnobuf, pin_cb, NULL);
900 }
901
902
903 /* Wrapper to call the store key helper function of app-openpgp.c.  */
904 int 
905 agent_openpgp_storekey (int keyno,
906                         unsigned char *template, size_t template_len,
907                         time_t created_at,
908                         const unsigned char *m, size_t mlen,
909                         const unsigned char *e, size_t elen)
910 {
911   APP app;
912
913   app = current_app? current_app : open_card ();
914   if (!app)
915     return gpg_error (GPG_ERR_CARD);
916
917   return app_openpgp_storekey (app, keyno, template, template_len,
918                                created_at, m, mlen, e, elen,
919                                pin_cb, NULL);
920 }