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