1 /* call-agent.c - divert operations to the agent
2 * Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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 3 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
39 #include "call-agent.h"
45 static assuan_context_t agent_ctx
= NULL
;
50 const char *ciphertext
;
54 struct writekey_parm_s
57 const unsigned char *keydata
;
70 /* Try to connect to the agent via socket or fork it off and work by
71 pipes. Handle the server's initial greeting */
76 return 0; /* Fixme: We need a context for each thread or serialize
77 the access to the agent. */
79 return start_new_gpg_agent (&agent_ctx
,
80 GPG_ERR_SOURCE_DEFAULT
,
83 opt
.display
, opt
.ttyname
, opt
.ttytype
,
84 opt
.lc_ctype
, opt
.lc_messages
,
85 opt
.verbose
, DBG_ASSUAN
,
90 /* Return a new malloced string by unescaping the string S. Escaping
91 is percent escaping and '+'/space mapping. A binary nul will
92 silently be replaced by a 0xFF. Function returns NULL to indicate
93 an out of memory status. */
95 unescape_status_string (const unsigned char *s
)
99 buffer
= d
= xtrymalloc (strlen (s
)+1);
104 if (*s
== '%' && s
[1] && s
[2])
125 /* Copy the text ATEXT into the buffer P and do plus '+' and percent
126 escaping. Note that the provided buffer needs to be 3 times the
127 size of ATEXT plus 1. Returns a pointer to the leading Nul in P. */
129 percent_plus_escape (char *p
, const char *atext
)
131 const unsigned char *s
;
133 for (s
=atext
; *s
; s
++)
135 if (*s
< ' ' || *s
== '+')
137 sprintf (p
, "%%%02X", *s
);
149 /* Take a 20 byte hexencoded string and put it into the the provided
150 20 byte buffer FPR in binary format. */
152 unhexify_fpr (const char *hexstr
, unsigned char *fpr
)
157 for (s
=hexstr
, n
=0; hexdigitp (s
); s
++, n
++)
160 return 0; /* no fingerprint (invalid or wrong length). */
162 for (s
=hexstr
, n
=0; *s
; s
+= 2, n
++)
167 /* Take the serial number from LINE and return it verbatim in a newly
168 allocated string. We make sure that only hex characters are
171 store_serialno (const char *line
)
176 for (s
=line
; hexdigitp (s
); s
++)
178 p
= xtrymalloc (s
+ 1 - line
);
181 memcpy (p
, line
, s
-line
);
189 /* Release the card info structure INFO. */
191 agent_release_card_info (struct agent_card_info_s
*info
)
196 xfree (info
->serialno
); info
->serialno
= NULL
;
197 xfree (info
->disp_name
); info
->disp_name
= NULL
;
198 xfree (info
->disp_lang
); info
->disp_lang
= NULL
;
199 xfree (info
->pubkey_url
); info
->pubkey_url
= NULL
;
200 xfree (info
->login_data
); info
->login_data
= NULL
;
201 info
->cafpr1valid
= info
->cafpr2valid
= info
->cafpr3valid
= 0;
202 info
->fpr1valid
= info
->fpr2valid
= info
->fpr3valid
= 0;
206 learn_status_cb (void *opaque
, const char *line
)
208 struct agent_card_info_s
*parm
= opaque
;
209 const char *keyword
= line
;
213 for (keywordlen
=0; *line
&& !spacep (line
); line
++, keywordlen
++)
215 while (spacep (line
))
218 if (keywordlen
== 8 && !memcmp (keyword
, "SERIALNO", keywordlen
))
220 xfree (parm
->serialno
);
221 parm
->serialno
= store_serialno (line
);
223 else if (keywordlen
== 9 && !memcmp (keyword
, "DISP-NAME", keywordlen
))
225 xfree (parm
->disp_name
);
226 parm
->disp_name
= unescape_status_string (line
);
228 else if (keywordlen
== 9 && !memcmp (keyword
, "DISP-LANG", keywordlen
))
230 xfree (parm
->disp_lang
);
231 parm
->disp_lang
= unescape_status_string (line
);
233 else if (keywordlen
== 8 && !memcmp (keyword
, "DISP-SEX", keywordlen
))
235 parm
->disp_sex
= *line
== '1'? 1 : *line
== '2' ? 2: 0;
237 else if (keywordlen
== 10 && !memcmp (keyword
, "PUBKEY-URL", keywordlen
))
239 xfree (parm
->pubkey_url
);
240 parm
->pubkey_url
= unescape_status_string (line
);
242 else if (keywordlen
== 10 && !memcmp (keyword
, "LOGIN-DATA", keywordlen
))
244 xfree (parm
->login_data
);
245 parm
->login_data
= unescape_status_string (line
);
247 else if (keywordlen
== 11 && !memcmp (keyword
, "SIG-COUNTER", keywordlen
))
249 parm
->sig_counter
= strtoul (line
, NULL
, 0);
251 else if (keywordlen
== 10 && !memcmp (keyword
, "CHV-STATUS", keywordlen
))
255 buf
= p
= unescape_status_string (line
);
260 parm
->chv1_cached
= atoi (p
);
261 while (*p
&& !spacep (p
))
265 for (i
=0; *p
&& i
< 3; i
++)
267 parm
->chvmaxlen
[i
] = atoi (p
);
268 while (*p
&& !spacep (p
))
273 for (i
=0; *p
&& i
< 3; i
++)
275 parm
->chvretry
[i
] = atoi (p
);
276 while (*p
&& !spacep (p
))
284 else if (keywordlen
== 7 && !memcmp (keyword
, "KEY-FPR", keywordlen
))
286 int no
= atoi (line
);
287 while (*line
&& !spacep (line
))
289 while (spacep (line
))
292 parm
->fpr1valid
= unhexify_fpr (line
, parm
->fpr1
);
294 parm
->fpr2valid
= unhexify_fpr (line
, parm
->fpr2
);
296 parm
->fpr3valid
= unhexify_fpr (line
, parm
->fpr3
);
298 else if (keywordlen
== 6 && !memcmp (keyword
, "CA-FPR", keywordlen
))
300 int no
= atoi (line
);
301 while (*line
&& !spacep (line
))
303 while (spacep (line
))
306 parm
->cafpr1valid
= unhexify_fpr (line
, parm
->cafpr1
);
308 parm
->cafpr2valid
= unhexify_fpr (line
, parm
->cafpr2
);
310 parm
->cafpr3valid
= unhexify_fpr (line
, parm
->cafpr3
);
316 /* Call the agent to learn about a smartcard */
318 agent_learn (struct agent_card_info_s
*info
)
326 memset (info
, 0, sizeof *info
);
327 rc
= assuan_transact (agent_ctx
, "LEARN --send",
328 NULL
, NULL
, NULL
, NULL
,
329 learn_status_cb
, info
);
334 /* Call the agent to retrieve a data object. This function returns
335 the data in the same structure as used by the learn command. It is
336 allowed to update such a structure using this commmand. */
338 agent_scd_getattr (const char *name
, struct agent_card_info_s
*info
)
341 char line
[ASSUAN_LINELENGTH
];
344 return gpg_error (GPG_ERR_INV_VALUE
);
346 /* We assume that NAME does not need escaping. */
347 if (12 + strlen (name
) > DIM(line
)-1)
348 return gpg_error (GPG_ERR_TOO_LARGE
);
349 stpcpy (stpcpy (line
, "SCD GETATTR "), name
);
355 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
,
356 learn_status_cb
, info
);
362 /* Send an setattr command to the SCdaemon. SERIALNO is not actually
363 used here but required by gpg 1.4's implementation of this code in
366 agent_scd_setattr (const char *name
,
367 const unsigned char *value
, size_t valuelen
,
368 const char *serialno
)
371 char line
[ASSUAN_LINELENGTH
];
374 if (!*name
|| !valuelen
)
375 return gpg_error (GPG_ERR_INV_VALUE
);
377 /* We assume that NAME does not need escaping. */
378 if (12 + strlen (name
) > DIM(line
)-1)
379 return gpg_error (GPG_ERR_TOO_LARGE
);
381 p
= stpcpy (stpcpy (line
, "SCD SETATTR "), name
);
383 for (; valuelen
; value
++, valuelen
--)
385 if (p
>= line
+ DIM(line
)-5 )
386 return gpg_error (GPG_ERR_TOO_LARGE
);
387 if (*value
< ' ' || *value
== '+' || *value
== '%')
389 sprintf (p
, "%%%02X", *value
);
392 else if (*value
== ' ')
403 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
409 /* Handle a KEYDATA inquiry. Note, we only send the data,
410 assuan_transact takes care of flushing and writing the end */
411 static assuan_error_t
412 inq_writekey_parms (void *opaque
, const char *keyword
)
414 struct writekey_parm_s
*parm
= opaque
;
416 return assuan_send_data (parm
->ctx
, parm
->keydata
, parm
->keydatalen
);
420 /* Send a WRITEKEY command to the SCdaemon. */
422 agent_scd_writekey (int keyno
, const char *serialno
,
423 const unsigned char *keydata
, size_t keydatalen
)
426 char line
[ASSUAN_LINELENGTH
];
427 struct writekey_parm_s parms
;
433 memset (&parms
, 0, sizeof parms
);
435 snprintf (line
, DIM(line
)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno
);
436 line
[DIM(line
)-1] = 0;
437 parms
.ctx
= agent_ctx
;
438 parms
.keydata
= keydata
;
439 parms
.keydatalen
= keydatalen
;
441 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
,
442 inq_writekey_parms
, &parms
, NULL
, NULL
);
450 /* Status callback for the SCD GENKEY command. */
452 scd_genkey_cb (void *opaque
, const char *line
)
454 struct agent_card_genkey_s
*parm
= opaque
;
455 const char *keyword
= line
;
459 log_debug ("got status line `%s'\n", line
);
460 for (keywordlen
=0; *line
&& !spacep (line
); line
++, keywordlen
++)
462 while (spacep (line
))
465 if (keywordlen
== 7 && !memcmp (keyword
, "KEY-FPR", keywordlen
))
467 parm
->fprvalid
= unhexify_fpr (line
, parm
->fpr
);
469 if (keywordlen
== 8 && !memcmp (keyword
, "KEY-DATA", keywordlen
))
472 const char *name
= line
;
474 while (*line
&& !spacep (line
))
476 while (spacep (line
))
479 rc
= gcry_mpi_scan (&a
, GCRYMPI_FMT_HEX
, line
, 0, NULL
);
481 log_error ("error parsing received key data: %s\n", gpg_strerror (rc
));
482 else if (*name
== 'n' && spacep (name
+1))
484 else if (*name
== 'e' && spacep (name
+1))
488 log_info ("unknown parameter name in received key data\n");
489 gcry_mpi_release (a
);
492 else if (keywordlen
== 14 && !memcmp (keyword
,"KEY-CREATED-AT", keywordlen
))
494 parm
->created_at
= (u32
)strtoul (line
, NULL
, 10);
500 /* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
501 this implementation. */
503 agent_scd_genkey (struct agent_card_genkey_s
*info
, int keyno
, int force
,
504 const char *serialno
)
507 char line
[ASSUAN_LINELENGTH
];
513 memset (info
, 0, sizeof *info
);
514 snprintf (line
, DIM(line
)-1, "SCD GENKEY %s%d",
515 force
? "--force ":"", keyno
);
516 line
[DIM(line
)-1] = 0;
518 memset (info
, 0, sizeof *info
);
519 rc
= assuan_transact (agent_ctx
, line
,
520 NULL
, NULL
, NULL
, NULL
,
521 scd_genkey_cb
, info
);
528 membuf_data_cb (void *opaque
, const void *buffer
, size_t length
)
530 membuf_t
*data
= opaque
;
533 put_membuf (data
, buffer
, length
);
537 /* Send a sign command to the scdaemon via gpg-agent's pass thru
540 agent_scd_pksign (const char *serialno
, int hashalgo
,
541 const unsigned char *indata
, size_t indatalen
,
542 unsigned char **r_buf
, size_t *r_buflen
)
545 char *p
, line
[ASSUAN_LINELENGTH
];
549 /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
558 if (indatalen
*2 + 50 > DIM(line
))
559 return gpg_error (GPG_ERR_GENERAL
);
561 sprintf (line
, "SCD SETDATA ");
562 p
= line
+ strlen (line
);
563 for (i
=0; i
< indatalen
; i
++, p
+= 2 )
564 sprintf (p
, "%02X", indata
[i
]);
565 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
569 init_membuf (&data
, 1024);
571 if (!hashalgo
) /* Temporary test hack. */
572 snprintf (line
, DIM(line
)-1, "SCD PKAUTH %s", serialno
);
575 snprintf (line
, DIM(line
)-1, "SCD PKSIGN %s%s",
576 hashalgo
== GCRY_MD_RMD160
? "--hash=rmd160 " : "",
578 line
[DIM(line
)-1] = 0;
579 rc
= assuan_transact (agent_ctx
, line
, membuf_data_cb
, &data
,
580 NULL
, NULL
, NULL
, NULL
);
583 xfree (get_membuf (&data
, &len
));
586 *r_buf
= get_membuf (&data
, r_buflen
);
592 /* Decrypt INDATA of length INDATALEN using the card identified by
593 SERIALNO. Return the plaintext in a nwly allocated buffer stored
594 at the address of R_BUF.
596 Note, we currently support only RSA or more exactly algorithms
597 taking one input data element. */
599 agent_scd_pkdecrypt (const char *serialno
,
600 const unsigned char *indata
, size_t indatalen
,
601 unsigned char **r_buf
, size_t *r_buflen
)
604 char *p
, line
[ASSUAN_LINELENGTH
];
613 /* FIXME: use secure memory where appropriate */
614 if (indatalen
*2 + 50 > DIM(line
))
615 return gpg_error (GPG_ERR_GENERAL
);
617 sprintf (line
, "SCD SETDATA ");
618 p
= line
+ strlen (line
);
619 for (i
=0; i
< indatalen
; i
++, p
+= 2 )
620 sprintf (p
, "%02X", indata
[i
]);
621 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
625 init_membuf (&data
, 1024);
626 snprintf (line
, DIM(line
)-1, "SCD PKDECRYPT %s", serialno
);
627 line
[DIM(line
)-1] = 0;
628 rc
= assuan_transact (agent_ctx
, line
,
629 membuf_data_cb
, &data
,
630 NULL
, NULL
, NULL
, NULL
);
633 xfree (get_membuf (&data
, &len
));
636 *r_buf
= get_membuf (&data
, r_buflen
);
638 return gpg_error (GPG_ERR_ENOMEM
);
644 /* Change the PIN of an OpenPGP card or reset the retry counter.
645 CHVNO 1: Change the PIN
647 3: Change the admin PIN
648 101: Set a new PIN and reset the retry counter
650 SERIALNO is not used.
653 agent_scd_change_pin (int chvno
, const char *serialno
)
656 char line
[ASSUAN_LINELENGTH
];
657 const char *reset
= "";
667 snprintf (line
, DIM(line
)-1, "SCD PASSWD %s %d", reset
, chvno
);
668 line
[DIM(line
)-1] = 0;
669 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
,
670 NULL
, NULL
, NULL
, NULL
);
675 /* Perform a CHECKPIN operation. SERIALNO should be the serial
676 number of the card - optionally followed by the fingerprint;
677 however the fingerprint is ignored here. */
679 agent_scd_checkpin (const char *serialno
)
682 char line
[ASSUAN_LINELENGTH
];
688 snprintf (line
, DIM(line
)-1, "SCD CHECKPIN %s", serialno
);
689 line
[DIM(line
)-1] = 0;
690 return assuan_transact (agent_ctx
, line
,
692 NULL
, NULL
, NULL
, NULL
);
696 /* Dummy function, only used by the gpg 1.4 implementation. */
698 agent_clear_pin_cache (const char *sn
)
706 /* Note: All strings shall be UTF-8. On success the caler needs to
707 free the string stored at R_PASSPHRASE. On error NULL will be
708 stored at R_PASSPHRASE and an appropriate fpf error code
711 agent_get_passphrase (const char *cache_id
,
714 const char *desc_msg
,
719 char cmd
[] = "GET_PASSPHRASE --data -- ";
722 *r_passphrase
= NULL
;
728 /* We allocate 3 times the needed space for the texts so that
729 there is enough space for escaping. */
730 line
= xtrymalloc ( strlen (cmd
) + 1
731 + (cache_id
? 3*strlen (cache_id
): 1) + 1
732 + (err_msg
? 3*strlen (err_msg
): 1) + 1
733 + (prompt
? 3*strlen (prompt
): 1) + 1
734 + (desc_msg
? 3*strlen (desc_msg
): 1) + 1
737 return gpg_error_from_syserror ();
739 p
= stpcpy (line
, cmd
);
740 if (cache_id
&& *cache_id
)
741 p
= percent_plus_escape (p
, cache_id
);
746 if (err_msg
&& *err_msg
)
747 p
= percent_plus_escape (p
, err_msg
);
752 if (prompt
&& *prompt
)
753 p
= percent_plus_escape (p
, prompt
);
758 if (desc_msg
&& *desc_msg
)
759 p
= percent_plus_escape (p
, desc_msg
);
764 init_membuf_secure (&data
, 64);
765 rc
= assuan_transact (agent_ctx
, line
,
766 membuf_data_cb
, &data
, NULL
, NULL
, NULL
, NULL
);
769 xfree (get_membuf (&data
, NULL
));
772 put_membuf (&data
, "", 1);
773 *r_passphrase
= get_membuf (&data
, NULL
);
775 rc
= gpg_error_from_syserror ();
783 agent_clear_passphrase (const char *cache_id
)
786 char line
[ASSUAN_LINELENGTH
];
788 if (!cache_id
|| !*cache_id
)
795 snprintf (line
, DIM(line
)-1, "CLEAR_PASSPHRASE %s", cache_id
);
796 line
[DIM(line
)-1] = 0;
797 return assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);