Emit CARDCTRL status lines.
[gnupg.git] / g10 / call-agent.c
1 /* call-agent.c - Divert GPG operations to the agent.
2  * Copyright (C) 2001, 2002, 2003, 2006, 2007, 
3  *               2008 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h> 
27 #include <time.h>
28 #include <assert.h>
29 #ifdef HAVE_LOCALE_H
30 #include <locale.h>
31 #endif
32 #include <assuan.h>
33
34 #include "gpg.h"
35 #include "util.h"
36 #include "membuf.h"
37 #include "options.h"
38 #include "i18n.h"
39 #include "asshelp.h"
40 #include "sysutils.h"
41 #include "call-agent.h"
42 #include "status.h"
43
44 #ifndef DBG_ASSUAN
45 # define DBG_ASSUAN 1
46 #endif
47
48 static assuan_context_t agent_ctx = NULL;
49 static int did_early_card_test;
50
51 struct cipher_parm_s 
52 {
53   assuan_context_t ctx;
54   const char *ciphertext;
55   size_t ciphertextlen;
56 };
57
58 struct writecert_parm_s
59 {
60   assuan_context_t ctx;
61   const unsigned char *certdata;
62   size_t certdatalen;
63 };
64
65 struct writekey_parm_s
66 {
67   assuan_context_t ctx;
68   const unsigned char *keydata;
69   size_t keydatalen;
70 };
71
72 struct genkey_parm_s 
73 {
74   assuan_context_t ctx;
75   const char *sexp;
76   size_t sexplen;
77 };
78
79
80 static int learn_status_cb (void *opaque, const char *line);
81
82
83 \f
84 /* If RC is not 0, write an appropriate status message. */
85 static void
86 status_sc_op_failure (int rc)
87 {
88   switch (gpg_err_code (rc))
89     {
90     case 0:
91       break;
92     case GPG_ERR_CANCELED:
93       write_status_text (STATUS_SC_OP_FAILURE, "1");
94       break;
95     case GPG_ERR_BAD_PIN:
96       write_status_text (STATUS_SC_OP_FAILURE, "2");
97       break;
98     default:
99       write_status (STATUS_SC_OP_FAILURE);
100       break;
101     }
102 }  
103
104
105
106
107 /* Try to connect to the agent via socket or fork it off and work by
108    pipes.  Handle the server's initial greeting */
109 static int
110 start_agent (int for_card)
111 {
112   int rc;
113
114   /* Fixme: We need a context for each thread or serialize the access
115      to the agent. */
116   if (agent_ctx)
117     rc = 0;
118   else
119     {
120       rc = start_new_gpg_agent (&agent_ctx,
121                                 GPG_ERR_SOURCE_DEFAULT,
122                                 opt.homedir,
123                                 opt.agent_program,
124                                 opt.lc_ctype, opt.lc_messages,
125                                 opt.session_env,
126                                 opt.verbose, DBG_ASSUAN,
127                                 NULL, NULL);
128       if (!rc)
129         {
130           /* Tell the agent that we support Pinentry notifications.
131              No error checking so that it will work also with older
132              agents.  */
133           assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
134                            NULL, NULL, NULL, NULL, NULL, NULL);
135         }
136     }
137
138   if (!rc && for_card && !did_early_card_test)
139     {
140       /* Request the serial number of the card for an early test.  */
141       struct agent_card_info_s info;
142
143       memset (&info, 0, sizeof info);
144       rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
145                             NULL, NULL, NULL, NULL,
146                             learn_status_cb, &info);
147       if (rc)
148         {
149           switch (gpg_err_code (rc))
150             {
151             case GPG_ERR_NOT_SUPPORTED:
152             case GPG_ERR_NO_SCDAEMON:
153               write_status_text (STATUS_CARDCTRL, "6");
154               break;
155             default:
156               write_status_text (STATUS_CARDCTRL, "4");
157               log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
158               break;
159             }
160         }
161
162       if (!rc && is_status_enabled () && info.serialno)
163         {
164           char *buf;
165           
166           buf = xasprintf ("3 %s", info.serialno);
167           write_status_text (STATUS_CARDCTRL, buf);
168           xfree (buf);
169         }
170
171       agent_release_card_info (&info);
172
173       if (!rc)
174         did_early_card_test = 1;
175     }
176
177   
178   return rc;
179 }
180
181
182 /* Return a new malloced string by unescaping the string S.  Escaping
183    is percent escaping and '+'/space mapping.  A binary nul will
184    silently be replaced by a 0xFF.  Function returns NULL to indicate
185    an out of memory status. */
186 static char *
187 unescape_status_string (const unsigned char *s)
188 {
189   return percent_plus_unescape (s, 0xff);
190 }
191
192
193 /* Take a 20 byte hexencoded string and put it into the the provided
194    20 byte buffer FPR in binary format. */
195 static int
196 unhexify_fpr (const char *hexstr, unsigned char *fpr)
197 {
198   const char *s;
199   int n;
200
201   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
202     ;
203   if (*s || (n != 40))
204     return 0; /* no fingerprint (invalid or wrong length). */
205   for (s=hexstr, n=0; *s; s += 2, n++)
206     fpr[n] = xtoi_2 (s);
207   return 1; /* okay */
208 }
209
210 /* Take the serial number from LINE and return it verbatim in a newly
211    allocated string.  We make sure that only hex characters are
212    returned. */
213 static char *
214 store_serialno (const char *line)
215 {
216   const char *s;
217   char *p;
218
219   for (s=line; hexdigitp (s); s++)
220     ;
221   p = xtrymalloc (s + 1 - line);
222   if (p)
223     {
224       memcpy (p, line, s-line);
225       p[s-line] = 0;
226     }
227   return p;
228 }
229
230
231 \f
232 /* This is a dummy data line callback.  */
233 static int
234 dummy_data_cb (void *opaque, const void *buffer, size_t length)
235 {
236   (void)opaque;
237   (void)buffer;
238   (void)length;
239   return 0;
240 }
241
242
243 /* This is the default inquiry callback.  It mainly handles the
244    Pinentry notifications.  */
245 static int
246 default_inq_cb (void *opaque, const char *line)
247 {
248   (void)opaque;
249
250   if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
251     {
252       /* There is no working server mode yet thus we use
253          AllowSetForegroundWindow window right here.  We might want to
254          do this anyway in case gpg is called on the console. */
255       gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
256       /* We do not pass errors to avoid breaking other code.  */
257     }
258   else
259     log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
260
261   return 0;
262 }
263
264
265
266 /* Release the card info structure INFO. */
267 void
268 agent_release_card_info (struct agent_card_info_s *info)
269 {
270   if (!info)
271     return;
272
273   xfree (info->serialno); info->serialno = NULL;
274   xfree (info->apptype); info->apptype = NULL;
275   xfree (info->disp_name); info->disp_name = NULL;
276   xfree (info->disp_lang); info->disp_lang = NULL;
277   xfree (info->pubkey_url); info->pubkey_url = NULL;
278   xfree (info->login_data); info->login_data = NULL;
279   info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
280   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
281 }
282
283 static int
284 learn_status_cb (void *opaque, const char *line)
285 {
286   struct agent_card_info_s *parm = opaque;
287   const char *keyword = line;
288   int keywordlen;
289   int i;
290
291   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
292     ;
293   while (spacep (line))
294     line++;
295
296   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
297     {
298       xfree (parm->serialno);
299       parm->serialno = store_serialno (line);
300       parm->is_v2 = (strlen (parm->serialno) >= 16 
301                      && xtoi_2 (parm->serialno+12) >= 2 );
302     }
303   else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
304     {
305       xfree (parm->apptype);
306       parm->apptype = unescape_status_string (line);
307     }
308   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
309     {
310       xfree (parm->disp_name);
311       parm->disp_name = unescape_status_string (line);
312     }
313   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
314     {
315       xfree (parm->disp_lang);
316       parm->disp_lang = unescape_status_string (line);
317     }
318   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
319     {
320       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
321     }
322   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
323     {
324       xfree (parm->pubkey_url);
325       parm->pubkey_url = unescape_status_string (line);
326     }
327   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
328     {
329       xfree (parm->login_data);
330       parm->login_data = unescape_status_string (line);
331     }
332   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
333     {
334       parm->sig_counter = strtoul (line, NULL, 0);
335     }
336   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
337     {
338       char *p, *buf;
339
340       buf = p = unescape_status_string (line);
341       if (buf)
342         {
343           while (spacep (p))
344             p++;
345           parm->chv1_cached = atoi (p);
346           while (*p && !spacep (p))
347             p++;
348           while (spacep (p))
349             p++;
350           for (i=0; *p && i < 3; i++)
351             {
352               parm->chvmaxlen[i] = atoi (p);
353               while (*p && !spacep (p))
354                 p++;
355               while (spacep (p))
356                 p++;
357             }
358           for (i=0; *p && i < 3; i++)
359             {
360               parm->chvretry[i] = atoi (p);
361               while (*p && !spacep (p))
362                 p++;
363               while (spacep (p))
364                 p++;
365             }
366           xfree (buf);
367         }
368     }
369   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
370     {
371       int no = atoi (line);
372       while (*line && !spacep (line))
373         line++;
374       while (spacep (line))
375         line++;
376       if (no == 1)
377         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
378       else if (no == 2)
379         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
380       else if (no == 3)
381         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
382     }
383   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
384     {
385       int no = atoi (line);
386       while (*line && !spacep (line))
387         line++;
388       while (spacep (line))
389         line++;
390       if (no == 1)
391         parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
392       else if (no == 2)
393         parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
394       else if (no == 3)
395         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
396     }
397   else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
398     {
399       int keyno, algo, nbits;
400
401       sscanf (line, "%d %d %d", &keyno, &algo, &nbits);
402       keyno--;
403       if (keyno >= 0 && keyno < DIM (parm->key_attr))
404         {
405           parm->key_attr[keyno].algo = algo;
406           parm->key_attr[keyno].nbits = nbits;
407         }
408     }
409
410   return 0;
411 }
412
413 /* Call the agent to learn about a smartcard */
414 int
415 agent_learn (struct agent_card_info_s *info)
416 {
417   int rc;
418
419   rc = start_agent (1);
420   if (rc)
421     return rc;
422
423   memset (info, 0, sizeof *info);
424   rc = assuan_transact (agent_ctx, "SCD LEARN --force",
425                         dummy_data_cb, NULL, default_inq_cb, NULL,
426                         learn_status_cb, info);
427   /* Also try to get the key attributes.  */
428   if (!rc)
429     agent_scd_getattr ("KEY-ATTR", info);
430   
431   return rc;
432 }
433
434 /* Call the agent to retrieve a data object.  This function returns
435    the data in the same structure as used by the learn command.  It is
436    allowed to update such a structure using this commmand. */
437 int
438 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
439 {
440   int rc;
441   char line[ASSUAN_LINELENGTH];
442
443   if (!*name)
444     return gpg_error (GPG_ERR_INV_VALUE);
445
446   /* We assume that NAME does not need escaping. */
447   if (12 + strlen (name) > DIM(line)-1)
448     return gpg_error (GPG_ERR_TOO_LARGE);
449   stpcpy (stpcpy (line, "SCD GETATTR "), name); 
450
451   rc = start_agent (1);
452   if (rc)
453     return rc;
454
455   rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
456                         learn_status_cb, info);
457   
458   return rc;
459 }
460
461 \f
462 /* Send an setattr command to the SCdaemon.  SERIALNO is not actually
463    used here but required by gpg 1.4's implementation of this code in
464    cardglue.c. */
465 int
466 agent_scd_setattr (const char *name,
467                    const unsigned char *value, size_t valuelen,
468                    const char *serialno)
469 {
470   int rc;
471   char line[ASSUAN_LINELENGTH];
472   char *p;
473
474   (void)serialno;
475
476   if (!*name || !valuelen)
477     return gpg_error (GPG_ERR_INV_VALUE);
478
479   /* We assume that NAME does not need escaping. */
480   if (12 + strlen (name) > DIM(line)-1)
481     return gpg_error (GPG_ERR_TOO_LARGE);
482       
483   p = stpcpy (stpcpy (line, "SCD SETATTR "), name); 
484   *p++ = ' ';
485   for (; valuelen; value++, valuelen--)
486     {
487       if (p >= line + DIM(line)-5 )
488         return gpg_error (GPG_ERR_TOO_LARGE);
489       if (*value < ' ' || *value == '+' || *value == '%')
490         {
491           sprintf (p, "%%%02X", *value);
492           p += 3;
493         }
494       else if (*value == ' ')
495         *p++ = '+';
496       else
497         *p++ = *value;
498     }
499   *p = 0;
500
501   rc = start_agent (1);
502   if (!rc)
503     {
504       rc = assuan_transact (agent_ctx, line, NULL, NULL, 
505                             default_inq_cb, NULL, NULL, NULL);
506     }
507
508   status_sc_op_failure (rc);
509   return rc;
510 }
511
512
513 \f
514 /* Handle a CERTDATA inquiry.  Note, we only send the data,
515    assuan_transact takes care of flushing and writing the END
516    command. */
517 static int
518 inq_writecert_parms (void *opaque, const char *line)
519 {
520   int rc;
521   struct writecert_parm_s *parm = opaque; 
522
523   if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
524     {
525       rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
526     }
527   else
528     rc = default_inq_cb (opaque, line);
529
530   return rc;
531 }
532
533
534 /* Send a WRITECERT command to the SCdaemon. */
535 int 
536 agent_scd_writecert (const char *certidstr,
537                      const unsigned char *certdata, size_t certdatalen)
538 {
539   int rc;
540   char line[ASSUAN_LINELENGTH];
541   struct writecert_parm_s parms;
542
543   rc = start_agent (1);
544   if (rc)
545     return rc;
546
547   memset (&parms, 0, sizeof parms);
548
549   snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
550   line[DIM(line)-1] = 0;
551   parms.ctx = agent_ctx;
552   parms.certdata = certdata;
553   parms.certdatalen = certdatalen;
554   
555   rc = assuan_transact (agent_ctx, line, NULL, NULL,
556                         inq_writecert_parms, &parms, NULL, NULL);
557
558   return rc;
559 }
560
561
562 \f
563 /* Handle a KEYDATA inquiry.  Note, we only send the data,
564    assuan_transact takes care of flushing and writing the end */
565 static int
566 inq_writekey_parms (void *opaque, const char *line)
567 {
568   int rc;
569   struct writekey_parm_s *parm = opaque; 
570
571   if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
572     {
573       rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
574     }
575   else
576     rc = default_inq_cb (opaque, line);
577
578   return rc;
579 }
580
581
582 /* Send a WRITEKEY command to the SCdaemon. */
583 int 
584 agent_scd_writekey (int keyno, const char *serialno,
585                     const unsigned char *keydata, size_t keydatalen)
586 {
587   int rc;
588   char line[ASSUAN_LINELENGTH];
589   struct writekey_parm_s parms;
590
591   (void)serialno;
592
593   rc = start_agent (1);
594   if (rc)
595     return rc;
596
597   memset (&parms, 0, sizeof parms);
598
599   snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
600   line[DIM(line)-1] = 0;
601   parms.ctx = agent_ctx;
602   parms.keydata = keydata;
603   parms.keydatalen = keydatalen;
604   
605   rc = assuan_transact (agent_ctx, line, NULL, NULL,
606                         inq_writekey_parms, &parms, NULL, NULL);
607
608   status_sc_op_failure (rc);
609   return rc;
610 }
611
612
613 \f
614 /* Status callback for the SCD GENKEY command. */
615 static int
616 scd_genkey_cb (void *opaque, const char *line)
617 {
618   struct agent_card_genkey_s *parm = opaque;
619   const char *keyword = line;
620   int keywordlen;
621   gpg_error_t rc;
622
623   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
624     ;
625   while (spacep (line))
626     line++;
627
628   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
629     {
630       parm->fprvalid = unhexify_fpr (line, parm->fpr);
631     }
632   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
633     {
634       gcry_mpi_t a;
635       const char *name = line;
636
637       while (*line && !spacep (line))
638         line++;
639       while (spacep (line))
640         line++;
641
642       rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
643       if (rc)
644         log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
645       else if (*name == 'n' && spacep (name+1))
646         parm->n = a;
647       else if (*name == 'e' && spacep (name+1))
648         parm->e = a;
649       else
650         {
651           log_info ("unknown parameter name in received key data\n");
652           gcry_mpi_release (a);
653         }
654     }
655   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
656     {
657       parm->created_at = (u32)strtoul (line, NULL, 10);
658     }
659
660   return 0;
661 }
662
663 /* Send a GENKEY command to the SCdaemon.  SERIALNO is not used in
664    this implementation.  If CREATEDATE has been given, it will be
665    passed to SCDAEMON so that the key can be created with this
666    timestamp; note the user needs to use the returned timestamp as old
667    versions of scddaemon don't support this option.  */
668 int
669 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
670                   const char *serialno, u32 createtime)
671 {
672   int rc;
673   char line[ASSUAN_LINELENGTH];
674   gnupg_isotime_t tbuf;
675
676   (void)serialno;
677
678   rc = start_agent (1);
679   if (rc)
680     return rc;
681
682   if (createtime)
683     epoch2isotime (tbuf, createtime);
684   else
685     *tbuf = 0;
686
687   memset (info, 0, sizeof *info);
688   snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
689             *tbuf? "--timestamp=":"", tbuf,
690             force? "--force":"", 
691             keyno);
692   line[DIM(line)-1] = 0;
693
694   memset (info, 0, sizeof *info);
695   rc = assuan_transact (agent_ctx, line,
696                         NULL, NULL, default_inq_cb, NULL,
697                         scd_genkey_cb, info);
698   
699   status_sc_op_failure (rc);
700   return rc;
701 }
702
703 \f
704 static int
705 membuf_data_cb (void *opaque, const void *buffer, size_t length)
706 {
707   membuf_t *data = opaque;
708
709   if (buffer)
710     put_membuf (data, buffer, length);
711   return 0;
712 }
713   
714 /* Send a sign command to the scdaemon via gpg-agent's pass thru
715    mechanism. */
716 int
717 agent_scd_pksign (const char *serialno, int hashalgo,
718                   const unsigned char *indata, size_t indatalen,
719                   unsigned char **r_buf, size_t *r_buflen)
720 {
721   int rc, i;
722   char *p, line[ASSUAN_LINELENGTH];
723   membuf_t data;
724   size_t len;
725
726   /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
727
728   *r_buf = NULL;
729   *r_buflen = 0;
730
731   rc = start_agent (1);
732   if (rc)
733     return rc;
734
735   if (indatalen*2 + 50 > DIM(line))
736     return gpg_error (GPG_ERR_GENERAL);
737
738   /* Send the serialno command to initialize the connection. We don't
739      care about the data returned.  If the card has already been
740      initialized, this is a very fast command.  We request the openpgp
741      card because that is what we expect. */
742   rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
743                         NULL, NULL, NULL, NULL, NULL, NULL);
744   if (rc)
745     return rc;
746
747   sprintf (line, "SCD SETDATA ");
748   p = line + strlen (line);
749   for (i=0; i < indatalen ; i++, p += 2 )
750     sprintf (p, "%02X", indata[i]);
751   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
752   if (rc)
753     return rc;
754
755   init_membuf (&data, 1024);
756 #if 0
757   if (!hashalgo) /* Temporary test hack. */
758     snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
759   else
760 #endif
761     snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
762               hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
763               serialno);
764   line[DIM(line)-1] = 0;
765   rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
766                         default_inq_cb, NULL, NULL, NULL);
767   if (rc)
768     {
769       xfree (get_membuf (&data, &len));
770     }
771   else
772     *r_buf = get_membuf (&data, r_buflen);
773
774   status_sc_op_failure (rc);
775   return rc;
776 }
777
778
779 /* Decrypt INDATA of length INDATALEN using the card identified by
780    SERIALNO.  Return the plaintext in a nwly allocated buffer stored
781    at the address of R_BUF. 
782
783    Note, we currently support only RSA or more exactly algorithms
784    taking one input data element. */
785 int
786 agent_scd_pkdecrypt (const char *serialno,
787                      const unsigned char *indata, size_t indatalen,
788                      unsigned char **r_buf, size_t *r_buflen)
789 {
790   int rc, i;
791   char *p, line[ASSUAN_LINELENGTH];
792   membuf_t data;
793   size_t len;
794
795   *r_buf = NULL;
796   rc = start_agent (1);
797   if (rc)
798     return rc;
799
800   /* FIXME: use secure memory where appropriate */
801   if (indatalen*2 + 50 > DIM(line))
802     return gpg_error (GPG_ERR_GENERAL);
803
804   /* Send the serialno command to initialize the connection. We don't
805      care about the data returned.  If the card has already been
806      initialized, this is a very fast command.  We request the openpgp
807      card because that is what we expect. */
808   rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
809                         NULL, NULL, NULL, NULL, NULL, NULL);
810   if (rc)
811     return rc;
812
813   sprintf (line, "SCD SETDATA ");
814   p = line + strlen (line);
815   for (i=0; i < indatalen ; i++, p += 2 )
816     sprintf (p, "%02X", indata[i]);
817   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
818   if (rc)
819     return rc;
820
821   init_membuf (&data, 1024);
822   snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
823   line[DIM(line)-1] = 0;
824   rc = assuan_transact (agent_ctx, line,
825                         membuf_data_cb, &data,
826                         default_inq_cb, NULL, NULL, NULL);
827   if (rc)
828     {
829       xfree (get_membuf (&data, &len));
830     }
831   else
832     {
833       *r_buf = get_membuf (&data, r_buflen);
834       if (!*r_buf)
835         rc = gpg_error (GPG_ERR_ENOMEM);
836     }
837
838   status_sc_op_failure (rc);
839   return rc;
840 }
841
842
843 \f
844 /* Send a READCERT command to the SCdaemon. */
845 int 
846 agent_scd_readcert (const char *certidstr,
847                     void **r_buf, size_t *r_buflen)
848 {
849   int rc;
850   char line[ASSUAN_LINELENGTH];
851   membuf_t data;
852   size_t len;
853
854   *r_buf = NULL;
855   rc = start_agent (1);
856   if (rc)
857     return rc;
858
859   init_membuf (&data, 2048);
860
861   snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
862   line[DIM(line)-1] = 0;
863   rc = assuan_transact (agent_ctx, line,
864                         membuf_data_cb, &data,
865                         default_inq_cb, NULL, NULL, NULL);
866   if (rc)
867     {
868       xfree (get_membuf (&data, &len));
869       return rc;
870     }
871   *r_buf = get_membuf (&data, r_buflen);
872   if (!*r_buf)
873     return gpg_error (GPG_ERR_ENOMEM);
874
875   return 0;
876 }
877
878
879 \f
880 /* Change the PIN of an OpenPGP card or reset the retry counter.
881    CHVNO 1: Change the PIN
882          2: For v1 cards: Same as 1.
883             For v2 cards: Reset the PIN using the Reset Code.
884          3: Change the admin PIN
885        101: Set a new PIN and reset the retry counter
886        102: For v1 cars: Same as 101.
887             For v2 cards: Set a new Reset Code.
888    SERIALNO is not used.
889  */
890 int
891 agent_scd_change_pin (int chvno, const char *serialno)
892 {
893   int rc;
894   char line[ASSUAN_LINELENGTH];
895   const char *reset = "";
896
897   (void)serialno;
898
899   if (chvno >= 100)
900     reset = "--reset";
901   chvno %= 100;
902
903   rc = start_agent (1);
904   if (rc)
905     return rc;
906
907   snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
908   line[DIM(line)-1] = 0;
909   rc = assuan_transact (agent_ctx, line, NULL, NULL,
910                         default_inq_cb, NULL, NULL, NULL);
911   status_sc_op_failure (rc);
912   return rc;
913 }
914
915
916 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
917    number of the card - optionally followed by the fingerprint;
918    however the fingerprint is ignored here. */
919 int
920 agent_scd_checkpin  (const char *serialno)
921 {
922   int rc;
923   char line[ASSUAN_LINELENGTH];
924
925   rc = start_agent (1);
926   if (rc)
927     return rc;
928
929   snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
930   line[DIM(line)-1] = 0;
931   rc = assuan_transact (agent_ctx, line,
932                         NULL, NULL,
933                         default_inq_cb, NULL, NULL, NULL);
934   status_sc_op_failure (rc);
935   return rc;
936 }
937
938
939 /* Dummy function, only used by the gpg 1.4 implementation. */
940 void
941 agent_clear_pin_cache (const char *sn)
942 {
943   (void)sn;
944 }
945
946
947
948 \f
949 /* Note: All strings shall be UTF-8. On success the caller needs to
950    free the string stored at R_PASSPHRASE. On error NULL will be
951    stored at R_PASSPHRASE and an appropriate fpf error code
952    returned. */
953 gpg_error_t
954 agent_get_passphrase (const char *cache_id,
955                       const char *err_msg,
956                       const char *prompt,
957                       const char *desc_msg,
958                       int repeat,
959                       int check,
960                       char **r_passphrase)
961 {
962   int rc;
963   char line[ASSUAN_LINELENGTH];
964   char *arg1 = NULL;
965   char *arg2 = NULL;  
966   char *arg3 = NULL; 
967   char *arg4 = NULL;
968   membuf_t data;
969
970   *r_passphrase = NULL;
971
972   rc = start_agent (0);
973   if (rc)
974     return rc;
975
976   /* Check that the gpg-agent understands the repeat option.  */
977   if (assuan_transact (agent_ctx, 
978                        "GETINFO cmd_has_option GET_PASSPHRASE repeat",
979                        NULL, NULL, NULL, NULL, NULL, NULL))
980     return gpg_error (GPG_ERR_NOT_SUPPORTED);
981
982   if (cache_id && *cache_id)
983     if (!(arg1 = percent_plus_escape (cache_id)))
984       goto no_mem;
985   if (err_msg && *err_msg)
986     if (!(arg2 = percent_plus_escape (err_msg)))
987       goto no_mem;
988   if (prompt && *prompt)
989     if (!(arg3 = percent_plus_escape (prompt)))
990       goto no_mem;
991   if (desc_msg && *desc_msg)
992     if (!(arg4 = percent_plus_escape (desc_msg)))
993       goto no_mem;
994
995   snprintf (line, DIM(line)-1, 
996             "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s", 
997             repeat, 
998             check? " --check --qualitybar":"",
999             arg1? arg1:"X",
1000             arg2? arg2:"X",
1001             arg3? arg3:"X",
1002             arg4? arg4:"X");
1003   line[DIM(line)-1] = 0;
1004   xfree (arg1);
1005   xfree (arg2);
1006   xfree (arg3);
1007   xfree (arg4);
1008
1009   init_membuf_secure (&data, 64);
1010   rc = assuan_transact (agent_ctx, line, 
1011                         membuf_data_cb, &data,
1012                         default_inq_cb, NULL, NULL, NULL);
1013
1014   if (rc)
1015     xfree (get_membuf (&data, NULL));
1016   else 
1017     {
1018       put_membuf (&data, "", 1);
1019       *r_passphrase = get_membuf (&data, NULL);
1020       if (!*r_passphrase)
1021         rc = gpg_error_from_syserror ();
1022     }
1023   return rc;
1024  no_mem:
1025   rc = gpg_error_from_syserror ();
1026   xfree (arg1);
1027   xfree (arg2);
1028   xfree (arg3);
1029   xfree (arg4);
1030   return rc;
1031 }
1032
1033
1034 gpg_error_t
1035 agent_clear_passphrase (const char *cache_id)
1036 {
1037   int rc;
1038   char line[ASSUAN_LINELENGTH];
1039
1040   if (!cache_id || !*cache_id)
1041     return 0;
1042
1043   rc = start_agent (0);
1044   if (rc)
1045     return rc;
1046
1047   snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
1048   line[DIM(line)-1] = 0;
1049   return assuan_transact (agent_ctx, line, NULL, NULL,
1050                           default_inq_cb, NULL, NULL, NULL);
1051 }