Create a pkcs#10 request directly from a card.
[gnupg.git] / g10 / call-agent.c
blob0590514df84b59760506d3bdd1fd25b614ec5b8d
1 /* call-agent.c - Divert GPG operations to the agent.
2 * Copyright (C) 2001, 2002, 2003, 2006, 2007,
3 * 2008 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
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.
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.
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/>.
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>
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"
43 #ifndef DBG_ASSUAN
44 # define DBG_ASSUAN 1
45 #endif
47 static assuan_context_t agent_ctx = NULL;
49 struct cipher_parm_s
51 assuan_context_t ctx;
52 const char *ciphertext;
53 size_t ciphertextlen;
56 struct writecert_parm_s
58 assuan_context_t ctx;
59 const unsigned char *certdata;
60 size_t certdatalen;
63 struct writekey_parm_s
65 assuan_context_t ctx;
66 const unsigned char *keydata;
67 size_t keydatalen;
70 struct genkey_parm_s
72 assuan_context_t ctx;
73 const char *sexp;
74 size_t sexplen;
79 /* Try to connect to the agent via socket or fork it off and work by
80 pipes. Handle the server's initial greeting */
81 static int
82 start_agent (void)
84 int rc;
86 if (agent_ctx)
87 return 0; /* Fixme: We need a context for each thread or serialize
88 the access to the agent. */
90 rc = start_new_gpg_agent (&agent_ctx,
91 GPG_ERR_SOURCE_DEFAULT,
92 opt.homedir,
93 opt.agent_program,
94 opt.display, opt.ttyname, opt.ttytype,
95 opt.lc_ctype, opt.lc_messages,
96 opt.xauthority, opt.pinentry_user_data,
97 opt.verbose, DBG_ASSUAN,
98 NULL, NULL);
99 if (!rc)
101 /* Tell the agent that we support Pinentry notifications. No
102 error checking so that it will work also with older
103 agents. */
104 assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
105 NULL, NULL, NULL, NULL, NULL, NULL);
108 return rc;
112 /* Return a new malloced string by unescaping the string S. Escaping
113 is percent escaping and '+'/space mapping. A binary nul will
114 silently be replaced by a 0xFF. Function returns NULL to indicate
115 an out of memory status. */
116 static char *
117 unescape_status_string (const unsigned char *s)
119 return percent_plus_unescape (s, 0xff);
123 /* Take a 20 byte hexencoded string and put it into the the provided
124 20 byte buffer FPR in binary format. */
125 static int
126 unhexify_fpr (const char *hexstr, unsigned char *fpr)
128 const char *s;
129 int n;
131 for (s=hexstr, n=0; hexdigitp (s); s++, n++)
133 if (*s || (n != 40))
134 return 0; /* no fingerprint (invalid or wrong length). */
135 for (s=hexstr, n=0; *s; s += 2, n++)
136 fpr[n] = xtoi_2 (s);
137 return 1; /* okay */
140 /* Take the serial number from LINE and return it verbatim in a newly
141 allocated string. We make sure that only hex characters are
142 returned. */
143 static char *
144 store_serialno (const char *line)
146 const char *s;
147 char *p;
149 for (s=line; hexdigitp (s); s++)
151 p = xtrymalloc (s + 1 - line);
152 if (p)
154 memcpy (p, line, s-line);
155 p[s-line] = 0;
157 return p;
162 /* This is a dummy data line callback. */
163 static int
164 dummy_data_cb (void *opaque, const void *buffer, size_t length)
166 (void)opaque;
167 (void)buffer;
168 (void)length;
169 return 0;
173 /* This is the default inquiry callback. It mainly handles the
174 Pinentry notifications. */
175 static int
176 default_inq_cb (void *opaque, const char *line)
178 (void)opaque;
180 if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
182 /* There is no working server mode yet thus we use
183 AllowSetForegroundWindow window right here. We might want to
184 do this anyway in case gpg is called on the console. */
185 gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
186 /* We do not pass errors to avoid breaking other code. */
188 else
189 log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
191 return 0;
196 /* Release the card info structure INFO. */
197 void
198 agent_release_card_info (struct agent_card_info_s *info)
200 if (!info)
201 return;
203 xfree (info->serialno); info->serialno = NULL;
204 xfree (info->apptype); info->apptype = NULL;
205 xfree (info->disp_name); info->disp_name = NULL;
206 xfree (info->disp_lang); info->disp_lang = NULL;
207 xfree (info->pubkey_url); info->pubkey_url = NULL;
208 xfree (info->login_data); info->login_data = NULL;
209 info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
210 info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
213 static int
214 learn_status_cb (void *opaque, const char *line)
216 struct agent_card_info_s *parm = opaque;
217 const char *keyword = line;
218 int keywordlen;
219 int i;
221 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
223 while (spacep (line))
224 line++;
226 if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
228 xfree (parm->serialno);
229 parm->serialno = store_serialno (line);
230 parm->is_v2 = (strlen (parm->serialno) >= 16
231 && xtoi_2 (parm->serialno+12) >= 2 );
233 else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
235 xfree (parm->apptype);
236 parm->apptype = unescape_status_string (line);
238 else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
240 xfree (parm->disp_name);
241 parm->disp_name = unescape_status_string (line);
243 else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
245 xfree (parm->disp_lang);
246 parm->disp_lang = unescape_status_string (line);
248 else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
250 parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
252 else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
254 xfree (parm->pubkey_url);
255 parm->pubkey_url = unescape_status_string (line);
257 else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
259 xfree (parm->login_data);
260 parm->login_data = unescape_status_string (line);
262 else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
264 parm->sig_counter = strtoul (line, NULL, 0);
266 else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
268 char *p, *buf;
270 buf = p = unescape_status_string (line);
271 if (buf)
273 while (spacep (p))
274 p++;
275 parm->chv1_cached = atoi (p);
276 while (*p && !spacep (p))
277 p++;
278 while (spacep (p))
279 p++;
280 for (i=0; *p && i < 3; i++)
282 parm->chvmaxlen[i] = atoi (p);
283 while (*p && !spacep (p))
284 p++;
285 while (spacep (p))
286 p++;
288 for (i=0; *p && i < 3; i++)
290 parm->chvretry[i] = atoi (p);
291 while (*p && !spacep (p))
292 p++;
293 while (spacep (p))
294 p++;
296 xfree (buf);
299 else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
301 int no = atoi (line);
302 while (*line && !spacep (line))
303 line++;
304 while (spacep (line))
305 line++;
306 if (no == 1)
307 parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
308 else if (no == 2)
309 parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
310 else if (no == 3)
311 parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
313 else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
315 int no = atoi (line);
316 while (*line && !spacep (line))
317 line++;
318 while (spacep (line))
319 line++;
320 if (no == 1)
321 parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
322 else if (no == 2)
323 parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
324 else if (no == 3)
325 parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
327 else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
329 int keyno, algo, nbits;
331 sscanf (line, "%d %d %d", &keyno, &algo, &nbits);
332 keyno--;
333 if (keyno >= 0 && keyno < DIM (parm->key_attr))
335 parm->key_attr[keyno].algo = algo;
336 parm->key_attr[keyno].nbits = nbits;
340 return 0;
343 /* Call the agent to learn about a smartcard */
345 agent_learn (struct agent_card_info_s *info)
347 int rc;
349 rc = start_agent ();
350 if (rc)
351 return rc;
353 memset (info, 0, sizeof *info);
354 rc = assuan_transact (agent_ctx, "LEARN --send",
355 dummy_data_cb, NULL, default_inq_cb, NULL,
356 learn_status_cb, info);
357 /* Also try to get the key attributes. */
358 if (!rc)
359 agent_scd_getattr ("KEY-ATTR", info);
361 return rc;
364 /* Call the agent to retrieve a data object. This function returns
365 the data in the same structure as used by the learn command. It is
366 allowed to update such a structure using this commmand. */
368 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
370 int rc;
371 char line[ASSUAN_LINELENGTH];
373 if (!*name)
374 return gpg_error (GPG_ERR_INV_VALUE);
376 /* We assume that NAME does not need escaping. */
377 if (12 + strlen (name) > DIM(line)-1)
378 return gpg_error (GPG_ERR_TOO_LARGE);
379 stpcpy (stpcpy (line, "SCD GETATTR "), name);
381 rc = start_agent ();
382 if (rc)
383 return rc;
385 rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
386 learn_status_cb, info);
388 return rc;
392 /* Send an setattr command to the SCdaemon. SERIALNO is not actually
393 used here but required by gpg 1.4's implementation of this code in
394 cardglue.c. */
396 agent_scd_setattr (const char *name,
397 const unsigned char *value, size_t valuelen,
398 const char *serialno)
400 int rc;
401 char line[ASSUAN_LINELENGTH];
402 char *p;
404 (void)serialno;
406 if (!*name || !valuelen)
407 return gpg_error (GPG_ERR_INV_VALUE);
409 /* We assume that NAME does not need escaping. */
410 if (12 + strlen (name) > DIM(line)-1)
411 return gpg_error (GPG_ERR_TOO_LARGE);
413 p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
414 *p++ = ' ';
415 for (; valuelen; value++, valuelen--)
417 if (p >= line + DIM(line)-5 )
418 return gpg_error (GPG_ERR_TOO_LARGE);
419 if (*value < ' ' || *value == '+' || *value == '%')
421 sprintf (p, "%%%02X", *value);
422 p += 3;
424 else if (*value == ' ')
425 *p++ = '+';
426 else
427 *p++ = *value;
429 *p = 0;
431 rc = start_agent ();
432 if (rc)
433 return rc;
435 rc = assuan_transact (agent_ctx, line, NULL, NULL,
436 default_inq_cb, NULL, NULL, NULL);
437 return rc;
442 /* Handle a CERTDATA inquiry. Note, we only send the data,
443 assuan_transact takes care of flushing and writing the END
444 command. */
445 static int
446 inq_writecert_parms (void *opaque, const char *line)
448 int rc;
449 struct writecert_parm_s *parm = opaque;
451 if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
453 rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
455 else
456 rc = default_inq_cb (opaque, line);
458 return rc;
462 /* Send a WRITECERT command to the SCdaemon. */
463 int
464 agent_scd_writecert (const char *certidstr,
465 const unsigned char *certdata, size_t certdatalen)
467 int rc;
468 char line[ASSUAN_LINELENGTH];
469 struct writecert_parm_s parms;
471 rc = start_agent ();
472 if (rc)
473 return rc;
475 memset (&parms, 0, sizeof parms);
477 snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
478 line[DIM(line)-1] = 0;
479 parms.ctx = agent_ctx;
480 parms.certdata = certdata;
481 parms.certdatalen = certdatalen;
483 rc = assuan_transact (agent_ctx, line, NULL, NULL,
484 inq_writecert_parms, &parms, NULL, NULL);
486 return rc;
491 /* Handle a KEYDATA inquiry. Note, we only send the data,
492 assuan_transact takes care of flushing and writing the end */
493 static int
494 inq_writekey_parms (void *opaque, const char *line)
496 int rc;
497 struct writekey_parm_s *parm = opaque;
499 if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
501 rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
503 else
504 rc = default_inq_cb (opaque, line);
506 return rc;
510 /* Send a WRITEKEY command to the SCdaemon. */
511 int
512 agent_scd_writekey (int keyno, const char *serialno,
513 const unsigned char *keydata, size_t keydatalen)
515 int rc;
516 char line[ASSUAN_LINELENGTH];
517 struct writekey_parm_s parms;
519 (void)serialno;
521 rc = start_agent ();
522 if (rc)
523 return rc;
525 memset (&parms, 0, sizeof parms);
527 snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
528 line[DIM(line)-1] = 0;
529 parms.ctx = agent_ctx;
530 parms.keydata = keydata;
531 parms.keydatalen = keydatalen;
533 rc = assuan_transact (agent_ctx, line, NULL, NULL,
534 inq_writekey_parms, &parms, NULL, NULL);
536 return rc;
541 /* Status callback for the SCD GENKEY command. */
542 static int
543 scd_genkey_cb (void *opaque, const char *line)
545 struct agent_card_genkey_s *parm = opaque;
546 const char *keyword = line;
547 int keywordlen;
548 gpg_error_t rc;
550 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
552 while (spacep (line))
553 line++;
555 if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
557 parm->fprvalid = unhexify_fpr (line, parm->fpr);
559 if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
561 gcry_mpi_t a;
562 const char *name = line;
564 while (*line && !spacep (line))
565 line++;
566 while (spacep (line))
567 line++;
569 rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
570 if (rc)
571 log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
572 else if (*name == 'n' && spacep (name+1))
573 parm->n = a;
574 else if (*name == 'e' && spacep (name+1))
575 parm->e = a;
576 else
578 log_info ("unknown parameter name in received key data\n");
579 gcry_mpi_release (a);
582 else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
584 parm->created_at = (u32)strtoul (line, NULL, 10);
587 return 0;
590 /* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
591 this implementation. If CREATEDATE has been given, it will be
592 passed to SCDAEMON so that the key can be created with this
593 timestamp; note the user needs to use the returned timestamp as old
594 versions of scddaemon don't support this option. */
596 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
597 const char *serialno, u32 createtime)
599 int rc;
600 char line[ASSUAN_LINELENGTH];
601 gnupg_isotime_t tbuf;
603 (void)serialno;
605 rc = start_agent ();
606 if (rc)
607 return rc;
609 if (createtime)
610 epoch2isotime (tbuf, createtime);
611 else
612 *tbuf = 0;
614 memset (info, 0, sizeof *info);
615 snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
616 *tbuf? "--timestamp=":"", tbuf,
617 force? "--force":"",
618 keyno);
619 line[DIM(line)-1] = 0;
621 memset (info, 0, sizeof *info);
622 rc = assuan_transact (agent_ctx, line,
623 NULL, NULL, default_inq_cb, NULL,
624 scd_genkey_cb, info);
626 return rc;
630 static int
631 membuf_data_cb (void *opaque, const void *buffer, size_t length)
633 membuf_t *data = opaque;
635 if (buffer)
636 put_membuf (data, buffer, length);
637 return 0;
640 /* Send a sign command to the scdaemon via gpg-agent's pass thru
641 mechanism. */
643 agent_scd_pksign (const char *serialno, int hashalgo,
644 const unsigned char *indata, size_t indatalen,
645 unsigned char **r_buf, size_t *r_buflen)
647 int rc, i;
648 char *p, line[ASSUAN_LINELENGTH];
649 membuf_t data;
650 size_t len;
652 /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
654 *r_buf = NULL;
655 *r_buflen = 0;
657 rc = start_agent ();
658 if (rc)
659 return rc;
661 if (indatalen*2 + 50 > DIM(line))
662 return gpg_error (GPG_ERR_GENERAL);
664 /* Send the serialno command to initialize the connection. We don't
665 care about the data returned. If the card has already been
666 initialized, this is a very fast command. We request the openpgp
667 card because that is what we expect. */
668 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
669 NULL, NULL, NULL, NULL, NULL, NULL);
670 if (rc)
671 return rc;
673 sprintf (line, "SCD SETDATA ");
674 p = line + strlen (line);
675 for (i=0; i < indatalen ; i++, p += 2 )
676 sprintf (p, "%02X", indata[i]);
677 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
678 if (rc)
679 return rc;
681 init_membuf (&data, 1024);
682 #if 0
683 if (!hashalgo) /* Temporary test hack. */
684 snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
685 else
686 #endif
687 snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
688 hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
689 serialno);
690 line[DIM(line)-1] = 0;
691 rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
692 default_inq_cb, NULL, NULL, NULL);
693 if (rc)
695 xfree (get_membuf (&data, &len));
696 return rc;
698 *r_buf = get_membuf (&data, r_buflen);
700 return 0;
704 /* Decrypt INDATA of length INDATALEN using the card identified by
705 SERIALNO. Return the plaintext in a nwly allocated buffer stored
706 at the address of R_BUF.
708 Note, we currently support only RSA or more exactly algorithms
709 taking one input data element. */
711 agent_scd_pkdecrypt (const char *serialno,
712 const unsigned char *indata, size_t indatalen,
713 unsigned char **r_buf, size_t *r_buflen)
715 int rc, i;
716 char *p, line[ASSUAN_LINELENGTH];
717 membuf_t data;
718 size_t len;
720 *r_buf = NULL;
721 rc = start_agent ();
722 if (rc)
723 return rc;
725 /* FIXME: use secure memory where appropriate */
726 if (indatalen*2 + 50 > DIM(line))
727 return gpg_error (GPG_ERR_GENERAL);
729 /* Send the serialno command to initialize the connection. We don't
730 care about the data returned. If the card has already been
731 initialized, this is a very fast command. We request the openpgp
732 card because that is what we expect. */
733 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
734 NULL, NULL, NULL, NULL, NULL, NULL);
735 if (rc)
736 return rc;
738 sprintf (line, "SCD SETDATA ");
739 p = line + strlen (line);
740 for (i=0; i < indatalen ; i++, p += 2 )
741 sprintf (p, "%02X", indata[i]);
742 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
743 if (rc)
744 return rc;
746 init_membuf (&data, 1024);
747 snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
748 line[DIM(line)-1] = 0;
749 rc = assuan_transact (agent_ctx, line,
750 membuf_data_cb, &data,
751 default_inq_cb, NULL, NULL, NULL);
752 if (rc)
754 xfree (get_membuf (&data, &len));
755 return rc;
757 *r_buf = get_membuf (&data, r_buflen);
758 if (!*r_buf)
759 return gpg_error (GPG_ERR_ENOMEM);
761 return 0;
766 /* Send a READCERT command to the SCdaemon. */
767 int
768 agent_scd_readcert (const char *certidstr,
769 void **r_buf, size_t *r_buflen)
771 int rc;
772 char line[ASSUAN_LINELENGTH];
773 membuf_t data;
774 size_t len;
776 *r_buf = NULL;
777 rc = start_agent ();
778 if (rc)
779 return rc;
781 init_membuf (&data, 2048);
783 snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
784 line[DIM(line)-1] = 0;
785 rc = assuan_transact (agent_ctx, line,
786 membuf_data_cb, &data,
787 default_inq_cb, NULL, NULL, NULL);
788 if (rc)
790 xfree (get_membuf (&data, &len));
791 return rc;
793 *r_buf = get_membuf (&data, r_buflen);
794 if (!*r_buf)
795 return gpg_error (GPG_ERR_ENOMEM);
797 return 0;
802 /* Change the PIN of an OpenPGP card or reset the retry counter.
803 CHVNO 1: Change the PIN
804 2: For v1 cards: Same as 1.
805 For v2 cards: Reset the PIN using the Reset Code.
806 3: Change the admin PIN
807 101: Set a new PIN and reset the retry counter
808 102: For v1 cars: Same as 101.
809 For v2 cards: Set a new Reset Code.
810 SERIALNO is not used.
813 agent_scd_change_pin (int chvno, const char *serialno)
815 int rc;
816 char line[ASSUAN_LINELENGTH];
817 const char *reset = "";
819 (void)serialno;
821 if (chvno >= 100)
822 reset = "--reset";
823 chvno %= 100;
825 rc = start_agent ();
826 if (rc)
827 return rc;
829 snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
830 line[DIM(line)-1] = 0;
831 rc = assuan_transact (agent_ctx, line, NULL, NULL,
832 default_inq_cb, NULL, NULL, NULL);
833 return rc;
837 /* Perform a CHECKPIN operation. SERIALNO should be the serial
838 number of the card - optionally followed by the fingerprint;
839 however the fingerprint is ignored here. */
841 agent_scd_checkpin (const char *serialno)
843 int rc;
844 char line[ASSUAN_LINELENGTH];
846 rc = start_agent ();
847 if (rc)
848 return rc;
850 snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
851 line[DIM(line)-1] = 0;
852 return assuan_transact (agent_ctx, line,
853 NULL, NULL,
854 default_inq_cb, NULL, NULL, NULL);
858 /* Dummy function, only used by the gpg 1.4 implementation. */
859 void
860 agent_clear_pin_cache (const char *sn)
862 (void)sn;
868 /* Note: All strings shall be UTF-8. On success the caller needs to
869 free the string stored at R_PASSPHRASE. On error NULL will be
870 stored at R_PASSPHRASE and an appropriate fpf error code
871 returned. */
872 gpg_error_t
873 agent_get_passphrase (const char *cache_id,
874 const char *err_msg,
875 const char *prompt,
876 const char *desc_msg,
877 int repeat,
878 int check,
879 char **r_passphrase)
881 int rc;
882 char line[ASSUAN_LINELENGTH];
883 char *arg1 = NULL;
884 char *arg2 = NULL;
885 char *arg3 = NULL;
886 char *arg4 = NULL;
887 membuf_t data;
889 *r_passphrase = NULL;
891 rc = start_agent ();
892 if (rc)
893 return rc;
895 /* Check that the gpg-agent understands the repeat option. */
896 if (assuan_transact (agent_ctx,
897 "GETINFO cmd_has_option GET_PASSPHRASE repeat",
898 NULL, NULL, NULL, NULL, NULL, NULL))
899 return gpg_error (GPG_ERR_NOT_SUPPORTED);
901 if (cache_id && *cache_id)
902 if (!(arg1 = percent_plus_escape (cache_id)))
903 goto no_mem;
904 if (err_msg && *err_msg)
905 if (!(arg2 = percent_plus_escape (err_msg)))
906 goto no_mem;
907 if (prompt && *prompt)
908 if (!(arg3 = percent_plus_escape (prompt)))
909 goto no_mem;
910 if (desc_msg && *desc_msg)
911 if (!(arg4 = percent_plus_escape (desc_msg)))
912 goto no_mem;
914 snprintf (line, DIM(line)-1,
915 "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s",
916 repeat,
917 check? " --check --qualitybar":"",
918 arg1? arg1:"X",
919 arg2? arg2:"X",
920 arg3? arg3:"X",
921 arg4? arg4:"X");
922 line[DIM(line)-1] = 0;
923 xfree (arg1);
924 xfree (arg2);
925 xfree (arg3);
926 xfree (arg4);
928 init_membuf_secure (&data, 64);
929 rc = assuan_transact (agent_ctx, line,
930 membuf_data_cb, &data,
931 default_inq_cb, NULL, NULL, NULL);
933 if (rc)
934 xfree (get_membuf (&data, NULL));
935 else
937 put_membuf (&data, "", 1);
938 *r_passphrase = get_membuf (&data, NULL);
939 if (!*r_passphrase)
940 rc = gpg_error_from_syserror ();
942 return rc;
943 no_mem:
944 rc = gpg_error_from_syserror ();
945 xfree (arg1);
946 xfree (arg2);
947 xfree (arg3);
948 xfree (arg4);
949 return rc;
953 gpg_error_t
954 agent_clear_passphrase (const char *cache_id)
956 int rc;
957 char line[ASSUAN_LINELENGTH];
959 if (!cache_id || !*cache_id)
960 return 0;
962 rc = start_agent ();
963 if (rc)
964 return rc;
966 snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
967 line[DIM(line)-1] = 0;
968 return assuan_transact (agent_ctx, line, NULL, NULL,
969 default_inq_cb, NULL, NULL, NULL);