* trustdb.h, keyedit.c (keyedit_menu, menu_select_uid_namehash): Allow
[gnupg.git] / g10 / cardglue.c
1 /* cardglue.c - mainly dispatcher for card related functions.
2  * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 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       write_status_text (STATUS_CARDCTRL, "4");
299       log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
300       apdu_close_reader (slot);
301       xfree (app);
302       return NULL;
303     }
304
305   app->initialized = 1;
306   current_app = app;
307   if (is_status_enabled () )
308     {
309       int i;
310       char *p, *buf;
311
312       buf = xmalloc (5 + app->serialnolen * 2 + 1);
313       p = stpcpy (buf, "3 ");
314       for (i=0; i < app->serialnolen; p +=2, i++)
315         sprintf (p, "%02X", app->serialno[i]);
316       write_status_text (STATUS_CARDCTRL, buf);
317       xfree (buf);
318     }
319
320   return app;
321 }
322
323 void
324 card_close (void)
325 {
326   if (current_app)
327     {
328       APP app = current_app;
329       current_app = NULL;
330
331       apdu_close_reader (app->slot);
332       xfree (app);
333     }
334 }
335
336
337 /* Check that the serial number of the current card (as described by
338    APP) matches SERIALNO.  If there is no match and we are not in
339    batch mode, present a prompt to insert the desired card.  The
340    function return 0 is the present card is okay, -1 if the user
341    selected to insert a new card or an error value.  Note that the
342    card context will be closed in all cases except for 0 as return
343    value and if it was possible to merely shutdown the reader. */
344 static int
345 check_card_serialno (APP app, const char *serialno)
346 {
347   const char *s;
348   int ask = 0;
349   int n;
350   
351   for (s = serialno, n=0; *s != '/' && hexdigitp (s); s++, n++)
352     ;
353   if (n != 32)
354     {
355       log_error ("invalid serial number in keyring detected\n");
356       return gpg_error (GPG_ERR_INV_ID);
357     }
358   if (app->serialnolen != 16)
359     ask = 1;
360   for (s = serialno, n=0; !ask && n < 16; s += 2, n++)
361     if (app->serialno[n] != xtoi_2 (s))
362       ask = 1;
363   if (ask)
364     {
365       char buf[5+32+1];
366       int did_shutdown = 0;
367
368       if (current_app && !apdu_shutdown_reader (current_app->slot))
369         did_shutdown = 1;
370       else
371         card_close ();
372       tty_printf (_("Please remove the current card and "
373                     "insert the one with serial number:\n"
374                     "   %.*s\n"), 32, serialno);
375
376       sprintf (buf, "1 %.32s", serialno);
377       write_status_text (STATUS_CARDCTRL, buf);
378
379       if ( cpr_get_answer_okay_cancel ("cardctrl.change_card.okay",
380                           _("Hit return when ready "
381                             "or enter 'c' to cancel: "),
382                                        1) )
383         {
384           card_close ();
385           return -1;
386         }
387       if (did_shutdown)
388         apdu_reset (current_app->slot);
389       else
390         card_close ();
391       return gpg_error (GPG_ERR_INV_ID);
392     }
393   return 0;
394 }
395
396
397
398 /* Return a new malloced string by unescaping the string S.  Escaping
399    is percent escaping and '+'/space mapping.  A binary nul will
400    silently be replaced by a 0xFF.  Function returns NULL to indicate
401    an out of memory status. */
402 static char *
403 unescape_status_string (const unsigned char *s)
404 {
405   char *buffer, *d;
406
407   buffer = d = xmalloc (strlen (s)+1);
408   while (*s)
409     {
410       if (*s == '%' && s[1] && s[2])
411         { 
412           s++;
413           *d = xtoi_2 (s);
414           if (!*d)
415             *d = '\xff';
416           d++;
417           s += 2;
418         }
419       else if (*s == '+')
420         {
421           *d++ = ' ';
422           s++;
423         }
424       else
425         *d++ = *s++;
426     }
427   *d = 0; 
428   return buffer;
429 }
430
431 /* Take a 20 byte hexencoded string and put it into the the provided
432    20 byte buffer FPR in binary format. */
433 static int
434 unhexify_fpr (const char *hexstr, unsigned char *fpr)
435 {
436   const char *s;
437   int n;
438
439   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
440     ;
441   if (*s || (n != 40))
442     return 0; /* no fingerprint (invalid or wrong length). */
443   n /= 2;
444   for (s=hexstr, n=0; *s; s += 2, n++)
445     fpr[n] = xtoi_2 (s);
446   return 1; /* okay */
447 }
448
449 /* Take the serial number from LINE and return it verbatim in a newly
450    allocated string.  We make sure that only hex characters are
451    returned. */
452 static char *
453 store_serialno (const char *line)
454 {
455   const char *s;
456   char *p;
457
458   for (s=line; hexdigitp (s); s++)
459     ;
460   p = xmalloc (s + 1 - line);
461   memcpy (p, line, s-line);
462   p[s-line] = 0;
463   return p;
464 }
465
466
467
468 static int
469 learn_status_cb (void *opaque, const char *line)
470 {
471   struct agent_card_info_s *parm = opaque;
472   const char *keyword = line;
473   int keywordlen;
474   int i;
475
476 /*   log_debug ("got status line `%s'\n", line); */
477   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
478     ;
479   while (spacep (line))
480     line++;
481
482   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
483     {
484       xfree (parm->serialno);
485       parm->serialno = store_serialno (line);
486     }
487   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
488     {
489       xfree (parm->disp_name);
490       parm->disp_name = unescape_status_string (line);
491     }
492   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
493     {
494       xfree (parm->disp_lang);
495       parm->disp_lang = unescape_status_string (line);
496     }
497   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
498     {
499       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
500     }
501   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
502     {
503       xfree (parm->pubkey_url);
504       parm->pubkey_url = unescape_status_string (line);
505     }
506   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
507     {
508       xfree (parm->login_data);
509       parm->login_data = unescape_status_string (line);
510     }
511   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
512     {
513       parm->sig_counter = strtoul (line, NULL, 0);
514     }
515   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
516     {
517       char *p, *buf;
518
519       buf = p = unescape_status_string (line);
520       if (buf)
521         {
522           while (spacep (p))
523             p++;
524           parm->chv1_cached = atoi (p);
525           while (*p && !spacep (p))
526             p++;
527           while (spacep (p))
528             p++;
529           for (i=0; *p && i < 3; i++)
530             {
531               parm->chvmaxlen[i] = atoi (p);
532               while (*p && !spacep (p))
533                 p++;
534               while (spacep (p))
535                 p++;
536             }
537           for (i=0; *p && i < 3; i++)
538             {
539               parm->chvretry[i] = atoi (p);
540               while (*p && !spacep (p))
541                 p++;
542               while (spacep (p))
543                 p++;
544             }
545           xfree (buf);
546         }
547     }
548   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
549     {
550       int no = atoi (line);
551       while (* line && !spacep (line))
552         line++;
553       while (spacep (line))
554         line++;
555       if (no == 1)
556         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
557       else if (no == 2)
558         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
559       else if (no == 3)
560         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
561     }
562   else if (keywordlen == 8 && !memcmp (keyword, "KEY-TIME", keywordlen))
563     {
564       int no = atoi (line);
565       while (* line && !spacep (line))
566         line++;
567       while (spacep (line))
568         line++;
569       if (no == 1)
570         parm->fpr1time = strtoul (line, NULL, 10);
571       else if (no == 2)
572         parm->fpr2time = strtoul (line, NULL, 10);
573       else if (no == 3)
574         parm->fpr3time = strtoul (line, NULL, 10);
575     }
576   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
577     {
578       int no = atoi (line);
579       while (*line && !spacep (line))
580         line++;
581       while (spacep (line))
582         line++;
583       if (no == 1)
584         parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
585       else if (no == 2)
586         parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
587       else if (no == 3)
588         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
589     }
590   else if (keywordlen == 12 && !memcmp (keyword, "PRIVATE-DO-", 11)
591            && strchr ("1234", keyword[11]))
592     {
593       int no = keyword[11] - '1';
594       assert (no >= 0 && no <= 3);
595       xfree (parm->private_do[no]);
596       parm->private_do[no] = unescape_status_string (line);
597     }
598  
599   return 0;
600 }
601
602
603 /* Return card info. */
604 int 
605 agent_learn (struct agent_card_info_s *info)
606 {
607   APP app;
608   int rc;
609   struct ctrl_ctx_s ctrl;
610   time_t stamp;
611   char *serial;
612   
613   app = current_app? current_app : open_card ();
614   if (!app)
615     return gpg_error (GPG_ERR_CARD);
616
617   memset (info, 0, sizeof *info);
618   memset (&ctrl, 0, sizeof ctrl);
619   ctrl.status_cb = learn_status_cb;
620   ctrl.status_cb_arg = info;
621
622   rc = app_get_serial_and_stamp (app, &serial, &stamp);
623   if (!rc)
624     {
625       send_status_info (&ctrl, "SERIALNO", serial, strlen(serial), NULL, 0);
626       xfree (serial);
627       rc = app->fnc.learn_status (app, &ctrl);
628     }
629
630   return rc;
631 }
632
633 /* Get an attribite from the card. Make sure info is initialized. */
634 int 
635 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
636 {
637   APP app;
638   struct ctrl_ctx_s ctrl;
639
640   app = current_app? current_app : open_card ();
641   if (!app)
642     return gpg_error (GPG_ERR_CARD);
643
644   ctrl.status_cb = learn_status_cb;
645   ctrl.status_cb_arg = info;
646   return app->fnc.getattr (app, &ctrl, name);
647 }
648
649
650
651 static int 
652 pin_cb (void *opaque, const char *info, char **retstr)
653 {
654   char *value;
655   int canceled;
656   int isadmin = 0;
657   int newpin = 0;
658   const char *again_text = NULL;
659   const char *ends, *s;
660
661   *retstr = NULL;
662   /*   log_debug ("asking for PIN '%s'\n", info); */
663
664   /* We use a special prefix to check whether the Admin PIN has been
665      requested. */
666   if (info && *info =='|' && (ends=strchr (info+1, '|')))
667     {
668       for (s=info+1; s < ends; s++)
669         {
670           if (*s == 'A')
671             isadmin = 1;
672           else if (*s == 'N')
673             newpin = 1;
674         }
675       info = ends+1;
676     }
677   else
678     log_debug ("pin_cb called without proper PIN info hack\n");
679
680  again:
681   if (is_status_enabled())
682     write_status_text (STATUS_NEED_PASSPHRASE_PIN,
683                        isadmin? "OPENPGP 3" : "OPENPGP 1");
684
685   value = ask_passphrase (info, again_text,
686                           newpin && isadmin? "passphrase.adminpin.new.ask" :
687                           newpin?  "passphrase.pin.new.ask" :
688                           isadmin? "passphrase.adminpin.ask" :
689                                    "passphrase.pin.ask", 
690                           newpin && isadmin? _("Enter New Admin PIN: ") :
691                           newpin?  _("Enter New PIN: ") :
692                           isadmin? _("Enter Admin PIN: ")
693                                  : _("Enter PIN: "),
694                           &canceled);
695   again_text = NULL;
696   if (!value && canceled)
697     return -1;
698   else if (!value)
699     return G10ERR_GENERAL;
700
701   if (newpin)
702     {
703       char *value2;
704
705       value2 = ask_passphrase (info, NULL,
706                                "passphrase.pin.repeat", 
707                                _("Repeat this PIN: "),
708                               &canceled);
709       if (!value && canceled)
710         {
711           xfree (value);
712           return -1;
713         }
714       else if (!value)
715         {
716           xfree (value);
717           return G10ERR_GENERAL;
718         }
719       if (strcmp (value, value2))
720         {
721           again_text = N_("PIN not correctly repeated; try again");
722           xfree (value2);
723           xfree (value);
724           value = NULL;
725           goto again;
726         }
727       xfree (value2);
728     }
729
730   *retstr = value;
731   return 0;
732 }
733
734
735
736 /* Send a SETATTR command to the SCdaemon. */
737 int 
738 agent_scd_setattr (const char *name,
739                    const unsigned char *value, size_t valuelen)
740 {
741   APP app;
742   int rc;
743
744   app = current_app? current_app : open_card ();
745   if (!app)
746     return gpg_error (GPG_ERR_CARD);
747
748   rc = app->fnc.setattr (app, name, pin_cb, NULL, value, valuelen);
749
750   if (rc)
751     write_status (STATUS_SC_OP_FAILURE);
752   return rc;
753 }
754
755
756 static int
757 genkey_status_cb (void *opaque, const char *line)
758 {
759   struct agent_card_genkey_s *parm = opaque;
760   const char *keyword = line;
761   int keywordlen;
762
763 /*   log_debug ("got status line `%s'\n", line); */
764   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
765     ;
766   while (spacep (line))
767     line++;
768
769   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
770     {
771       parm->fprvalid = unhexify_fpr (line, parm->fpr);
772     }
773   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
774     {
775       MPI a;
776       const char *name = line;
777       char *buf;
778
779       while (*line && !spacep (line))
780         line++;
781       while (spacep (line))
782         line++;
783
784       buf = xmalloc ( 2 + strlen (line) + 1);
785       strcpy (stpcpy (buf, "0x"), line);
786       a = mpi_alloc (300);
787       if( mpi_fromstr (a, buf) )
788         log_error ("error parsing received key data\n");
789       else if (*name == 'n' && spacep (name+1))
790         parm->n = a;
791       else if (*name == 'e' && spacep (name+1))
792         parm->e = a;
793       else
794         {
795           log_info ("unknown parameter name in received key data\n");
796           mpi_free (a);
797         }
798       xfree (buf);
799     }
800   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
801     {
802       parm->created_at = (u32)strtoul (line, NULL, 10);
803     }
804
805   return 0;
806 }
807
808 /* Send a GENKEY command to the SCdaemon. */
809 int 
810 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force)
811 {
812   APP app;
813   char keynostr[20];
814   struct ctrl_ctx_s ctrl;
815   int rc;
816
817   app = current_app? current_app : open_card ();
818   if (!app)
819     return gpg_error (GPG_ERR_CARD);
820
821   memset (info, 0, sizeof *info);
822   sprintf (keynostr, "%d", keyno);
823   ctrl.status_cb = genkey_status_cb;
824   ctrl.status_cb_arg = info;
825
826   rc = app->fnc.genkey (app, &ctrl, keynostr,
827                         force? 1:0,
828                         pin_cb, NULL);
829   if (rc)
830     write_status (STATUS_SC_OP_FAILURE);
831   return rc;
832 }
833
834 /* Send a PKSIGN command to the SCdaemon. */
835 int 
836 agent_scd_pksign (const char *serialno, int hashalgo,
837                   const unsigned char *indata, size_t indatalen,
838                   unsigned char **r_buf, size_t *r_buflen)
839 {
840   APP app;
841   int rc;
842
843   *r_buf = NULL;
844   *r_buflen = 0;
845  retry:
846   app = current_app? current_app : open_card ();
847   if (!app)
848     return gpg_error (GPG_ERR_CARD);
849
850   /* Check that the card's serialnumber is as required.*/
851   rc = check_card_serialno (app, serialno);
852   if (rc == -1)
853     goto retry;
854
855   if (!rc)
856     rc = app->fnc.sign (app, serialno, hashalgo,
857                         pin_cb, NULL,
858                         indata, indatalen,
859                         r_buf, r_buflen);
860   if (rc)
861     write_status (STATUS_SC_OP_FAILURE);
862   return rc;
863 }
864
865
866 /* Send a PKDECRYPT command to the SCdaemon. */
867 int 
868 agent_scd_pkdecrypt (const char *serialno,
869                      const unsigned char *indata, size_t indatalen,
870                      unsigned char **r_buf, size_t *r_buflen)
871 {
872   APP app;
873   int rc;
874
875   *r_buf = NULL;
876   *r_buflen = 0;
877  retry:
878   app = current_app? current_app : open_card ();
879   if (!app)
880     return gpg_error (GPG_ERR_CARD);
881
882   /* Check that the card's serialnumber is as required.*/
883   rc = check_card_serialno (app, serialno);
884   if (rc == -1)
885     goto retry;
886
887   if (!rc)
888     rc = app->fnc.decipher (app, serialno, 
889                             pin_cb, NULL,
890                             indata, indatalen,
891                             r_buf, r_buflen);
892   if (rc)
893     write_status (STATUS_SC_OP_FAILURE);
894   return rc;
895 }
896
897 /* Change the PIN of an OpenPGP card or reset the retry counter. */
898 int 
899 agent_scd_change_pin (int chvno)
900 {
901   APP app;
902   char chvnostr[20];
903   int reset = 0;
904   int rc;
905
906   reset = (chvno >= 100);
907   chvno %= 100;
908
909   app = current_app? current_app : open_card ();
910   if (!app)
911     return gpg_error (GPG_ERR_CARD);
912
913   sprintf (chvnostr, "%d", chvno);
914   rc = app->fnc.change_pin (app, NULL, chvnostr, reset,
915                             pin_cb, NULL);
916   if (rc)
917     write_status (STATUS_SC_OP_FAILURE);
918   return rc;
919 }
920
921 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
922    number of the card - optionally followed by the fingerprint;
923    however the fingerprint is ignored here. */
924 int
925 agent_scd_checkpin (const char *serialnobuf)
926 {
927   APP app;
928   int rc;
929
930   app = current_app? current_app : open_card ();
931   if (!app)
932     return gpg_error (GPG_ERR_CARD);
933
934   rc = app->fnc.check_pin (app, serialnobuf, pin_cb, NULL);
935   if (rc)
936     write_status (STATUS_SC_OP_FAILURE);
937   return rc;
938 }
939
940
941 /* Wrapper to call the store key helper function of app-openpgp.c.  */
942 int 
943 agent_openpgp_storekey (int keyno,
944                         unsigned char *template, size_t template_len,
945                         time_t created_at,
946                         const unsigned char *m, size_t mlen,
947                         const unsigned char *e, size_t elen)
948 {
949   APP app;
950   int rc;
951
952   app = current_app? current_app : open_card ();
953   if (!app)
954     return gpg_error (GPG_ERR_CARD);
955
956   rc = app_openpgp_storekey (app, keyno, template, template_len,
957                              created_at, m, mlen, e, elen,
958                              pin_cb, NULL);
959   if (rc)
960     write_status (STATUS_SC_OP_FAILURE);
961   return rc;
962 }