1 /* call-agent.c - Divert GPGSM operations to the agent
2 * Copyright (C) 2001, 2002, 2003, 2005, 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/>.
38 #include "keydb.h" /* fixme: Move this to import.c */
42 static assuan_context_t agent_ctx
= NULL
;
49 const unsigned char *ciphertext
;
57 const unsigned char *sexp
;
71 /* Try to connect to the agent via socket or fork it off and work by
72 pipes. Handle the server's initial greeting */
74 start_agent (ctrl_t ctrl
)
79 rc
= 0; /* fixme: We need a context for each thread or
80 serialize the access to the agent (which is
81 suitable given that the agent is not MT. */
84 rc
= start_new_gpg_agent (&agent_ctx
,
85 GPG_ERR_SOURCE_DEFAULT
,
88 opt
.display
, opt
.ttyname
, opt
.ttytype
,
89 opt
.lc_ctype
, opt
.lc_messages
,
90 opt
.xauthority
, opt
.pinentry_user_data
,
91 opt
.verbose
, DBG_ASSUAN
,
96 /* Tell the agent that we support Pinentry notifications. No
97 error checking so that it will work also with older
99 assuan_transact (agent_ctx
, "OPTION allow-pinentry-notify",
100 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
104 if (!ctrl
->agent_seen
)
106 ctrl
->agent_seen
= 1;
107 audit_log_ok (ctrl
->audit
, AUDIT_AGENT_READY
, rc
);
116 membuf_data_cb (void *opaque
, const void *buffer
, size_t length
)
118 membuf_t
*data
= opaque
;
121 put_membuf (data
, buffer
, length
);
126 /* This is the default inquiry callback. It mainly handles the
127 Pinentry notifications. */
129 default_inq_cb (void *opaque
, const char *line
)
132 ctrl_t ctrl
= opaque
;
134 if (!strncmp (line
, "PINENTRY_LAUNCHED", 17) && (line
[17]==' '||!line
[17]))
136 err
= gpgsm_proxy_pinentry_notify (ctrl
, line
);
138 log_error (_("failed to proxy %s inquiry to client\n"),
139 "PINENTRY_LAUNCHED");
140 /* We do not pass errors to avoid breaking other code. */
143 log_error ("ignoring gpg-agent inquiry `%s'\n", line
);
151 /* Call the agent to do a sign operation using the key identified by
152 the hex string KEYGRIP. */
154 gpgsm_agent_pksign (ctrl_t ctrl
, const char *keygrip
, const char *desc
,
155 unsigned char *digest
, size_t digestlen
, int digestalgo
,
156 unsigned char **r_buf
, size_t *r_buflen
)
159 char *p
, line
[ASSUAN_LINELENGTH
];
164 rc
= start_agent (ctrl
);
168 if (digestlen
*2 + 50 > DIM(line
))
169 return gpg_error (GPG_ERR_GENERAL
);
171 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
175 snprintf (line
, DIM(line
)-1, "SIGKEY %s", keygrip
);
176 line
[DIM(line
)-1] = 0;
177 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
183 snprintf (line
, DIM(line
)-1, "SETKEYDESC %s", desc
);
184 line
[DIM(line
)-1] = 0;
185 rc
= assuan_transact (agent_ctx
, line
,
186 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
191 sprintf (line
, "SETHASH %d ", digestalgo
);
192 p
= line
+ strlen (line
);
193 for (i
=0; i
< digestlen
; i
++, p
+= 2 )
194 sprintf (p
, "%02X", digest
[i
]);
195 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
199 init_membuf (&data
, 1024);
200 rc
= assuan_transact (agent_ctx
, "PKSIGN",
201 membuf_data_cb
, &data
, default_inq_cb
, ctrl
,
205 xfree (get_membuf (&data
, &len
));
208 *r_buf
= get_membuf (&data
, r_buflen
);
210 if (!gcry_sexp_canon_len (*r_buf
, *r_buflen
, NULL
, NULL
))
212 xfree (*r_buf
); *r_buf
= NULL
;
213 return gpg_error (GPG_ERR_INV_VALUE
);
216 return *r_buf
? 0 : out_of_core ();
220 /* Call the scdaemon to do a sign operation using the key identified by
221 the hex string KEYID. */
223 gpgsm_scd_pksign (ctrl_t ctrl
, const char *keyid
, const char *desc
,
224 unsigned char *digest
, size_t digestlen
, int digestalgo
,
225 unsigned char **r_buf
, size_t *r_buflen
)
228 char *p
, line
[ASSUAN_LINELENGTH
];
232 unsigned char *sigbuf
;
239 case GCRY_MD_SHA1
: hashopt
= "--hash=sha1"; break;
240 case GCRY_MD_RMD160
:hashopt
= "--hash=rmd160"; break;
241 case GCRY_MD_MD5
: hashopt
= "--hash=md5"; break;
242 case GCRY_MD_SHA256
:hashopt
= "--hash=sha256"; break;
244 return gpg_error (GPG_ERR_DIGEST_ALGO
);
247 rc
= start_agent (ctrl
);
251 if (digestlen
*2 + 50 > DIM(line
))
252 return gpg_error (GPG_ERR_GENERAL
);
254 p
= stpcpy (line
, "SCD SETDATA " );
255 for (i
=0; i
< digestlen
; i
++, p
+= 2 )
256 sprintf (p
, "%02X", digest
[i
]);
257 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
261 init_membuf (&data
, 1024);
263 snprintf (line
, DIM(line
)-1, "SCD PKSIGN %s %s", hashopt
, keyid
);
264 line
[DIM(line
)-1] = 0;
265 rc
= assuan_transact (agent_ctx
, line
,
266 membuf_data_cb
, &data
, default_inq_cb
, ctrl
,
270 xfree (get_membuf (&data
, &len
));
273 sigbuf
= get_membuf (&data
, &sigbuflen
);
275 /* Create an S-expression from it which is formatted like this:
276 "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" Fixme: If a card ever
277 creates non-RSA keys we need to change things. */
278 *r_buflen
= 21 + 11 + sigbuflen
+ 4;
279 p
= xtrymalloc (*r_buflen
);
280 *r_buf
= (unsigned char*)p
;
286 p
= stpcpy (p
, "(7:sig-val(3:rsa(1:s" );
287 sprintf (p
, "%u:", (unsigned int)sigbuflen
);
289 memcpy (p
, sigbuf
, sigbuflen
);
294 assert (gcry_sexp_canon_len (*r_buf
, *r_buflen
, NULL
, NULL
));
301 /* Handle a CIPHERTEXT inquiry. Note, we only send the data,
302 assuan_transact talkes care of flushing and writing the end */
304 inq_ciphertext_cb (void *opaque
, const char *line
)
306 struct cipher_parm_s
*parm
= opaque
;
309 if (!strncmp (line
, "CIPHERTEXT", 10) && (line
[10]==' '||!line
[10]))
311 assuan_begin_confidential (parm
->ctx
);
312 rc
= assuan_send_data (parm
->ctx
, parm
->ciphertext
, parm
->ciphertextlen
);
313 assuan_end_confidential (parm
->ctx
);
316 rc
= default_inq_cb (parm
->ctrl
, line
);
322 /* Call the agent to do a decrypt operation using the key identified by
323 the hex string KEYGRIP. */
325 gpgsm_agent_pkdecrypt (ctrl_t ctrl
, const char *keygrip
, const char *desc
,
326 ksba_const_sexp_t ciphertext
,
327 char **r_buf
, size_t *r_buflen
)
330 char line
[ASSUAN_LINELENGTH
];
332 struct cipher_parm_s cipher_parm
;
334 char *p
, *buf
, *endp
;
335 size_t ciphertextlen
;
337 if (!keygrip
|| strlen(keygrip
) != 40 || !ciphertext
|| !r_buf
|| !r_buflen
)
338 return gpg_error (GPG_ERR_INV_VALUE
);
341 ciphertextlen
= gcry_sexp_canon_len (ciphertext
, 0, NULL
, NULL
);
343 return gpg_error (GPG_ERR_INV_VALUE
);
345 rc
= start_agent (ctrl
);
349 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
353 assert ( DIM(line
) >= 50 );
354 snprintf (line
, DIM(line
)-1, "SETKEY %s", keygrip
);
355 line
[DIM(line
)-1] = 0;
356 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
362 snprintf (line
, DIM(line
)-1, "SETKEYDESC %s", desc
);
363 line
[DIM(line
)-1] = 0;
364 rc
= assuan_transact (agent_ctx
, line
,
365 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
370 init_membuf (&data
, 1024);
371 cipher_parm
.ctrl
= ctrl
;
372 cipher_parm
.ctx
= agent_ctx
;
373 cipher_parm
.ciphertext
= ciphertext
;
374 cipher_parm
.ciphertextlen
= ciphertextlen
;
375 rc
= assuan_transact (agent_ctx
, "PKDECRYPT",
376 membuf_data_cb
, &data
,
377 inq_ciphertext_cb
, &cipher_parm
, NULL
, NULL
);
380 xfree (get_membuf (&data
, &len
));
384 put_membuf (&data
, "", 1); /* Make sure it is 0 terminated. */
385 buf
= get_membuf (&data
, &len
);
387 return gpg_error (GPG_ERR_ENOMEM
);
388 assert (len
); /* (we forced Nul termination.) */
392 if (len
< 13 || memcmp (buf
, "(5:value", 8) ) /* "(5:valueN:D)\0" */
393 return gpg_error (GPG_ERR_INV_SEXP
);
394 len
-= 11; /* Count only the data of the second part. */
395 p
= buf
+ 8; /* Skip leading parenthesis and the value tag. */
399 /* For compatibility with older gpg-agents handle the old style
400 incomplete S-exps. */
401 len
--; /* Do not count the Nul. */
405 n
= strtoul (p
, &endp
, 10);
406 if (!n
|| *endp
!= ':')
407 return gpg_error (GPG_ERR_INV_SEXP
);
410 return gpg_error (GPG_ERR_INV_SEXP
); /* Oops: Inconsistent S-Exp. */
412 memmove (buf
, endp
, n
);
423 /* Handle a KEYPARMS inquiry. Note, we only send the data,
424 assuan_transact takes care of flushing and writing the end */
426 inq_genkey_parms (void *opaque
, const char *line
)
428 struct genkey_parm_s
*parm
= opaque
;
431 if (!strncmp (line
, "KEYPARAM", 8) && (line
[8]==' '||!line
[8]))
433 rc
= assuan_send_data (parm
->ctx
, parm
->sexp
, parm
->sexplen
);
436 rc
= default_inq_cb (parm
->ctrl
, line
);
443 /* Call the agent to generate a newkey */
445 gpgsm_agent_genkey (ctrl_t ctrl
,
446 ksba_const_sexp_t keyparms
, ksba_sexp_t
*r_pubkey
)
449 struct genkey_parm_s gk_parm
;
455 rc
= start_agent (ctrl
);
459 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
463 init_membuf (&data
, 1024);
465 gk_parm
.ctx
= agent_ctx
;
466 gk_parm
.sexp
= keyparms
;
467 gk_parm
.sexplen
= gcry_sexp_canon_len (keyparms
, 0, NULL
, NULL
);
468 if (!gk_parm
.sexplen
)
469 return gpg_error (GPG_ERR_INV_VALUE
);
470 rc
= assuan_transact (agent_ctx
, "GENKEY",
471 membuf_data_cb
, &data
,
472 inq_genkey_parms
, &gk_parm
, NULL
, NULL
);
475 xfree (get_membuf (&data
, &len
));
478 buf
= get_membuf (&data
, &len
);
480 return gpg_error (GPG_ERR_ENOMEM
);
481 if (!gcry_sexp_canon_len (buf
, len
, NULL
, NULL
))
484 return gpg_error (GPG_ERR_INV_SEXP
);
491 /* Call the agent to read the public key part for a given keygrip. If
492 FROMCARD is true, the key is directly read from the current
493 smartcard. In this case HEXKEYGRIP should be the keyID
496 gpgsm_agent_readkey (ctrl_t ctrl
, int fromcard
, const char *hexkeygrip
,
497 ksba_sexp_t
*r_pubkey
)
503 char line
[ASSUAN_LINELENGTH
];
506 rc
= start_agent (ctrl
);
510 rc
= assuan_transact (agent_ctx
, "RESET",NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
514 snprintf (line
, DIM(line
)-1, "%sREADKEY %s",
515 fromcard
? "SCD ":"", hexkeygrip
);
516 line
[DIM(line
)-1] = 0;
518 init_membuf (&data
, 1024);
519 rc
= assuan_transact (agent_ctx
, line
,
520 membuf_data_cb
, &data
,
521 default_inq_cb
, ctrl
, NULL
, NULL
);
524 xfree (get_membuf (&data
, &len
));
527 buf
= get_membuf (&data
, &len
);
529 return gpg_error (GPG_ERR_ENOMEM
);
530 if (!gcry_sexp_canon_len (buf
, len
, NULL
, NULL
))
533 return gpg_error (GPG_ERR_INV_SEXP
);
542 istrusted_status_cb (void *opaque
, const char *line
)
544 struct rootca_flags_s
*flags
= opaque
;
546 if (!strncmp (line
, "TRUSTLISTFLAG", 13) && (line
[13]==' ' || !line
[13]))
548 for (line
+= 13; *line
== ' '; line
++)
550 if (!strncmp (line
, "relax", 5) && (line
[5] == ' ' || !line
[5]))
552 else if (!strncmp (line
, "cm", 2) && (line
[2] == ' ' || !line
[2]))
553 flags
->chain_model
= 1;
560 /* Ask the agent whether the certificate is in the list of trusted
561 keys. ROOTCA_FLAGS is guaranteed to be cleared on error. */
563 gpgsm_agent_istrusted (ctrl_t ctrl
, ksba_cert_t cert
,
564 struct rootca_flags_s
*rootca_flags
)
568 char line
[ASSUAN_LINELENGTH
];
570 memset (rootca_flags
, 0, sizeof *rootca_flags
);
572 rc
= start_agent (ctrl
);
576 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
579 log_error ("error getting the fingerprint\n");
580 return gpg_error (GPG_ERR_GENERAL
);
583 snprintf (line
, DIM(line
)-1, "ISTRUSTED %s", fpr
);
584 line
[DIM(line
)-1] = 0;
587 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
,
588 istrusted_status_cb
, rootca_flags
);
590 rootca_flags
->valid
= 1;
594 /* Ask the agent to mark CERT as a trusted Root-CA one */
596 gpgsm_agent_marktrusted (ctrl_t ctrl
, ksba_cert_t cert
)
600 char line
[ASSUAN_LINELENGTH
];
602 rc
= start_agent (ctrl
);
606 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
609 log_error ("error getting the fingerprint\n");
610 return gpg_error (GPG_ERR_GENERAL
);
613 dn
= ksba_cert_get_issuer (cert
, 0);
617 return gpg_error (GPG_ERR_GENERAL
);
619 snprintf (line
, DIM(line
)-1, "MARKTRUSTED %s S %s", fpr
, dn
);
620 line
[DIM(line
)-1] = 0;
624 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
,
625 default_inq_cb
, ctrl
, NULL
, NULL
);
631 /* Ask the agent whether the a corresponding secret key is available
632 for the given keygrip */
634 gpgsm_agent_havekey (ctrl_t ctrl
, const char *hexkeygrip
)
637 char line
[ASSUAN_LINELENGTH
];
639 rc
= start_agent (ctrl
);
643 if (!hexkeygrip
|| strlen (hexkeygrip
) != 40)
644 return gpg_error (GPG_ERR_INV_VALUE
);
646 snprintf (line
, DIM(line
)-1, "HAVEKEY %s", hexkeygrip
);
647 line
[DIM(line
)-1] = 0;
649 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
655 learn_cb (void *opaque
, const void *buffer
, size_t length
)
657 struct learn_parm_s
*parm
= opaque
;
668 put_membuf (parm
->data
, buffer
, length
);
671 /* END encountered - process what we have */
672 buf
= get_membuf (parm
->data
, &len
);
675 parm
->error
= gpg_error (GPG_ERR_ENOMEM
);
680 /* FIXME: this should go into import.c */
681 rc
= ksba_cert_new (&cert
);
687 rc
= ksba_cert_init_from_mem (cert
, buf
, len
);
690 log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc
));
691 ksba_cert_release (cert
);
696 rc
= gpgsm_basic_cert_check (parm
->ctrl
, cert
);
697 if (gpg_err_code (rc
) == GPG_ERR_MISSING_CERT
)
698 { /* For later use we store it in the ephemeral database. */
699 log_info ("issuer certificate missing - storing as ephemeral\n");
700 keydb_store_cert (cert
, 1, NULL
);
703 log_error ("invalid certificate: %s\n", gpg_strerror (rc
));
708 if (!keydb_store_cert (cert
, 0, &existed
))
710 if (opt
.verbose
> 1 && existed
)
711 log_info ("certificate already in DB\n");
712 else if (opt
.verbose
&& !existed
)
713 log_info ("certificate imported\n");
717 ksba_cert_release (cert
);
718 init_membuf (parm
->data
, 4096);
722 /* Call the agent to learn about a smartcard */
724 gpgsm_agent_learn (ctrl_t ctrl
)
727 struct learn_parm_s learn_parm
;
731 rc
= start_agent (ctrl
);
735 init_membuf (&data
, 4096);
736 learn_parm
.error
= 0;
737 learn_parm
.ctrl
= ctrl
;
738 learn_parm
.ctx
= agent_ctx
;
739 learn_parm
.data
= &data
;
740 rc
= assuan_transact (agent_ctx
, "LEARN --send",
741 learn_cb
, &learn_parm
,
742 NULL
, NULL
, NULL
, NULL
);
743 xfree (get_membuf (&data
, &len
));
746 return learn_parm
.error
;
750 /* Ask the agent to change the passphrase of the key identified by
751 HEXKEYGRIP. If DESC is not NULL, display instead of the default
752 description message. */
754 gpgsm_agent_passwd (ctrl_t ctrl
, const char *hexkeygrip
, const char *desc
)
757 char line
[ASSUAN_LINELENGTH
];
759 rc
= start_agent (ctrl
);
763 if (!hexkeygrip
|| strlen (hexkeygrip
) != 40)
764 return gpg_error (GPG_ERR_INV_VALUE
);
768 snprintf (line
, DIM(line
)-1, "SETKEYDESC %s", desc
);
769 line
[DIM(line
)-1] = 0;
770 rc
= assuan_transact (agent_ctx
, line
,
771 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
776 snprintf (line
, DIM(line
)-1, "PASSWD %s", hexkeygrip
);
777 line
[DIM(line
)-1] = 0;
779 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
,
780 default_inq_cb
, ctrl
, NULL
, NULL
);
786 /* Ask the agent to pop up a confirmation dialog with the text DESC
787 and an okay and cancel button. */
789 gpgsm_agent_get_confirmation (ctrl_t ctrl
, const char *desc
)
792 char line
[ASSUAN_LINELENGTH
];
794 rc
= start_agent (ctrl
);
798 snprintf (line
, DIM(line
)-1, "GET_CONFIRMATION %s", desc
);
799 line
[DIM(line
)-1] = 0;
801 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
,
802 default_inq_cb
, ctrl
, NULL
, NULL
);