Line data Source code
1 : /* call-agent.c - Divert GPGSM operations to the agent
2 : * Copyright (C) 2001, 2002, 2003, 2005, 2007,
3 : * 2008, 2009, 2010 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 :
33 : #include "gpgsm.h"
34 : #include <gcrypt.h>
35 : #include <assuan.h>
36 : #include "i18n.h"
37 : #include "asshelp.h"
38 : #include "keydb.h" /* fixme: Move this to import.c */
39 : #include "membuf.h"
40 : #include "shareddefs.h"
41 : #include "passphrase.h"
42 :
43 :
44 : static assuan_context_t agent_ctx = NULL;
45 :
46 :
47 : struct cipher_parm_s
48 : {
49 : ctrl_t ctrl;
50 : assuan_context_t ctx;
51 : const unsigned char *ciphertext;
52 : size_t ciphertextlen;
53 : };
54 :
55 : struct genkey_parm_s
56 : {
57 : ctrl_t ctrl;
58 : assuan_context_t ctx;
59 : const unsigned char *sexp;
60 : size_t sexplen;
61 : };
62 :
63 : struct learn_parm_s
64 : {
65 : int error;
66 : ctrl_t ctrl;
67 : assuan_context_t ctx;
68 : membuf_t *data;
69 : };
70 :
71 : struct import_key_parm_s
72 : {
73 : ctrl_t ctrl;
74 : assuan_context_t ctx;
75 : const void *key;
76 : size_t keylen;
77 : };
78 :
79 : struct default_inq_parm_s
80 : {
81 : ctrl_t ctrl;
82 : assuan_context_t ctx;
83 : };
84 :
85 :
86 : /* Print a warning if the server's version number is less than our
87 : version number. Returns an error code on a connection problem. */
88 : static gpg_error_t
89 0 : warn_version_mismatch (ctrl_t ctrl, assuan_context_t ctx,
90 : const char *servername, int mode)
91 : {
92 : gpg_error_t err;
93 : char *serverversion;
94 0 : const char *myversion = strusage (13);
95 :
96 0 : err = get_assuan_server_version (ctx, mode, &serverversion);
97 0 : if (err)
98 0 : log_error (_("error getting version from '%s': %s\n"),
99 : servername, gpg_strerror (err));
100 0 : else if (!compare_version_strings (serverversion, myversion))
101 : {
102 : char *warn;
103 :
104 0 : warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
105 : servername, serverversion, myversion);
106 0 : if (!warn)
107 0 : err = gpg_error_from_syserror ();
108 : else
109 : {
110 0 : log_info (_("WARNING: %s\n"), warn);
111 0 : gpgsm_status2 (ctrl, STATUS_WARNING, "server_version_mismatch 0",
112 : warn, NULL);
113 0 : xfree (warn);
114 : }
115 : }
116 0 : xfree (serverversion);
117 0 : return err;
118 : }
119 :
120 :
121 : /* Try to connect to the agent via socket or fork it off and work by
122 : pipes. Handle the server's initial greeting */
123 : static int
124 0 : start_agent (ctrl_t ctrl)
125 : {
126 : int rc;
127 :
128 0 : if (agent_ctx)
129 0 : rc = 0; /* fixme: We need a context for each thread or
130 : serialize the access to the agent (which is
131 : suitable given that the agent is not MT. */
132 : else
133 : {
134 0 : rc = start_new_gpg_agent (&agent_ctx,
135 : GPG_ERR_SOURCE_DEFAULT,
136 : opt.agent_program,
137 0 : opt.lc_ctype, opt.lc_messages,
138 : opt.session_env,
139 0 : opt.autostart, opt.verbose, DBG_IPC,
140 : gpgsm_status2, ctrl);
141 :
142 0 : if (!opt.autostart && gpg_err_code (rc) == GPG_ERR_NO_AGENT)
143 0 : {
144 : static int shown;
145 :
146 0 : if (!shown)
147 : {
148 0 : shown = 1;
149 0 : log_info (_("no gpg-agent running in this session\n"));
150 : }
151 : }
152 0 : else if (!rc && !(rc = warn_version_mismatch (ctrl, agent_ctx,
153 : GPG_AGENT_NAME, 0)))
154 : {
155 : /* Tell the agent that we support Pinentry notifications. No
156 : error checking so that it will work also with older
157 : agents. */
158 0 : assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
159 : NULL, NULL, NULL, NULL, NULL, NULL);
160 :
161 : /* Pass on the pinentry mode. */
162 0 : if (opt.pinentry_mode)
163 : {
164 0 : char *tmp = xasprintf ("OPTION pinentry-mode=%s",
165 0 : str_pinentry_mode (opt.pinentry_mode));
166 0 : rc = assuan_transact (agent_ctx, tmp,
167 : NULL, NULL, NULL, NULL, NULL, NULL);
168 0 : xfree (tmp);
169 0 : if (rc)
170 0 : log_error ("setting pinentry mode '%s' failed: %s\n",
171 0 : str_pinentry_mode (opt.pinentry_mode),
172 : gpg_strerror (rc));
173 : }
174 : }
175 : }
176 :
177 0 : if (!ctrl->agent_seen)
178 : {
179 0 : ctrl->agent_seen = 1;
180 0 : audit_log_ok (ctrl->audit, AUDIT_AGENT_READY, rc);
181 : }
182 :
183 0 : return rc;
184 : }
185 :
186 : /* This is the default inquiry callback. It mainly handles the
187 : Pinentry notifications. */
188 : static gpg_error_t
189 0 : default_inq_cb (void *opaque, const char *line)
190 : {
191 0 : gpg_error_t err = 0;
192 0 : struct default_inq_parm_s *parm = opaque;
193 0 : ctrl_t ctrl = parm->ctrl;
194 :
195 0 : if (has_leading_keyword (line, "PINENTRY_LAUNCHED"))
196 : {
197 0 : err = gpgsm_proxy_pinentry_notify (ctrl, line);
198 0 : if (err)
199 0 : log_error (_("failed to proxy %s inquiry to client\n"),
200 : "PINENTRY_LAUNCHED");
201 : /* We do not pass errors to avoid breaking other code. */
202 : }
203 0 : else if ((has_leading_keyword (line, "PASSPHRASE")
204 0 : || has_leading_keyword (line, "NEW_PASSPHRASE"))
205 0 : && opt.pinentry_mode == PINENTRY_MODE_LOOPBACK
206 0 : && have_static_passphrase ())
207 0 : {
208 0 : const char *s = get_static_passphrase ();
209 0 : err = assuan_send_data (parm->ctx, s, strlen (s));
210 : }
211 : else
212 0 : log_error ("ignoring gpg-agent inquiry '%s'\n", line);
213 :
214 0 : return err;
215 : }
216 :
217 :
218 :
219 :
220 : /* Call the agent to do a sign operation using the key identified by
221 : the hex string KEYGRIP. */
222 : int
223 0 : gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
224 : unsigned char *digest, size_t digestlen, int digestalgo,
225 : unsigned char **r_buf, size_t *r_buflen )
226 : {
227 : int rc, i;
228 : char *p, line[ASSUAN_LINELENGTH];
229 : membuf_t data;
230 : size_t len;
231 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
232 :
233 0 : *r_buf = NULL;
234 0 : rc = start_agent (ctrl);
235 0 : if (rc)
236 0 : return rc;
237 :
238 0 : if (digestlen*2 + 50 > DIM(line))
239 0 : return gpg_error (GPG_ERR_GENERAL);
240 :
241 0 : rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
242 0 : if (rc)
243 0 : return rc;
244 :
245 0 : snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
246 0 : line[DIM(line)-1] = 0;
247 0 : rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
248 0 : if (rc)
249 0 : return rc;
250 :
251 0 : if (desc)
252 : {
253 0 : snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
254 0 : line[DIM(line)-1] = 0;
255 0 : rc = assuan_transact (agent_ctx, line,
256 : NULL, NULL, NULL, NULL, NULL, NULL);
257 0 : if (rc)
258 0 : return rc;
259 : }
260 :
261 0 : sprintf (line, "SETHASH %d ", digestalgo);
262 0 : p = line + strlen (line);
263 0 : for (i=0; i < digestlen ; i++, p += 2 )
264 0 : sprintf (p, "%02X", digest[i]);
265 0 : rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
266 0 : if (rc)
267 0 : return rc;
268 :
269 0 : init_membuf (&data, 1024);
270 0 : rc = assuan_transact (agent_ctx, "PKSIGN",
271 : put_membuf_cb, &data, default_inq_cb, &inq_parm,
272 : NULL, NULL);
273 0 : if (rc)
274 : {
275 0 : xfree (get_membuf (&data, &len));
276 0 : return rc;
277 : }
278 0 : *r_buf = get_membuf (&data, r_buflen);
279 :
280 0 : if (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL))
281 : {
282 0 : xfree (*r_buf); *r_buf = NULL;
283 0 : return gpg_error (GPG_ERR_INV_VALUE);
284 : }
285 :
286 0 : return *r_buf? 0 : out_of_core ();
287 : }
288 :
289 :
290 : /* Call the scdaemon to do a sign operation using the key identified by
291 : the hex string KEYID. */
292 : int
293 0 : gpgsm_scd_pksign (ctrl_t ctrl, const char *keyid, const char *desc,
294 : unsigned char *digest, size_t digestlen, int digestalgo,
295 : unsigned char **r_buf, size_t *r_buflen )
296 : {
297 : int rc, i;
298 : char *p, line[ASSUAN_LINELENGTH];
299 : membuf_t data;
300 : size_t len;
301 : const char *hashopt;
302 : unsigned char *sigbuf;
303 : size_t sigbuflen;
304 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
305 :
306 : (void)desc;
307 :
308 0 : *r_buf = NULL;
309 :
310 0 : switch(digestalgo)
311 : {
312 0 : case GCRY_MD_SHA1: hashopt = "--hash=sha1"; break;
313 0 : case GCRY_MD_RMD160:hashopt = "--hash=rmd160"; break;
314 0 : case GCRY_MD_MD5: hashopt = "--hash=md5"; break;
315 0 : case GCRY_MD_SHA256:hashopt = "--hash=sha256"; break;
316 : default:
317 0 : return gpg_error (GPG_ERR_DIGEST_ALGO);
318 : }
319 :
320 0 : rc = start_agent (ctrl);
321 0 : if (rc)
322 0 : return rc;
323 :
324 0 : if (digestlen*2 + 50 > DIM(line))
325 0 : return gpg_error (GPG_ERR_GENERAL);
326 :
327 0 : p = stpcpy (line, "SCD SETDATA " );
328 0 : for (i=0; i < digestlen ; i++, p += 2 )
329 0 : sprintf (p, "%02X", digest[i]);
330 0 : rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
331 0 : if (rc)
332 0 : return rc;
333 :
334 0 : init_membuf (&data, 1024);
335 :
336 0 : snprintf (line, DIM(line)-1, "SCD PKSIGN %s %s", hashopt, keyid);
337 0 : line[DIM(line)-1] = 0;
338 0 : rc = assuan_transact (agent_ctx, line,
339 : put_membuf_cb, &data, default_inq_cb, &inq_parm,
340 : NULL, NULL);
341 0 : if (rc)
342 : {
343 0 : xfree (get_membuf (&data, &len));
344 0 : return rc;
345 : }
346 0 : sigbuf = get_membuf (&data, &sigbuflen);
347 :
348 : /* Create an S-expression from it which is formatted like this:
349 : "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" Fixme: If a card ever
350 : creates non-RSA keys we need to change things. */
351 0 : *r_buflen = 21 + 11 + sigbuflen + 4;
352 0 : p = xtrymalloc (*r_buflen);
353 0 : *r_buf = (unsigned char*)p;
354 0 : if (!p)
355 : {
356 0 : xfree (sigbuf);
357 0 : return 0;
358 : }
359 0 : p = stpcpy (p, "(7:sig-val(3:rsa(1:s" );
360 0 : sprintf (p, "%u:", (unsigned int)sigbuflen);
361 0 : p += strlen (p);
362 0 : memcpy (p, sigbuf, sigbuflen);
363 0 : p += sigbuflen;
364 0 : strcpy (p, ")))");
365 0 : xfree (sigbuf);
366 :
367 0 : assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
368 0 : return 0;
369 : }
370 :
371 :
372 :
373 :
374 : /* Handle a CIPHERTEXT inquiry. Note, we only send the data,
375 : assuan_transact takes care of flushing and writing the end */
376 : static gpg_error_t
377 0 : inq_ciphertext_cb (void *opaque, const char *line)
378 : {
379 0 : struct cipher_parm_s *parm = opaque;
380 : int rc;
381 :
382 0 : if (has_leading_keyword (line, "CIPHERTEXT"))
383 : {
384 0 : assuan_begin_confidential (parm->ctx);
385 0 : rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
386 0 : assuan_end_confidential (parm->ctx);
387 : }
388 : else
389 : {
390 0 : struct default_inq_parm_s inq_parm = { parm->ctrl, parm->ctx };
391 0 : rc = default_inq_cb (&inq_parm, line);
392 : }
393 :
394 0 : return rc;
395 : }
396 :
397 :
398 : /* Call the agent to do a decrypt operation using the key identified by
399 : the hex string KEYGRIP. */
400 : int
401 0 : gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
402 : ksba_const_sexp_t ciphertext,
403 : char **r_buf, size_t *r_buflen )
404 : {
405 : int rc;
406 : char line[ASSUAN_LINELENGTH];
407 : membuf_t data;
408 : struct cipher_parm_s cipher_parm;
409 : size_t n, len;
410 : char *p, *buf, *endp;
411 : size_t ciphertextlen;
412 :
413 0 : if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
414 0 : return gpg_error (GPG_ERR_INV_VALUE);
415 0 : *r_buf = NULL;
416 :
417 0 : ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL);
418 0 : if (!ciphertextlen)
419 0 : return gpg_error (GPG_ERR_INV_VALUE);
420 :
421 0 : rc = start_agent (ctrl);
422 0 : if (rc)
423 0 : return rc;
424 :
425 0 : rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
426 0 : if (rc)
427 0 : return rc;
428 :
429 : assert ( DIM(line) >= 50 );
430 0 : snprintf (line, DIM(line)-1, "SETKEY %s", keygrip);
431 0 : line[DIM(line)-1] = 0;
432 0 : rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
433 0 : if (rc)
434 0 : return rc;
435 :
436 0 : if (desc)
437 : {
438 0 : snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
439 0 : line[DIM(line)-1] = 0;
440 0 : rc = assuan_transact (agent_ctx, line,
441 : NULL, NULL, NULL, NULL, NULL, NULL);
442 0 : if (rc)
443 0 : return rc;
444 : }
445 :
446 0 : init_membuf (&data, 1024);
447 0 : cipher_parm.ctrl = ctrl;
448 0 : cipher_parm.ctx = agent_ctx;
449 0 : cipher_parm.ciphertext = ciphertext;
450 0 : cipher_parm.ciphertextlen = ciphertextlen;
451 0 : rc = assuan_transact (agent_ctx, "PKDECRYPT",
452 : put_membuf_cb, &data,
453 : inq_ciphertext_cb, &cipher_parm, NULL, NULL);
454 0 : if (rc)
455 : {
456 0 : xfree (get_membuf (&data, &len));
457 0 : return rc;
458 : }
459 :
460 0 : put_membuf (&data, "", 1); /* Make sure it is 0 terminated. */
461 0 : buf = get_membuf (&data, &len);
462 0 : if (!buf)
463 0 : return gpg_error (GPG_ERR_ENOMEM);
464 0 : assert (len); /* (we forced Nul termination.) */
465 :
466 0 : if (*buf == '(')
467 : {
468 0 : if (len < 13 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)\0" */
469 0 : return gpg_error (GPG_ERR_INV_SEXP);
470 0 : len -= 11; /* Count only the data of the second part. */
471 0 : p = buf + 8; /* Skip leading parenthesis and the value tag. */
472 : }
473 : else
474 : {
475 : /* For compatibility with older gpg-agents handle the old style
476 : incomplete S-exps. */
477 0 : len--; /* Do not count the Nul. */
478 0 : p = buf;
479 : }
480 :
481 0 : n = strtoul (p, &endp, 10);
482 0 : if (!n || *endp != ':')
483 0 : return gpg_error (GPG_ERR_INV_SEXP);
484 0 : endp++;
485 0 : if (endp-p+n > len)
486 0 : return gpg_error (GPG_ERR_INV_SEXP); /* Oops: Inconsistent S-Exp. */
487 :
488 0 : memmove (buf, endp, n);
489 :
490 0 : *r_buflen = n;
491 0 : *r_buf = buf;
492 0 : return 0;
493 : }
494 :
495 :
496 :
497 :
498 :
499 : /* Handle a KEYPARMS inquiry. Note, we only send the data,
500 : assuan_transact takes care of flushing and writing the end */
501 : static gpg_error_t
502 0 : inq_genkey_parms (void *opaque, const char *line)
503 : {
504 0 : struct genkey_parm_s *parm = opaque;
505 : int rc;
506 :
507 0 : if (has_leading_keyword (line, "KEYPARAM"))
508 : {
509 0 : rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
510 : }
511 : else
512 : {
513 0 : struct default_inq_parm_s inq_parm = { parm->ctrl, parm->ctx };
514 0 : rc = default_inq_cb (&inq_parm, line);
515 : }
516 :
517 0 : return rc;
518 : }
519 :
520 :
521 :
522 : /* Call the agent to generate a newkey */
523 : int
524 0 : gpgsm_agent_genkey (ctrl_t ctrl,
525 : ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
526 : {
527 : int rc;
528 : struct genkey_parm_s gk_parm;
529 : membuf_t data;
530 : size_t len;
531 : unsigned char *buf;
532 :
533 0 : *r_pubkey = NULL;
534 0 : rc = start_agent (ctrl);
535 0 : if (rc)
536 0 : return rc;
537 :
538 0 : rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
539 0 : if (rc)
540 0 : return rc;
541 :
542 0 : init_membuf (&data, 1024);
543 0 : gk_parm.ctrl = ctrl;
544 0 : gk_parm.ctx = agent_ctx;
545 0 : gk_parm.sexp = keyparms;
546 0 : gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
547 0 : if (!gk_parm.sexplen)
548 0 : return gpg_error (GPG_ERR_INV_VALUE);
549 0 : rc = assuan_transact (agent_ctx, "GENKEY",
550 : put_membuf_cb, &data,
551 : inq_genkey_parms, &gk_parm, NULL, NULL);
552 0 : if (rc)
553 : {
554 0 : xfree (get_membuf (&data, &len));
555 0 : return rc;
556 : }
557 0 : buf = get_membuf (&data, &len);
558 0 : if (!buf)
559 0 : return gpg_error (GPG_ERR_ENOMEM);
560 0 : if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
561 : {
562 0 : xfree (buf);
563 0 : return gpg_error (GPG_ERR_INV_SEXP);
564 : }
565 0 : *r_pubkey = buf;
566 0 : return 0;
567 : }
568 :
569 :
570 : /* Call the agent to read the public key part for a given keygrip. If
571 : FROMCARD is true, the key is directly read from the current
572 : smartcard. In this case HEXKEYGRIP should be the keyID
573 : (e.g. OPENPGP.3). */
574 : int
575 0 : gpgsm_agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
576 : ksba_sexp_t *r_pubkey)
577 : {
578 : int rc;
579 : membuf_t data;
580 : size_t len;
581 : unsigned char *buf;
582 : char line[ASSUAN_LINELENGTH];
583 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
584 :
585 0 : *r_pubkey = NULL;
586 0 : rc = start_agent (ctrl);
587 0 : if (rc)
588 0 : return rc;
589 :
590 0 : rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
591 0 : if (rc)
592 0 : return rc;
593 :
594 0 : snprintf (line, DIM(line)-1, "%sREADKEY %s",
595 : fromcard? "SCD ":"", hexkeygrip);
596 0 : line[DIM(line)-1] = 0;
597 :
598 0 : init_membuf (&data, 1024);
599 0 : rc = assuan_transact (agent_ctx, line,
600 : put_membuf_cb, &data,
601 : default_inq_cb, &inq_parm, NULL, NULL);
602 0 : if (rc)
603 : {
604 0 : xfree (get_membuf (&data, &len));
605 0 : return rc;
606 : }
607 0 : buf = get_membuf (&data, &len);
608 0 : if (!buf)
609 0 : return gpg_error (GPG_ERR_ENOMEM);
610 0 : if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
611 : {
612 0 : xfree (buf);
613 0 : return gpg_error (GPG_ERR_INV_SEXP);
614 : }
615 0 : *r_pubkey = buf;
616 0 : return 0;
617 : }
618 :
619 :
620 :
621 : /* Take the serial number from LINE and return it verbatim in a newly
622 : allocated string. We make sure that only hex characters are
623 : returned. */
624 : static char *
625 0 : store_serialno (const char *line)
626 : {
627 : const char *s;
628 : char *p;
629 :
630 0 : for (s=line; hexdigitp (s); s++)
631 : ;
632 0 : p = xtrymalloc (s + 1 - line);
633 0 : if (p)
634 : {
635 0 : memcpy (p, line, s-line);
636 0 : p[s-line] = 0;
637 : }
638 0 : return p;
639 : }
640 :
641 :
642 : /* Callback for the gpgsm_agent_serialno function. */
643 : static gpg_error_t
644 0 : scd_serialno_status_cb (void *opaque, const char *line)
645 : {
646 0 : char **r_serialno = opaque;
647 0 : const char *keyword = line;
648 : int keywordlen;
649 :
650 0 : for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
651 : ;
652 0 : while (spacep (line))
653 0 : line++;
654 :
655 0 : if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
656 : {
657 0 : xfree (*r_serialno);
658 0 : *r_serialno = store_serialno (line);
659 : }
660 :
661 0 : return 0;
662 : }
663 :
664 :
665 : /* Call the agent to read the serial number of the current card. */
666 : int
667 0 : gpgsm_agent_scd_serialno (ctrl_t ctrl, char **r_serialno)
668 : {
669 : int rc;
670 0 : char *serialno = NULL;
671 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
672 :
673 0 : *r_serialno = NULL;
674 0 : rc = start_agent (ctrl);
675 0 : if (rc)
676 0 : return rc;
677 :
678 0 : rc = assuan_transact (agent_ctx, "SCD SERIALNO",
679 : NULL, NULL,
680 : default_inq_cb, &inq_parm,
681 : scd_serialno_status_cb, &serialno);
682 0 : if (!rc && !serialno)
683 0 : rc = gpg_error (GPG_ERR_INTERNAL);
684 0 : if (rc)
685 : {
686 0 : xfree (serialno);
687 0 : return rc;
688 : }
689 0 : *r_serialno = serialno;
690 0 : return 0;
691 : }
692 :
693 :
694 :
695 : /* Callback for the gpgsm_agent_serialno function. */
696 : static gpg_error_t
697 0 : scd_keypairinfo_status_cb (void *opaque, const char *line)
698 : {
699 0 : strlist_t *listaddr = opaque;
700 0 : const char *keyword = line;
701 : int keywordlen;
702 : strlist_t sl;
703 : char *p;
704 :
705 0 : for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
706 : ;
707 0 : while (spacep (line))
708 0 : line++;
709 :
710 0 : if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
711 : {
712 0 : sl = append_to_strlist (listaddr, line);
713 0 : p = sl->d;
714 : /* Make sure that we only have two tokes so that future
715 : extensions of the format won't change the format expected by
716 : the caller. */
717 0 : while (*p && !spacep (p))
718 0 : p++;
719 0 : if (*p)
720 : {
721 0 : while (spacep (p))
722 0 : p++;
723 0 : while (*p && !spacep (p))
724 0 : p++;
725 0 : *p = 0;
726 : }
727 : }
728 :
729 0 : return 0;
730 : }
731 :
732 :
733 : /* Call the agent to read the keypairinfo lines of the current card.
734 : The list is returned as a string made up of the keygrip, a space
735 : and the keyid. */
736 : int
737 0 : gpgsm_agent_scd_keypairinfo (ctrl_t ctrl, strlist_t *r_list)
738 : {
739 : int rc;
740 0 : strlist_t list = NULL;
741 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
742 :
743 0 : *r_list = NULL;
744 0 : rc = start_agent (ctrl);
745 0 : if (rc)
746 0 : return rc;
747 :
748 0 : rc = assuan_transact (agent_ctx, "SCD LEARN --force",
749 : NULL, NULL,
750 : default_inq_cb, &inq_parm,
751 : scd_keypairinfo_status_cb, &list);
752 0 : if (!rc && !list)
753 0 : rc = gpg_error (GPG_ERR_NO_DATA);
754 0 : if (rc)
755 : {
756 0 : free_strlist (list);
757 0 : return rc;
758 : }
759 0 : *r_list = list;
760 0 : return 0;
761 : }
762 :
763 :
764 :
765 : static gpg_error_t
766 0 : istrusted_status_cb (void *opaque, const char *line)
767 : {
768 0 : struct rootca_flags_s *flags = opaque;
769 : const char *s;
770 :
771 0 : if ((s = has_leading_keyword (line, "TRUSTLISTFLAG")))
772 : {
773 0 : line = s;
774 0 : if (has_leading_keyword (line, "relax"))
775 0 : flags->relax = 1;
776 0 : else if (has_leading_keyword (line, "cm"))
777 0 : flags->chain_model = 1;
778 : }
779 0 : return 0;
780 : }
781 :
782 :
783 :
784 : /* Ask the agent whether the certificate is in the list of trusted
785 : keys. The certificate is either specified by the CERT object or by
786 : the fingerprint HEXFPR. ROOTCA_FLAGS is guaranteed to be cleared
787 : on error. */
788 : int
789 0 : gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert, const char *hexfpr,
790 : struct rootca_flags_s *rootca_flags)
791 : {
792 : int rc;
793 : char line[ASSUAN_LINELENGTH];
794 :
795 0 : memset (rootca_flags, 0, sizeof *rootca_flags);
796 :
797 0 : if (cert && hexfpr)
798 0 : return gpg_error (GPG_ERR_INV_ARG);
799 :
800 0 : rc = start_agent (ctrl);
801 0 : if (rc)
802 0 : return rc;
803 :
804 0 : if (hexfpr)
805 : {
806 0 : snprintf (line, DIM(line)-1, "ISTRUSTED %s", hexfpr);
807 0 : line[DIM(line)-1] = 0;
808 : }
809 : else
810 : {
811 : char *fpr;
812 :
813 0 : fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
814 0 : if (!fpr)
815 : {
816 0 : log_error ("error getting the fingerprint\n");
817 0 : return gpg_error (GPG_ERR_GENERAL);
818 : }
819 :
820 0 : snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr);
821 0 : line[DIM(line)-1] = 0;
822 0 : xfree (fpr);
823 : }
824 :
825 0 : rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
826 : istrusted_status_cb, rootca_flags);
827 0 : if (!rc)
828 0 : rootca_flags->valid = 1;
829 0 : return rc;
830 : }
831 :
832 : /* Ask the agent to mark CERT as a trusted Root-CA one */
833 : int
834 0 : gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
835 : {
836 : int rc;
837 : char *fpr, *dn, *dnfmt;
838 : char line[ASSUAN_LINELENGTH];
839 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
840 :
841 0 : rc = start_agent (ctrl);
842 0 : if (rc)
843 0 : return rc;
844 :
845 0 : fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
846 0 : if (!fpr)
847 : {
848 0 : log_error ("error getting the fingerprint\n");
849 0 : return gpg_error (GPG_ERR_GENERAL);
850 : }
851 :
852 0 : dn = ksba_cert_get_issuer (cert, 0);
853 0 : if (!dn)
854 : {
855 0 : xfree (fpr);
856 0 : return gpg_error (GPG_ERR_GENERAL);
857 : }
858 0 : dnfmt = gpgsm_format_name2 (dn, 0);
859 0 : xfree (dn);
860 0 : if (!dnfmt)
861 0 : return gpg_error_from_syserror ();
862 0 : snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dnfmt);
863 0 : line[DIM(line)-1] = 0;
864 0 : ksba_free (dnfmt);
865 0 : xfree (fpr);
866 :
867 0 : rc = assuan_transact (agent_ctx, line, NULL, NULL,
868 : default_inq_cb, &inq_parm, NULL, NULL);
869 0 : return rc;
870 : }
871 :
872 :
873 :
874 : /* Ask the agent whether the a corresponding secret key is available
875 : for the given keygrip */
876 : int
877 0 : gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
878 : {
879 : int rc;
880 : char line[ASSUAN_LINELENGTH];
881 :
882 0 : rc = start_agent (ctrl);
883 0 : if (rc)
884 0 : return rc;
885 :
886 0 : if (!hexkeygrip || strlen (hexkeygrip) != 40)
887 0 : return gpg_error (GPG_ERR_INV_VALUE);
888 :
889 0 : snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
890 0 : line[DIM(line)-1] = 0;
891 :
892 0 : rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
893 0 : return rc;
894 : }
895 :
896 :
897 : static gpg_error_t
898 0 : learn_status_cb (void *opaque, const char *line)
899 : {
900 0 : struct learn_parm_s *parm = opaque;
901 : const char *s;
902 :
903 : /* Pass progress data to the caller. */
904 0 : if ((s = has_leading_keyword (line, "PROGRESS")))
905 : {
906 0 : line = s;
907 0 : if (parm->ctrl)
908 : {
909 0 : if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
910 0 : return gpg_error (GPG_ERR_ASS_CANCELED);
911 : }
912 : }
913 0 : return 0;
914 : }
915 :
916 : static gpg_error_t
917 0 : learn_cb (void *opaque, const void *buffer, size_t length)
918 : {
919 0 : struct learn_parm_s *parm = opaque;
920 : size_t len;
921 : char *buf;
922 : ksba_cert_t cert;
923 : int rc;
924 :
925 0 : if (parm->error)
926 0 : return 0;
927 :
928 0 : if (buffer)
929 : {
930 0 : put_membuf (parm->data, buffer, length);
931 0 : return 0;
932 : }
933 : /* END encountered - process what we have */
934 0 : buf = get_membuf (parm->data, &len);
935 0 : if (!buf)
936 : {
937 0 : parm->error = gpg_error (GPG_ERR_ENOMEM);
938 0 : return 0;
939 : }
940 :
941 0 : if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, "learncard C 0 0"))
942 0 : return gpg_error (GPG_ERR_ASS_CANCELED);
943 :
944 : /* FIXME: this should go into import.c */
945 0 : rc = ksba_cert_new (&cert);
946 0 : if (rc)
947 : {
948 0 : parm->error = rc;
949 0 : return 0;
950 : }
951 0 : rc = ksba_cert_init_from_mem (cert, buf, len);
952 0 : if (rc)
953 : {
954 0 : log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
955 0 : ksba_cert_release (cert);
956 0 : parm->error = rc;
957 0 : return 0;
958 : }
959 :
960 : /* We do not store a certifciate with missing issuers as ephemeral
961 : because we can assume that the --learn-card command has been used
962 : on purpose. */
963 0 : rc = gpgsm_basic_cert_check (parm->ctrl, cert);
964 0 : if (rc && gpg_err_code (rc) != GPG_ERR_MISSING_CERT
965 0 : && gpg_err_code (rc) != GPG_ERR_MISSING_ISSUER_CERT)
966 0 : log_error ("invalid certificate: %s\n", gpg_strerror (rc));
967 : else
968 : {
969 : int existed;
970 :
971 0 : if (!keydb_store_cert (cert, 0, &existed))
972 : {
973 0 : if (opt.verbose > 1 && existed)
974 0 : log_info ("certificate already in DB\n");
975 0 : else if (opt.verbose && !existed)
976 0 : log_info ("certificate imported\n");
977 : }
978 : }
979 :
980 0 : ksba_cert_release (cert);
981 0 : init_membuf (parm->data, 4096);
982 0 : return 0;
983 : }
984 :
985 : /* Call the agent to learn about a smartcard */
986 : int
987 0 : gpgsm_agent_learn (ctrl_t ctrl)
988 : {
989 : int rc;
990 : struct learn_parm_s learn_parm;
991 : membuf_t data;
992 : size_t len;
993 :
994 0 : rc = start_agent (ctrl);
995 0 : if (rc)
996 0 : return rc;
997 :
998 0 : rc = warn_version_mismatch (ctrl, agent_ctx, SCDAEMON_NAME, 2);
999 0 : if (rc)
1000 0 : return rc;
1001 :
1002 0 : init_membuf (&data, 4096);
1003 0 : learn_parm.error = 0;
1004 0 : learn_parm.ctrl = ctrl;
1005 0 : learn_parm.ctx = agent_ctx;
1006 0 : learn_parm.data = &data;
1007 0 : rc = assuan_transact (agent_ctx, "LEARN --send",
1008 : learn_cb, &learn_parm,
1009 : NULL, NULL,
1010 : learn_status_cb, &learn_parm);
1011 0 : xfree (get_membuf (&data, &len));
1012 0 : if (rc)
1013 0 : return rc;
1014 0 : return learn_parm.error;
1015 : }
1016 :
1017 :
1018 : /* Ask the agent to change the passphrase of the key identified by
1019 : HEXKEYGRIP. If DESC is not NULL, display instead of the default
1020 : description message. */
1021 : int
1022 0 : gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
1023 : {
1024 : int rc;
1025 : char line[ASSUAN_LINELENGTH];
1026 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
1027 :
1028 0 : rc = start_agent (ctrl);
1029 0 : if (rc)
1030 0 : return rc;
1031 :
1032 0 : if (!hexkeygrip || strlen (hexkeygrip) != 40)
1033 0 : return gpg_error (GPG_ERR_INV_VALUE);
1034 :
1035 0 : if (desc)
1036 : {
1037 0 : snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
1038 0 : line[DIM(line)-1] = 0;
1039 0 : rc = assuan_transact (agent_ctx, line,
1040 : NULL, NULL, NULL, NULL, NULL, NULL);
1041 0 : if (rc)
1042 0 : return rc;
1043 : }
1044 :
1045 0 : snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
1046 0 : line[DIM(line)-1] = 0;
1047 :
1048 0 : rc = assuan_transact (agent_ctx, line, NULL, NULL,
1049 : default_inq_cb, &inq_parm, NULL, NULL);
1050 0 : return rc;
1051 : }
1052 :
1053 :
1054 :
1055 : /* Ask the agent to pop up a confirmation dialog with the text DESC
1056 : and an okay and cancel button. */
1057 : gpg_error_t
1058 0 : gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc)
1059 : {
1060 : int rc;
1061 : char line[ASSUAN_LINELENGTH];
1062 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
1063 :
1064 0 : rc = start_agent (ctrl);
1065 0 : if (rc)
1066 0 : return rc;
1067 :
1068 0 : snprintf (line, DIM(line)-1, "GET_CONFIRMATION %s", desc);
1069 0 : line[DIM(line)-1] = 0;
1070 :
1071 0 : rc = assuan_transact (agent_ctx, line, NULL, NULL,
1072 : default_inq_cb, &inq_parm, NULL, NULL);
1073 0 : return rc;
1074 : }
1075 :
1076 :
1077 :
1078 : /* Return 0 if the agent is alive. This is useful to make sure that
1079 : an agent has been started. */
1080 : gpg_error_t
1081 0 : gpgsm_agent_send_nop (ctrl_t ctrl)
1082 : {
1083 : int rc;
1084 :
1085 0 : rc = start_agent (ctrl);
1086 0 : if (!rc)
1087 0 : rc = assuan_transact (agent_ctx, "NOP",
1088 : NULL, NULL, NULL, NULL, NULL, NULL);
1089 0 : return rc;
1090 : }
1091 :
1092 :
1093 :
1094 : static gpg_error_t
1095 0 : keyinfo_status_cb (void *opaque, const char *line)
1096 : {
1097 0 : char **serialno = opaque;
1098 : const char *s, *s2;
1099 :
1100 0 : if ((s = has_leading_keyword (line, "KEYINFO")) && !*serialno)
1101 : {
1102 0 : s = strchr (s, ' ');
1103 0 : if (s && s[1] == 'T' && s[2] == ' ' && s[3])
1104 : {
1105 0 : s += 3;
1106 0 : s2 = strchr (s, ' ');
1107 0 : if ( s2 > s )
1108 : {
1109 0 : *serialno = xtrymalloc ((s2 - s)+1);
1110 0 : if (*serialno)
1111 : {
1112 0 : memcpy (*serialno, s, s2 - s);
1113 0 : (*serialno)[s2 - s] = 0;
1114 : }
1115 : }
1116 : }
1117 : }
1118 0 : return 0;
1119 : }
1120 :
1121 : /* Return the serial number for a secret key. If the returned serial
1122 : number is NULL, the key is not stored on a smartcard. Caller needs
1123 : to free R_SERIALNO. */
1124 : gpg_error_t
1125 0 : gpgsm_agent_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
1126 : {
1127 : gpg_error_t err;
1128 : char line[ASSUAN_LINELENGTH];
1129 0 : char *serialno = NULL;
1130 :
1131 0 : *r_serialno = NULL;
1132 :
1133 0 : err = start_agent (ctrl);
1134 0 : if (err)
1135 0 : return err;
1136 :
1137 0 : if (!hexkeygrip || strlen (hexkeygrip) != 40)
1138 0 : return gpg_error (GPG_ERR_INV_VALUE);
1139 :
1140 0 : snprintf (line, DIM(line)-1, "KEYINFO %s", hexkeygrip);
1141 0 : line[DIM(line)-1] = 0;
1142 :
1143 0 : err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
1144 : keyinfo_status_cb, &serialno);
1145 0 : if (!err && serialno)
1146 : {
1147 : /* Sanity check for bad characters. */
1148 0 : if (strpbrk (serialno, ":\n\r"))
1149 0 : err = GPG_ERR_INV_VALUE;
1150 : }
1151 0 : if (err)
1152 0 : xfree (serialno);
1153 : else
1154 0 : *r_serialno = serialno;
1155 0 : return err;
1156 : }
1157 :
1158 :
1159 :
1160 : /* Ask for the passphrase (this is used for pkcs#12 import/export. On
1161 : success the caller needs to free the string stored at R_PASSPHRASE.
1162 : On error NULL will be stored at R_PASSPHRASE and an appropriate
1163 : error code returned. If REPEAT is true the agent tries to get a
1164 : new passphrase (i.e. asks the user to confirm it). */
1165 : gpg_error_t
1166 0 : gpgsm_agent_ask_passphrase (ctrl_t ctrl, const char *desc_msg, int repeat,
1167 : char **r_passphrase)
1168 : {
1169 : gpg_error_t err;
1170 : char line[ASSUAN_LINELENGTH];
1171 0 : char *arg4 = NULL;
1172 : membuf_t data;
1173 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
1174 :
1175 0 : *r_passphrase = NULL;
1176 :
1177 0 : err = start_agent (ctrl);
1178 0 : if (err)
1179 0 : return err;
1180 :
1181 0 : if (desc_msg && *desc_msg && !(arg4 = percent_plus_escape (desc_msg)))
1182 0 : return gpg_error_from_syserror ();
1183 :
1184 0 : snprintf (line, DIM(line)-1, "GET_PASSPHRASE --data%s -- X X X %s",
1185 : repeat? " --repeat=1 --check --qualitybar":"",
1186 : arg4);
1187 0 : xfree (arg4);
1188 :
1189 0 : init_membuf_secure (&data, 64);
1190 0 : err = assuan_transact (agent_ctx, line,
1191 : put_membuf_cb, &data,
1192 : default_inq_cb, &inq_parm, NULL, NULL);
1193 :
1194 0 : if (err)
1195 0 : xfree (get_membuf (&data, NULL));
1196 : else
1197 : {
1198 0 : put_membuf (&data, "", 1);
1199 0 : *r_passphrase = get_membuf (&data, NULL);
1200 0 : if (!*r_passphrase)
1201 0 : err = gpg_error_from_syserror ();
1202 : }
1203 0 : return err;
1204 : }
1205 :
1206 :
1207 :
1208 : /* Retrieve a key encryption key from the agent. With FOREXPORT true
1209 : the key shall be use for export, with false for import. On success
1210 : the new key is stored at R_KEY and its length at R_KEKLEN. */
1211 : gpg_error_t
1212 0 : gpgsm_agent_keywrap_key (ctrl_t ctrl, int forexport,
1213 : void **r_kek, size_t *r_keklen)
1214 : {
1215 : gpg_error_t err;
1216 : membuf_t data;
1217 : size_t len;
1218 : unsigned char *buf;
1219 : char line[ASSUAN_LINELENGTH];
1220 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
1221 :
1222 0 : *r_kek = NULL;
1223 0 : err = start_agent (ctrl);
1224 0 : if (err)
1225 0 : return err;
1226 :
1227 0 : snprintf (line, DIM(line)-1, "KEYWRAP_KEY %s",
1228 : forexport? "--export":"--import");
1229 :
1230 0 : init_membuf_secure (&data, 64);
1231 0 : err = assuan_transact (agent_ctx, line,
1232 : put_membuf_cb, &data,
1233 : default_inq_cb, &inq_parm, NULL, NULL);
1234 0 : if (err)
1235 : {
1236 0 : xfree (get_membuf (&data, &len));
1237 0 : return err;
1238 : }
1239 0 : buf = get_membuf (&data, &len);
1240 0 : if (!buf)
1241 0 : return gpg_error_from_syserror ();
1242 0 : *r_kek = buf;
1243 0 : *r_keklen = len;
1244 0 : return 0;
1245 : }
1246 :
1247 :
1248 :
1249 :
1250 : /* Handle the inquiry for an IMPORT_KEY command. */
1251 : static gpg_error_t
1252 0 : inq_import_key_parms (void *opaque, const char *line)
1253 : {
1254 0 : struct import_key_parm_s *parm = opaque;
1255 : gpg_error_t err;
1256 :
1257 0 : if (has_leading_keyword (line, "KEYDATA"))
1258 : {
1259 0 : assuan_begin_confidential (parm->ctx);
1260 0 : err = assuan_send_data (parm->ctx, parm->key, parm->keylen);
1261 0 : assuan_end_confidential (parm->ctx);
1262 : }
1263 : else
1264 : {
1265 0 : struct default_inq_parm_s inq_parm = { parm->ctrl, parm->ctx };
1266 0 : err = default_inq_cb (&inq_parm, line);
1267 : }
1268 :
1269 0 : return err;
1270 : }
1271 :
1272 :
1273 : /* Call the agent to import a key into the agent. */
1274 : gpg_error_t
1275 0 : gpgsm_agent_import_key (ctrl_t ctrl, const void *key, size_t keylen)
1276 : {
1277 : gpg_error_t err;
1278 : struct import_key_parm_s parm;
1279 :
1280 0 : err = start_agent (ctrl);
1281 0 : if (err)
1282 0 : return err;
1283 :
1284 0 : parm.ctrl = ctrl;
1285 0 : parm.ctx = agent_ctx;
1286 0 : parm.key = key;
1287 0 : parm.keylen = keylen;
1288 :
1289 0 : err = assuan_transact (agent_ctx, "IMPORT_KEY",
1290 : NULL, NULL, inq_import_key_parms, &parm, NULL, NULL);
1291 0 : return err;
1292 : }
1293 :
1294 :
1295 :
1296 : /* Receive a secret key from the agent. KEYGRIP is the hexified
1297 : keygrip, DESC a prompt to be displayed with the agent's passphrase
1298 : question (needs to be plus+percent escaped). On success the key is
1299 : stored as a canonical S-expression at R_RESULT and R_RESULTLEN. */
1300 : gpg_error_t
1301 0 : gpgsm_agent_export_key (ctrl_t ctrl, const char *keygrip, const char *desc,
1302 : unsigned char **r_result, size_t *r_resultlen)
1303 : {
1304 : gpg_error_t err;
1305 : membuf_t data;
1306 : size_t len;
1307 : unsigned char *buf;
1308 : char line[ASSUAN_LINELENGTH];
1309 0 : struct default_inq_parm_s inq_parm = { ctrl, agent_ctx };
1310 :
1311 0 : *r_result = NULL;
1312 :
1313 0 : err = start_agent (ctrl);
1314 0 : if (err)
1315 0 : return err;
1316 :
1317 0 : if (desc)
1318 : {
1319 0 : snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
1320 0 : err = assuan_transact (agent_ctx, line,
1321 : NULL, NULL, NULL, NULL, NULL, NULL);
1322 0 : if (err)
1323 0 : return err;
1324 : }
1325 :
1326 0 : snprintf (line, DIM(line)-1, "EXPORT_KEY %s", keygrip);
1327 :
1328 0 : init_membuf_secure (&data, 1024);
1329 0 : err = assuan_transact (agent_ctx, line,
1330 : put_membuf_cb, &data,
1331 : default_inq_cb, &inq_parm, NULL, NULL);
1332 0 : if (err)
1333 : {
1334 0 : xfree (get_membuf (&data, &len));
1335 0 : return err;
1336 : }
1337 0 : buf = get_membuf (&data, &len);
1338 0 : if (!buf)
1339 0 : return gpg_error_from_syserror ();
1340 0 : *r_result = buf;
1341 0 : *r_resultlen = len;
1342 0 : return 0;
1343 : }
|