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