Reimplemented cipher iterations.
[pwmd.git] / src / agent.c
blobcc3cf0f030b8bfc580957106c664a1645d2d4148
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdlib.h>
26 #include <glib.h>
27 #include <glib/gprintf.h>
28 #include <glib/gstdio.h>
29 #include <errno.h>
30 #include <pwd.h>
31 #include <signal.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <fcntl.h>
35 #include <dirent.h>
36 #include "pwmd-error.h"
37 #include "mem.h"
38 #include "common.h"
39 #include "commands.h"
40 #include "agent.h"
41 #include "misc.h"
42 #include "mutex.h"
43 #include "rcfile.h"
44 #include "cache.h"
45 #include "cipher.h"
47 #ifdef WITH_LIBACL
48 #include <acl/libacl.h>
49 #endif
51 #ifdef __FreeBSD__
52 #include <sys/types.h>
53 #include <signal.h>
54 #endif
56 static guint8 pwmd_magic[5] = { '\177', 'P', 'W', 'M', 'D' };
58 static gpg_error_t mem_realloc_cb(void *data, const void *buffer, size_t len)
60 membuf_t *mem = (membuf_t *)data;
61 void *p;
63 if (!buffer)
64 return 0;
66 if ((p = xrealloc(mem->buf, mem->len + len)) == NULL)
67 return 1;
69 mem->buf = p;
70 memcpy((char *)mem->buf + mem->len, buffer, len);
71 mem->len += len;
72 return 0;
75 static gpg_error_t status_cb(gpointer data, const gchar *line)
77 struct agent_s *agent = data;
79 agent->inquire_maxlen = 0;
81 if (!strncmp(line, "INQUIRE_MAXLEN ", 15)) {
82 agent->inquire_maxlen = atoi(line+15);
83 if (!agent->client_ctx)
84 return 0;
87 return send_status(agent->client_ctx, STATUS_AGENT, "%s", line);
90 static gpg_error_t assuan_command(struct agent_s *a, gchar **result,
91 gsize *len, const gchar *cmd)
93 gpg_error_t rc;
95 a->data.len = 0;
96 a->data.buf = NULL;
97 if (result)
98 *result = NULL;
99 if (len)
100 *len = 0;
101 rc = assuan_transact(a->ctx, cmd, mem_realloc_cb, &a->data,
102 a->inquire_cb, a->inquire_data, status_cb, a);
104 if (rc)
105 xfree(a->data.buf);
106 else {
107 if (a->data.buf) {
108 mem_realloc_cb(&a->data, "", 1);
109 if (result)
110 *result = (gchar *)a->data.buf;
111 else
112 xfree(a->data.buf);
114 if (len)
115 *len = a->data.len;
119 return rc;
122 /* This commands are sent from launch_agent() after reconnecting to the agent
123 * and also from the initial client connection. */
124 static gpg_error_t send_agent_common_options(struct agent_s *agent)
126 gpg_error_t rc;
128 rc = send_to_agent(agent, NULL, NULL, "OPTION cache-ttl-opt-preset=-1");
129 return rc;
132 static gpg_error_t launch_agent(struct agent_s *agent)
134 gpg_error_t rc;
135 assuan_context_t ctx;
136 const gchar *t = NULL;
137 static struct assuan_malloc_hooks mhooks = { xmalloc, xrealloc, xfree };
138 gchar *s, buf[LINE_MAX];
139 FILE *fp;
141 s = get_key_file_string("global", "agent_env_file");
142 if (s) {
143 gchar *ss = expand_homedir(s);
145 g_free(s);
146 fp = fopen(ss, "r");
147 g_free(ss);
149 if (fp) {
150 while ((s = fgets(buf, sizeof(buf), fp))) {
151 s = g_strchomp(s);
152 if (g_str_has_prefix(s, "GPG_AGENT_INFO=")) {
153 g_setenv("GPG_AGENT_INFO", s+strlen("GPG_AGENT_INFO="), TRUE);
154 break;
158 fclose(fp);
160 else
161 log_write("%s: %s", s, pwmd_strerror(gpg_error_from_syserror()));
164 t = g_getenv("GPG_AGENT_INFO");
165 if (!t)
166 return gpg_err_code(GPG_ERR_NO_AGENT);
168 rc = assuan_new_ext(&ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks,
169 debug_level ? assuan_log_cb : NULL, "AGENT ");
170 if (rc)
171 return rc;
173 gchar **fields = g_strsplit(t, ":", 0);
174 rc = assuan_socket_connect(ctx, fields[0], ASSUAN_INVALID_PID, 0);
175 g_strfreev(fields);
176 if (rc) {
177 assuan_release(ctx);
178 return rc;
181 if (agent->ctx) {
182 /* Restore the previous agent settings for this new context. */
183 assuan_release(agent->ctx);
184 agent->ctx = ctx;
185 rc = send_agent_common_options(agent);
186 if (!rc && agent->display)
187 rc = set_agent_option(agent, "display", agent->display);
189 if (!rc && agent->ttyname)
190 rc = set_agent_option(agent, "ttyname", agent->ttyname);
192 if (!rc && agent->ttytype)
193 rc = set_agent_option(agent, "ttytype", agent->ttytype);
195 if (!rc && agent->lc_messages)
196 rc = set_agent_option(agent, "lc-messages", agent->lc_messages);
198 if (!rc && agent->lc_ctype)
199 rc = set_agent_option(agent, "lc-ctype", agent->lc_ctype);
202 agent->ctx = ctx;
203 return 0;
206 gpg_error_t send_to_agent(struct agent_s *agent, gchar **result, gsize *len,
207 const gchar *fmt, ...)
209 gpg_error_t rc = 0;
210 va_list ap;
211 gchar *cmd;
213 if (!agent->ctx) {
214 rc = launch_agent(agent);
215 if (rc)
216 return rc;
219 va_start(ap, fmt);
220 if (g_vasprintf(&cmd, fmt, ap) > 0) {
221 rc = assuan_command(agent, result, len, cmd);
222 if (!agent->restart && gpg_err_source(rc) == GPG_ERR_SOURCE_DEFAULT
223 && (gpg_err_code(rc) == GPG_ERR_ASS_CONNECT_FAILED
224 || gpg_err_code(rc) == GPG_ERR_EPIPE)) {
225 g_unsetenv("GPG_AGENT_INFO");
226 agent->restart = TRUE;
227 rc = launch_agent(agent);
228 if (!rc)
229 rc = assuan_command(agent, result, len, cmd);
232 agent->restart = FALSE;
233 g_free(cmd);
235 else
236 rc = GPG_ERR_ENOMEM;
238 va_end(ap);
239 return rc;
242 static void agent_disconnect(struct agent_s *agent)
244 if (!agent)
245 return;
247 if (agent->ctx)
248 assuan_release(agent->ctx);
250 agent->ctx = NULL;
253 void cleanup_agent(struct agent_s *agent)
255 if (!agent)
256 return;
258 g_free(agent->desc);
259 g_free(agent->display);
260 g_free(agent->ttyname);
261 g_free(agent->ttytype);
262 g_free(agent->lc_messages);
263 g_free(agent->lc_ctype);
265 if (agent->ctx)
266 agent_disconnect(agent);
268 g_free(agent);
271 gpg_error_t agent_init(struct agent_s **agent)
273 struct agent_s *new = g_malloc0(sizeof(struct agent_s));
275 if (!new)
276 return GPG_ERR_ENOMEM;
278 *agent = new;
279 return 0;
282 void set_header_defaults(file_header_t *hdr)
284 gchar *s = get_key_file_string(NULL, "cipher");
285 gint flags = cipher_string_to_cipher(s);
287 g_free(s);
288 memset(hdr, 0, sizeof(file_header_t));
289 memcpy(hdr->magic, pwmd_magic, sizeof(hdr->magic));
290 if (flags == -1)
291 log_write(_("Invalid 'cipher' in configuration file. Using a default of aes256."));
292 hdr->flags = flags == -1 ? PWMD_CIPHER_AES256 : flags;
293 hdr->version = VERSION_HEX;
296 gpg_error_t read_data_header(const gchar *filename, file_header_t *rhdr,
297 struct stat *rst, gint *rfd)
299 gpg_error_t rc = 0;
300 gsize len;
301 struct stat st;
302 file_header_t hdr;
303 gint fd;
305 if (g_lstat(filename, &st) == -1)
306 return gpg_error_from_syserror();
308 if (!S_ISREG(st.st_mode))
309 return GPG_ERR_ENOANO;
311 fd = open(filename, O_RDONLY);
312 if (fd == -1)
313 return gpg_error_from_syserror();
315 len = read(fd, &hdr, sizeof(file_header_t));
316 if (len != sizeof(file_header_t))
317 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
319 if (!rc && memcmp(hdr.magic, pwmd_magic, sizeof(hdr.magic)))
320 rc = GPG_ERR_BAD_DATA;
321 else if (hdr.version < 0x030000)
322 rc = GPG_ERR_UNKNOWN_VERSION;
324 if (rc)
325 close(fd);
326 else {
327 if (rhdr)
328 *rhdr = hdr;
329 if (rst)
330 *rst = st;
331 if (rfd)
332 *rfd = fd;
333 else
334 close(fd);
337 return rc;
340 gpg_error_t read_data_file(const gchar *filename, struct crypto_s *crypto)
342 gint fd;
343 gpg_error_t rc = 0;
344 gsize len, rlen;
345 gchar *buf = NULL;
346 struct stat st;
348 cleanup_crypto_stage1(crypto);
349 rc = read_data_header(filename, &crypto->hdr, &st, &fd);
350 if (rc)
351 return rc;
353 crypto->ciphertext_len = crypto->hdr.datalen;
354 crypto->ciphertext = g_malloc(crypto->hdr.datalen);
355 if (!crypto->ciphertext) {
356 rc = GPG_ERR_ENOMEM;
357 goto fail;
360 rlen = read(fd, crypto->grip, 20);
361 if (rlen != 20) {
362 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
363 goto fail;
366 rlen = read(fd, crypto->sign_grip, 20);
367 if (rlen != 20) {
368 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
369 goto fail;
372 len = read(fd, crypto->ciphertext, crypto->hdr.datalen);
373 if (len != crypto->hdr.datalen) {
374 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
375 goto fail;
378 len = st.st_size-sizeof(file_header_t)-crypto->hdr.datalen-40;
379 buf = g_malloc(len);
380 if (!buf) {
381 rc = GPG_ERR_ENOMEM;
382 goto fail;
385 rlen = read(fd, buf, len);
386 if (rlen != len) {
387 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
388 goto fail;
391 rc = gcry_sexp_new(&crypto->ciphertext_sexp, buf, rlen, 1);
392 if (rc)
393 goto fail;
395 if (crypto->pkey_sexp)
396 gcry_sexp_release(crypto->pkey_sexp);
398 if (crypto->sigpkey_sexp)
399 gcry_sexp_release(crypto->sigpkey_sexp);
401 crypto->pkey_sexp = crypto->sigpkey_sexp = NULL;
402 rc = get_pubkey_bin(crypto, crypto->grip, &crypto->pkey_sexp);
403 if (!rc)
404 rc = get_pubkey_bin(crypto, crypto->sign_grip, &crypto->sigpkey_sexp);
406 fail:
407 close(fd);
408 g_free(buf);
409 return rc;
412 static gpg_error_t inquire_cb(gpointer user, const char *keyword)
414 struct inquire_data_s *idata = user;
416 if (!idata->preset && (!g_strcmp0(keyword, "PASSPHRASE")
417 || !g_strcmp0(keyword, "NEW_PASSPHRASE"))) {
418 return agent_loopback_cb(idata->crypto, keyword);
420 // SAVE --inquire-keyparam
421 else if (idata->preset && !g_strcmp0(keyword, "KEYPARAM")) {
422 idata->preset = FALSE;
423 return agent_loopback_cb(idata->crypto, keyword);
426 if (idata->crypto->agent->inquire_maxlen
427 && idata->len > idata->crypto->agent->inquire_maxlen) {
428 log_write(_("Inquired data too large: have=%u, max=%u"), idata->len,
429 idata->crypto->agent->inquire_maxlen);
430 return GPG_ERR_TOO_LARGE;
433 idata->crypto->agent->inquire_maxlen = 0;
434 return assuan_send_data(idata->crypto->agent->ctx, idata->line, idata->len);
437 static gpg_error_t extract_key(struct crypto_s *crypto, guchar **result,
438 gsize *result_len)
440 gpg_error_t rc;
441 gcry_sexp_t enc_sexp = NULL, tmp_sexp;
442 struct inquire_data_s idata = {0};
443 gchar *hexgrip = NULL;
444 gchar *key;
445 gsize keylen, keysize;
446 gchar *tmp;
447 gint algo = cipher_to_gcrypt(crypto->hdr.flags);
448 gboolean shadowed;
450 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
451 if (rc)
452 return rc;
454 tmp_sexp = gcry_sexp_find_token(crypto->ciphertext_sexp, "enc-val", 0);
455 if (!tmp_sexp)
456 return GPG_ERR_BAD_DATA;
458 hexgrip = bin2hex(crypto->grip, sizeof(crypto->grip));
459 if (!hexgrip) {
460 rc = GPG_ERR_ENOMEM;
461 goto fail;
464 rc = cache_is_shadowed(hexgrip);
465 if (rc && rc != GPG_ERR_NO_DATA)
466 goto fail;
468 shadowed = !rc ? TRUE : FALSE;
469 if (!shadowed) {
470 gcry_sexp_t tmp2_sexp = gcry_sexp_cdr(tmp_sexp);
471 gcry_sexp_release(tmp_sexp);
472 tmp_sexp = gcry_sexp_nth(tmp2_sexp, 0);
473 gcry_sexp_release(tmp2_sexp);
474 rc = gcry_sexp_build(&enc_sexp, NULL, "(enc-val (flags pkcs1) %S)",
475 tmp_sexp);
477 else
478 rc = gcry_sexp_build(&enc_sexp, NULL, "%S", tmp_sexp);
480 gcry_sexp_release(tmp_sexp);
481 if (rc)
482 return rc;
484 crypto->agent->inquire_cb = inquire_cb;
485 idata.crypto = crypto;
486 idata.len = gcry_sexp_sprint(enc_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
487 idata.line = g_malloc(idata.len);
488 if (!idata.line) {
489 rc = GPG_ERR_ENOMEM;
490 goto fail;
493 idata.len = gcry_sexp_sprint(enc_sexp, GCRYSEXP_FMT_CANON, idata.line,
494 idata.len);
495 crypto->agent->inquire_data = &idata;
496 gcry_sexp_release(enc_sexp);
497 enc_sexp = NULL;
498 log_write1(_("Keygrip is %s, bits=%i"), hexgrip,
499 gcry_pk_get_nbits(crypto->pkey_sexp));
500 rc = send_to_agent(crypto->agent, NULL, NULL, "SETKEY %s", hexgrip);
501 if (rc)
502 goto fail;
504 if (!crypto->agent->desc) {
505 tmp = plus_escape(_(
506 "A %s is required to unlock the secret key for the "
507 "encrypted data file \"%s\". Please enter the %s "
508 "below."),
509 shadowed ? "PIN" : _("passphrase"), crypto->filename,
510 shadowed ? "PIN" : _("passphrase"));
512 else
513 tmp = plus_escape(crypto->agent->desc);
515 rc = send_to_agent(crypto->agent, NULL, NULL, "SETKEYDESC %s", tmp);
516 g_free(tmp);
517 if (rc)
518 goto fail;
520 assuan_begin_confidential(crypto->agent->ctx);
521 rc = send_to_agent(crypto->agent, &key, &keylen, "PKDECRYPT");
522 assuan_end_confidential(crypto->agent->ctx);
523 if (rc)
524 goto fail;
526 rc = gcry_sexp_new(&tmp_sexp, key, keylen, 1);
527 xfree(key);
528 if (rc)
529 goto fail;
531 key = (gchar *)gcry_sexp_nth_data(tmp_sexp, 1, result_len);
532 if (key) {
533 *result = gcry_malloc(*result_len);
534 if (!*result)
535 rc = GPG_ERR_ENOMEM;
536 else
537 memcpy(*result, key, *result_len);
539 else
540 rc = GPG_ERR_BAD_DATA;
542 gcry_sexp_release(tmp_sexp);
544 fail:
545 g_free(idata.line);
546 g_free(hexgrip);
548 if (enc_sexp)
549 gcry_sexp_release(enc_sexp);
551 return rc;
554 static gpg_error_t verify(gcry_sexp_t pkey, gcry_sexp_t sig_sexp,
555 const gpointer data, gsize len)
557 gpg_error_t rc;
558 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
559 guchar *hash;
560 gcry_sexp_t data_sexp;
562 hash = gcry_malloc(hashlen);
563 if (!hash)
564 return GPG_ERR_ENOMEM;
566 gcry_md_hash_buffer(GCRY_MD_SHA256, hash, data, len);
567 rc = gcry_sexp_build(&data_sexp, NULL,
568 "(data (flags pkcs1) (hash sha256 %b))", hashlen, hash);
569 gcry_free(hash);
570 if (!rc) {
571 rc = gcry_pk_verify(sig_sexp, data_sexp, pkey);
572 gcry_sexp_release(data_sexp);
575 return rc;
578 #define CRYPTO_BLOCKSIZE(c) (blocksize * 1024)
581 * Useful for a large amount of data. Rather than doing all of the data in one
582 * iteration do it in chunks. This lets the command be cancelable rather than
583 * waiting for it to complete.
585 static gpg_error_t iterate_crypto_once(gcry_cipher_hd_t h, guchar *inbuf,
586 gsize insize, gsize blocksize, status_msg_t which)
588 gpg_error_t rc = 0;
589 goffset len = CRYPTO_BLOCKSIZE(blocksize);
590 gpointer p = gcry_malloc(len);
591 goffset total = 0;
592 guchar *inbuf2;
594 if (!p)
595 return GPG_ERR_ENOMEM;
597 if (insize < CRYPTO_BLOCKSIZE(blocksize))
598 len = insize;
600 pthread_cleanup_push(gcry_free, p);
602 for (;;) {
603 inbuf2 = inbuf+total;
604 guchar *tmp;
606 if (len + total > insize)
607 len = blocksize;
609 if (which == STATUS_ENCRYPT)
610 rc = gcry_cipher_encrypt(h, p, len, inbuf2, len);
611 else
612 rc = gcry_cipher_decrypt(h, p, len, inbuf2, len);
614 if (rc)
615 break;
617 tmp = inbuf+total;
618 memmove(tmp, p, len);
619 total += len;
620 if (total >= insize)
621 break;
623 pthread_testcancel();
626 pthread_cleanup_pop(1);
627 return rc;
630 gpg_error_t decrypt_data(assuan_context_t ctx, struct crypto_s *crypto)
632 gpg_error_t rc;
633 guchar *key = NULL;
634 gsize keylen = 0;
635 gcry_cipher_hd_t h = NULL;
636 gsize blocksize, keysize;
637 gint algo = cipher_to_gcrypt(crypto->hdr.flags);
638 gpointer outbuf = NULL;
639 gcry_sexp_t sig_sexp;
640 guint64 n = crypto->hdr.iterations, progress;
641 gchar *p;
643 rc = extract_key(crypto, &key, &keylen);
644 if (rc)
645 return rc;
647 sig_sexp = gcry_sexp_find_token(crypto->ciphertext_sexp, "sig-val", 0);
648 if (!sig_sexp) {
649 rc = GPG_ERR_BAD_DATA;
650 goto fail;
653 rc = verify(crypto->sigpkey_sexp, sig_sexp, crypto->ciphertext, crypto->ciphertext_len);
654 gcry_sexp_release(sig_sexp);
655 if (rc)
656 goto fail;
658 rc = gcry_cipher_open(&h, algo, GCRY_CIPHER_MODE_CBC, 0);
659 if (rc)
660 goto fail;
662 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
663 if (rc)
664 goto fail;
666 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_BLKLEN, NULL, &blocksize);
667 if (rc)
668 goto fail;
670 rc = gcry_cipher_setiv(h, crypto->hdr.iv, sizeof(crypto->hdr.iv));
671 if (rc)
672 goto fail;
674 rc = gcry_cipher_setkey(h, key, keylen);
675 if (rc)
676 goto fail;
678 outbuf = gcry_malloc(crypto->hdr.datalen);
679 if (!outbuf) {
680 rc = GPG_ERR_ENOMEM;
681 goto fail;
684 memcpy(outbuf, crypto->ciphertext, crypto->hdr.datalen);
685 rc = iterate_crypto_once(h, outbuf, crypto->hdr.datalen, blocksize,
686 STATUS_DECRYPT);
687 if (rc)
688 goto fail;
690 key[0] ^= 1;
691 rc = gcry_cipher_setkey(h, key, keylen);
692 if (rc)
693 goto fail;
695 p = get_key_file_string(NULL, "cipher_progress");
696 if (p) {
697 errno = 0;
698 progress = strtoull(p, NULL, 10);
699 if (errno)
700 progress = strtoull(DEFAULT_ITERATION_PROGRESS, NULL, 10);
702 g_free(p);
704 else
705 progress = strtoull(DEFAULT_ITERATION_PROGRESS, NULL, 10);
707 if (!rc && ctx && crypto->hdr.iterations)
708 rc = send_status(ctx, STATUS_DECRYPT, "%llu %llu", 0,
709 crypto->hdr.iterations);
711 for (n = 0; !rc && n < crypto->hdr.iterations; n++) {
712 if (ctx && !(n%progress)) {
713 rc = send_status(ctx, STATUS_DECRYPT, "%llu %llu", n,
714 crypto->hdr.iterations);
715 if (rc)
716 break;
719 rc = gcry_cipher_setiv(h, crypto->hdr.iv, sizeof(crypto->hdr.iv));
720 if (rc)
721 goto fail;
723 rc = iterate_crypto_once(h, outbuf, crypto->hdr.datalen, blocksize,
724 STATUS_DECRYPT);
727 if (!rc && ctx && crypto->hdr.iterations)
728 rc = send_status(ctx, STATUS_DECRYPT, "%llu %llu", n,
729 crypto->hdr.iterations);
731 fail:
732 if (rc)
733 gcry_free(outbuf);
734 else {
735 crypto->plaintext = outbuf;
736 crypto->plaintext_len = crypto->hdr.datalen;
739 gcry_free(key);
740 gcry_cipher_close(h);
741 return rc;
744 gpg_error_t decrypt_xml(struct crypto_s *crypto, const gpointer data,
745 gsize len)
747 gcry_cipher_hd_t h = NULL;
748 gpg_error_t rc;
750 rc = gcry_cipher_open(&h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
751 if (rc)
752 return rc;
754 gcry_free(crypto->plaintext);
755 crypto->plaintext = gcry_malloc(len);
756 if (!crypto->plaintext) {
757 rc = GPG_ERR_ENOMEM;
758 goto done;
761 rc = gcry_cipher_setiv(h, cache_iv, cache_blocksize);
762 if (rc)
763 goto done;
765 rc = gcry_cipher_setkey(h, cache_key, cache_keysize);
766 if (rc)
767 goto done;
769 rc = gcry_cipher_decrypt(h, crypto->plaintext, len, data, len);
770 if (rc) {
771 gcry_free(crypto->plaintext);
772 crypto->plaintext = NULL;
775 crypto->plaintext_len = len;
777 done:
778 if (h)
779 gcry_cipher_close(h);
781 return rc;
784 gpg_error_t encrypt_xml(assuan_context_t ctx, gpointer key, gsize keylen,
785 gint algo, const gpointer xml, gsize len, gpointer *result, gsize
786 *result_len, guchar **iv, gsize *iv_len, guint64 iter)
788 gpg_error_t rc;
789 gcry_cipher_hd_t h;
790 gsize blocksize, keysize;
791 gpointer inbuf = NULL;
792 gsize olen = len;
793 guint64 n, progress;
794 guchar *tmpkey = NULL;
795 gchar *p;
797 rc = gcry_cipher_open(&h, algo, GCRY_CIPHER_MODE_CBC, 0);
798 if (rc)
799 return rc;
801 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
802 if (rc)
803 goto fail;
805 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_BLKLEN, NULL, &blocksize);
806 if (rc)
807 goto fail;
809 if (*(iv_len) == 0) {
810 *(iv) = g_malloc(blocksize);
811 if (!*(iv))
812 goto fail;
814 gcry_create_nonce(*(iv), blocksize);
817 *iv_len = blocksize;
818 tmpkey = gcry_malloc(keylen);
819 if (!tmpkey) {
820 rc = GPG_ERR_ENOMEM;
821 goto fail;
824 memcpy(tmpkey, key, keylen);
825 tmpkey[0] ^= 1;
826 rc = gcry_cipher_setkey(h, tmpkey, keylen);
827 if (rc)
828 goto fail;
830 if (len%blocksize)
831 len += blocksize-(len%blocksize);
833 inbuf = gcry_malloc(len);
834 if (!inbuf) {
835 rc = GPG_ERR_ENOMEM;
836 goto fail;
839 memset(inbuf, 0, len);
840 memcpy(inbuf, xml, olen);
841 p = get_key_file_string(NULL, "cipher_progress");
842 if (p) {
843 errno = 0;
844 progress = strtoull(p, NULL, 10);
845 if (errno)
846 progress = strtoull(DEFAULT_ITERATION_PROGRESS, NULL, 10);
848 g_free(p);
850 else
851 progress = strtoull(DEFAULT_ITERATION_PROGRESS, NULL, 10);
853 if (!rc && ctx && iter)
854 rc = send_status(ctx, STATUS_ENCRYPT, "%llu %llu", 0, iter);
856 for (n = 0; !rc && n < iter; n++) {
857 if (ctx && !(n%progress)) {
858 rc = send_status(ctx, STATUS_ENCRYPT, "%llu %llu", n, iter);
859 if (rc)
860 break;
863 rc = gcry_cipher_setiv(h, *(iv), blocksize);
864 if (rc)
865 goto fail;
867 rc = iterate_crypto_once(h, inbuf, len, blocksize, STATUS_ENCRYPT);
870 if (!rc && ctx && iter)
871 rc = send_status(ctx, STATUS_ENCRYPT, "%llu %llu", n, iter);
873 if (rc)
874 goto fail;
876 /* Do at least one iteration. */
877 rc = gcry_cipher_setiv(h, *(iv), blocksize);
878 if (rc)
879 goto fail;
881 rc = gcry_cipher_setkey(h, key, keylen);
882 if (rc)
883 goto fail;
885 rc = iterate_crypto_once(h, inbuf, len, blocksize, STATUS_ENCRYPT);
886 if (rc)
887 goto fail;
889 *result = inbuf;
890 *result_len = len;
891 gcry_free(tmpkey);
892 gcry_cipher_close(h);
893 return 0;
895 fail:
896 gcry_free(tmpkey);
897 g_free(*iv);
898 gcry_free(inbuf);
899 gcry_cipher_close(h);
900 return rc;
903 gpg_error_t agent_loopback_cb(gpointer user, const gchar *keyword)
905 struct crypto_s *crypto = user;
906 gpg_error_t rc;
907 guchar *result;
908 gsize len;
909 gboolean keyparam = FALSE;
911 if (!g_strcmp0(keyword, "KEYPARAM")) {
912 keyparam = TRUE;
913 rc = assuan_inquire(crypto->client_ctx, keyword, &result, &len, 0);
915 else { // PASSPHRASE or NEW_PASSPHRASE
916 assuan_begin_confidential(crypto->client_ctx);
917 rc = assuan_inquire(crypto->client_ctx, keyword, &result, &len, 0);
918 assuan_end_confidential(crypto->client_ctx);
921 if (!rc) {
922 if (keyparam && !len) {
923 gchar *tmp = default_key_params(crypto);
925 if (!tmp)
926 return gpg_error(GPG_ERR_ENOMEM);
928 len = strlen(tmp);
929 result = xmalloc(len);
930 memcpy(result, tmp, len);
931 g_free(tmp);
934 pthread_cleanup_push(xfree, result);
936 if (keyparam)
937 rc = assuan_send_data(crypto->agent->ctx, result, len);
938 else {
939 assuan_begin_confidential(crypto->agent->ctx);
940 rc = assuan_send_data(crypto->agent->ctx, result, len);
941 assuan_end_confidential(crypto->agent->ctx);
944 pthread_cleanup_pop(1);
946 else if (gpg_err_code(rc) == GPG_ERR_ASS_CANCELED) {
947 gpg_error_t arc = assuan_write_line(crypto->agent->ctx, "CAN");
949 if (!arc) {
950 char *line;
951 size_t len;
953 arc = assuan_read_line(crypto->agent->ctx, &line, &len);
954 if (arc)
955 rc = arc;
957 else
958 rc = arc;
961 return rc;
964 static gpg_error_t sign(gcry_sexp_t *rsexp, const gchar *sign_hexgrip,
965 struct crypto_s *crypto, const gpointer data, gsize len)
967 gpg_error_t rc;
968 gchar *result;
969 gchar *tmp = sign_hexgrip ? g_strdup(sign_hexgrip)
970 : bin2hex(crypto->grip, sizeof(crypto->grip));
972 pthread_cleanup_push(g_free, tmp);
973 log_write1(_("Sign keygrip is %s"), tmp);
974 rc = send_to_agent(crypto->agent, NULL, NULL, "SIGKEY %s", tmp);
975 pthread_cleanup_pop(1);
976 if (!rc) {
977 guchar *hash;
978 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
980 hash = gcry_malloc(hashlen);
981 if (!hash)
982 return GPG_ERR_ENOMEM;
984 gcry_md_hash_buffer(GCRY_MD_SHA256, hash, data, len);
985 tmp = bin2hex(hash, hashlen);
986 gcry_free(hash);
987 pthread_cleanup_push(g_free, tmp);
988 rc = send_to_agent(crypto->agent, NULL, NULL,
989 "SETHASH --hash=sha256 %s", tmp);
990 pthread_cleanup_pop(1);
993 if (!rc) {
994 struct inquire_data_s idata = {0};
996 idata.crypto = crypto;
997 crypto->agent->inquire_data = &idata;
998 crypto->agent->inquire_cb = inquire_cb;
999 rc = send_to_agent(crypto->agent, &result, &len, "PKSIGN");
1000 if (!rc) {
1001 rc = gcry_sexp_sscan(rsexp, NULL, result, len);
1002 xfree(result);
1006 return rc;
1009 static gpg_error_t write_file(struct crypto_s *crypto, const gchar *filename,
1010 gpointer data, gsize data_len, gpointer sexp, gsize sexp_len,
1011 gcry_sexp_t pubkey, gcry_sexp_t sigpkey)
1013 gchar tmp[FILENAME_MAX] = { 0 };
1014 mode_t mode = 0;
1015 struct stat st;
1016 gint fd;
1017 gpg_error_t rc = 0;
1018 gsize len;
1019 #ifdef WITH_LIBACL
1020 acl_t acl = NULL;
1021 #endif
1023 if (filename) {
1024 if (g_lstat(filename, &st) == 0) {
1025 mode = st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
1027 if (!(mode & S_IWUSR))
1028 return GPG_ERR_EACCES;
1030 else if (errno != ENOENT)
1031 return gpg_error_from_syserror();
1033 g_snprintf(tmp, sizeof(tmp), "%s.XXXXXX", filename);
1034 #if GLIB_CHECK_VERSION(2, 22, 0)
1035 fd = g_mkstemp_full(tmp, O_WRONLY, 0600);
1036 #else
1037 fd = mkstemp(tmp);
1038 #endif
1039 if (fd == -1) {
1040 rc = gpg_error_from_syserror();
1041 log_write("%s: %s", tmp, pwmd_strerror(rc));
1042 return rc;
1045 else {
1046 // xml_import() or convert_file() from command line.
1047 fd = STDOUT_FILENO;
1050 pthread_cleanup_push(cleanup_unlink_cb, tmp);
1051 crypto->save.hdr.version = VERSION_HEX;
1052 len = write(fd, &crypto->save.hdr, sizeof(file_header_t));
1053 if (len == sizeof(file_header_t)) {
1054 guchar grip[20];
1056 gcry_pk_get_keygrip(pubkey, grip);
1057 len = write(fd, grip, sizeof(grip));
1058 if (len == sizeof(grip)) {
1059 gcry_pk_get_keygrip(sigpkey, grip);
1060 len = write(fd, grip, sizeof(grip));
1061 if (len == sizeof(grip)) {
1062 len = write(fd, data, data_len);
1063 if (len == data_len) {
1064 len = write(fd, sexp, sexp_len);
1065 if (len != sexp_len)
1066 rc = gpg_error_from_syserror();
1068 else
1069 rc = gpg_error_from_syserror();
1072 else
1073 rc = gpg_error_from_syserror();
1075 else
1076 rc = gpg_error_from_syserror();
1078 #ifdef WITH_LIBACL
1079 pthread_cleanup_push(acl_free, acl);
1080 #endif
1081 if (!rc) {
1082 if (fsync(fd) != -1) {
1083 if (filename && close(fd) != -1) {
1084 if (mode && get_key_file_boolean(filename, "backup")) {
1085 gchar tmp2[FILENAME_MAX];
1087 g_snprintf(tmp2, sizeof(tmp2), "%s.backup", filename);
1088 #ifdef WITH_LIBACL
1089 acl = acl_get_file(filename, ACL_TYPE_ACCESS);
1090 if (!acl)
1091 log_write("ACL: %s: %s", filename,
1092 pwmd_strerror(gpg_error_from_syserror()));
1093 #endif
1095 if (g_rename(filename, tmp2) == -1)
1096 rc = gpg_error_from_syserror();
1098 else if (filename) {
1099 #ifdef WITH_LIBACL
1100 acl = acl_get_file(".", ACL_TYPE_DEFAULT);
1101 if (!acl)
1102 log_write("ACL: %s: %s", filename,
1103 pwmd_strerror(gpg_error_from_syserror()));
1104 #endif
1107 else if (filename)
1108 rc = gpg_error_from_syserror();
1110 else
1111 rc = gpg_error_from_syserror();
1114 if (!rc) {
1115 if (filename && g_rename(tmp, filename) != -1) {
1116 tmp[0] = 0;
1117 if (filename && mode)
1118 g_chmod(filename, mode);
1120 #ifdef WITH_LIBACL
1121 if (filename && acl && acl_set_file(filename, ACL_TYPE_ACCESS, acl))
1122 log_write("ACL: %s: %s", filename,
1123 pwmd_strerror(gpg_error_from_syserror()));
1124 #endif
1126 /* Be sure the file entry has been written to disk. On FreeBSD I
1127 * noticed delays causing a following command to return
1128 * GPG_ERR_CHECKSUM. Recommended from fsync(2) (Linux).
1130 DIR *dir;
1131 gchar *path;
1132 gchar *s = get_key_file_string("global", "data_directory");
1134 path = expand_homedir(s);
1135 g_free(s);
1136 dir = opendir(path);
1137 g_free(path);
1138 if (dir) {
1139 fd = dirfd(dir);
1140 if (fd != -1)
1141 fsync(fd);
1142 else
1143 rc = gpg_error_from_syserror();
1145 closedir(dir);
1147 else
1148 rc = gpg_error_from_syserror();
1150 else
1151 rc = gpg_error_from_syserror();
1154 #ifdef WITH_LIBACL
1155 pthread_cleanup_pop(1);
1156 #endif
1157 pthread_cleanup_pop(rc ? 1 : 0); // unlink
1158 return rc;
1161 gpg_error_t encrypt_data_file(assuan_context_t ctx, struct crypto_s *crypto,
1162 gcry_sexp_t pubkey, gcry_sexp_t sigpkey, const gchar *filename, const
1163 gpointer xml, gsize len)
1165 gpg_error_t rc;
1166 gpointer data = NULL;
1167 gsize data_len = 0;
1168 gpointer enc_xml = NULL;
1169 gsize enc_xml_len = 0;
1170 guchar *iv = NULL;
1171 gsize iv_len = 0;
1172 gint algo = cipher_to_gcrypt(crypto->save.hdr.flags);
1173 gpointer key = NULL;
1174 gsize keysize;
1175 guchar sig_grip[20];
1176 guchar grip[20];
1178 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
1179 if (rc)
1180 return rc;
1182 pthread_cleanup_push(gcry_free, key);
1183 key = gcry_random_bytes_secure(keysize, GCRY_STRONG_RANDOM);
1184 pthread_testcancel(); // may have been a long operation
1185 pthread_cleanup_pop(0);
1186 if (!key)
1187 return GPG_ERR_ENOMEM;
1189 gcry_pk_get_keygrip(pubkey, grip);
1190 gcry_pk_get_keygrip(sigpkey, sig_grip);
1191 pthread_cleanup_push(g_free, iv);
1192 pthread_cleanup_push(gcry_free, key);
1193 rc = encrypt_xml(ctx, key, keysize, algo, xml, len, &enc_xml, &enc_xml_len,
1194 &iv, &iv_len, crypto->save.hdr.iterations);
1195 if (!rc) {
1196 gcry_sexp_t sig_sexp = NULL;
1197 gchar *hexgrip = bin2hex(sig_grip, 20);
1199 pthread_cleanup_push(gcry_free, enc_xml);
1200 rc = sign(&sig_sexp, hexgrip, crypto, enc_xml, enc_xml_len);
1201 g_free(hexgrip);
1203 if (!rc) {
1204 rc = verify(sigpkey, sig_sexp, enc_xml, enc_xml_len);
1206 if (!rc) {
1207 gcry_sexp_t tmp_sexp;
1209 rc = gcry_sexp_build(&tmp_sexp, NULL,
1210 "(data (flags pkcs1) (value %b))", keysize, key);
1211 if (!rc) {
1212 gcry_sexp_t key_sexp;
1214 pthread_cleanup_push((void (*)(void*))gcry_sexp_release,
1215 (void *)sig_sexp);
1216 rc = gcry_pk_encrypt(&key_sexp, tmp_sexp, pubkey);
1217 pthread_cleanup_pop(0);
1218 gcry_sexp_release(tmp_sexp);
1220 if (!rc) {
1221 memcpy(crypto->save.hdr.iv, iv, iv_len);
1222 crypto->save.hdr.datalen = enc_xml_len;
1223 rc = gcry_sexp_build(&tmp_sexp, NULL, "%S%S", key_sexp,
1224 sig_sexp);
1225 gcry_sexp_release(key_sexp);
1227 if (!rc) {
1228 data_len = gcry_sexp_sprint(tmp_sexp,
1229 GCRYSEXP_FMT_CANON, NULL, 0);
1230 data = g_malloc(data_len);
1231 if (data)
1232 gcry_sexp_sprint(tmp_sexp, GCRYSEXP_FMT_CANON,
1233 data, data_len);
1234 else
1235 rc = GPG_ERR_ENOMEM;
1237 gcry_sexp_release(tmp_sexp);
1244 pthread_cleanup_pop(0); // enc_xml
1246 if (sig_sexp)
1247 gcry_sexp_release(sig_sexp);
1250 pthread_cleanup_pop(1); // key
1251 pthread_cleanup_pop(1); // iv
1253 if (!rc) {
1254 pthread_cleanup_push(gcry_free, enc_xml);
1255 rc = write_file(crypto, filename, enc_xml, enc_xml_len, data, data_len,
1256 pubkey, sigpkey);
1257 pthread_cleanup_pop(1); // enc_xml
1258 if (!rc)
1259 memcpy(&crypto->hdr, &crypto->save.hdr, sizeof(file_header_t));
1262 g_free(data);
1263 return rc;
1266 void cleanup_save(struct save_s *save)
1268 if (!save)
1269 return;
1271 if (save->pkey)
1272 gcry_sexp_release(save->pkey);
1274 if (save->sigpkey)
1275 gcry_sexp_release(save->sigpkey);
1277 memset(save, 0, sizeof(struct save_s));
1280 /* Keep the agent ctx to retain pinentry options which will be freed in
1281 * cleanup_cb(). Also keep .pubkey since it may be needed for a SAVE. */
1282 void cleanup_crypto_stage1(struct crypto_s *cr)
1284 if (!cr)
1285 return;
1287 cleanup_save(&cr->save);
1289 if (cr->ciphertext_sexp)
1290 gcry_sexp_release(cr->ciphertext_sexp);
1292 if (cr->plaintext)
1293 gcry_free(cr->plaintext);
1295 g_free(cr->ciphertext);
1296 g_free(cr->filename);
1297 cr->filename = NULL;
1298 cr->ciphertext_sexp = NULL;
1299 cr->ciphertext = NULL;
1300 cr->ciphertext_len = 0;
1301 cr->plaintext = NULL;
1302 cr->plaintext_len = 0;
1305 void cleanup_crypto_stage2(struct crypto_s *cr)
1307 if (!cr)
1308 return;
1310 cleanup_crypto_stage1(cr);
1311 set_header_defaults(&cr->hdr);
1314 void cleanup_crypto(struct crypto_s **c)
1316 struct crypto_s *cr = *c;
1318 if (!cr)
1319 return;
1321 cleanup_crypto_stage2(cr);
1323 if (cr->pkey_sexp)
1324 gcry_sexp_release(cr->pkey_sexp);
1326 if (cr->sigpkey_sexp)
1327 gcry_sexp_release(cr->sigpkey_sexp);
1329 if (cr->agent)
1330 cleanup_agent(cr->agent);
1332 g_free(cr);
1333 *c = NULL;
1336 gpg_error_t init_client_crypto(struct crypto_s **crypto)
1338 struct crypto_s *new = g_malloc0(sizeof(struct crypto_s));
1339 gpg_error_t rc;
1341 if (!new) {
1342 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
1343 return GPG_ERR_ENOMEM;
1346 rc = agent_init(&new->agent);
1347 if (!rc) {
1348 rc = send_agent_common_options(new->agent);
1349 if (!rc)
1350 rc = set_pinentry_options(new->agent);
1353 if (rc) {
1354 g_free(new);
1355 return rc;
1358 set_header_defaults(&new->hdr);
1359 *crypto = new;
1360 return 0;
1363 gpg_error_t generate_key(struct crypto_s *crypto, gchar *sexpstr,
1364 gboolean empty, gboolean preset)
1366 gpg_error_t rc;
1367 gchar *pkey;
1368 gsize plen;
1370 if (crypto->save.s2k_count) {
1371 rc = send_to_agent(crypto->agent, NULL, NULL,
1372 "OPTION s2k-count=%lu", crypto->save.s2k_count);
1373 if (rc)
1374 return rc;
1377 if (!crypto->agent->inquire_cb)
1378 crypto->agent->inquire_cb = inquire_cb;
1380 rc = send_to_agent(crypto->agent, &pkey, &plen, "GENKEY %s%s",
1381 preset ? "--preset " : "",
1382 empty ? "--no-protection" : "");
1383 if (rc)
1384 return rc;
1386 if (crypto->save.pkey)
1387 gcry_sexp_release(crypto->save.pkey);
1389 crypto->save.pkey = NULL;
1390 rc = gcry_sexp_new(&crypto->save.pkey, pkey, plen, 1);
1391 if (!rc) {
1392 guchar grip[20];
1394 gcry_pk_get_keygrip(crypto->save.pkey, grip);
1395 gchar *hexgrip = bin2hex(grip, sizeof(grip));
1396 log_write1(_("Keygrip is %s"), hexgrip);
1397 g_free(hexgrip);
1399 if (!crypto->save.sigpkey) {
1400 gcry_sexp_build((gcry_sexp_t *)&crypto->save.sigpkey, NULL, "%S",
1401 crypto->save.pkey);
1405 xfree(pkey);
1406 return rc;
1409 gpg_error_t set_agent_option(struct agent_s *agent, const gchar *name,
1410 const gchar *value)
1412 return send_to_agent(agent, NULL, NULL, "OPTION %s=%s", name, value);
1415 gpg_error_t set_agent_passphrase(struct crypto_s *crypto, const gchar *key,
1416 gsize len)
1418 gchar *hexgrip;
1419 struct inquire_data_s idata;
1420 gpg_error_t rc;
1421 gint i;
1423 /* This is for use with key files or passphrases obtained from an inquire.
1424 * gpg-agent uses strings as passphrases and will truncate the passphrase
1425 * at the first encountered null byte. It's only a warning because the
1426 * passphrase may belong to a key shared outside of pwmd. */
1427 for (i = 0; i < len; i++) {
1428 if (key[i] == 0) {
1429 log_write(_("WARNING: keylen=%i, truncated to %i."), len, i);
1430 break;
1434 hexgrip = bin2hex(crypto->grip, 20);
1435 crypto->agent->inquire_cb = inquire_cb;
1436 crypto->agent->inquire_data = &idata;
1437 idata.crypto = crypto;
1438 idata.line = (gchar *)key,
1439 idata.len = len;
1440 idata.preset = TRUE;
1441 assuan_begin_confidential(crypto->agent->ctx);
1442 rc = send_to_agent(crypto->agent, NULL, NULL,
1443 "PRESET_PASSPHRASE --inquire %s -1", hexgrip);
1444 assuan_end_confidential(crypto->agent->ctx);
1445 idata.preset = FALSE;
1446 g_free(hexgrip);
1447 return rc;
1450 gpg_error_t set_pinentry_mode(struct agent_s *agent, const gchar *mode)
1452 return set_agent_option(agent, "pinentry-mode", mode);
1455 gpg_error_t get_pubkey_bin(struct crypto_s *crypto, const guchar *grip,
1456 gcry_sexp_t *result)
1458 gchar *hexgrip = bin2hex(grip, 20);
1459 gpg_error_t rc;
1461 if (!hexgrip)
1462 return GPG_ERR_ENOMEM;
1464 rc = get_pubkey(crypto, hexgrip, result);
1465 g_free(hexgrip);
1466 return rc;
1469 gpg_error_t get_pubkey(struct crypto_s *crypto, const gchar *grip,
1470 gcry_sexp_t *result)
1472 gchar *pkey = NULL;
1473 gsize plen;
1474 gpg_error_t rc;
1476 rc = send_to_agent(crypto->agent, &pkey, &plen, "READKEY %s", grip);
1477 if (!rc)
1478 rc = gcry_sexp_new(result, pkey, plen, 1);
1480 xfree(pkey);
1481 return rc;
1484 gpg_error_t set_pinentry_options(struct agent_s *agent)
1486 gpg_error_t rc = 0;
1488 if (getenv("DISPLAY")) {
1489 rc = set_agent_option(agent, "display", getenv("DISPLAY"));
1490 if (!rc) {
1491 g_free(agent->display);
1492 agent->display = g_strdup(getenv("DISPLAY"));
1495 else if (ttyname(STDOUT_FILENO)) {
1496 rc = set_agent_option(agent, "ttyname", ttyname(STDOUT_FILENO));
1497 if (!rc) {
1498 rc = set_agent_option(agent, "ttytype", getenv("TERM"));
1499 if (!rc) {
1500 g_free(agent->ttyname);
1501 g_free(agent->ttytype);
1502 agent->ttyname = g_strdup(ttyname(STDOUT_FILENO));
1503 agent->ttytype = g_strdup(getenv("TERM"));
1508 return rc;
1511 static gpg_error_t inquire_keyfile(gpointer user, const gchar *keyword)
1513 struct crypto_s *crypto = user;
1514 gchar *filename = crypto->agent->inquire_data2;
1515 gchar *params = crypto->agent->inquire_data3;
1516 gint fd;
1517 struct stat st;
1518 guchar *buf;
1519 gsize len;
1520 gpg_error_t rc;
1522 if (!g_strcmp0(keyword, "KEYPARAM"))
1523 return assuan_send_data(crypto->agent->ctx, params, strlen(params));
1525 // This function is only used when generating a new keypair.
1526 if (g_strcmp0(keyword, "NEW_PASSPHRASE"))
1527 return gpg_error(GPG_ERR_ASS_UNKNOWN_INQUIRE);
1529 if (stat(filename, &st) == -1)
1530 return gpg_error_from_syserror();
1532 if (crypto->agent->inquire_maxlen
1533 && st.st_size > crypto->agent->inquire_maxlen) {
1534 log_write(_("The passphrase is too large: have=%u, max=%u."),
1535 (unsigned)st.st_size, crypto->agent->inquire_maxlen);
1536 return GPG_ERR_TOO_LARGE;
1539 buf = gcry_malloc_secure(st.st_size);
1540 if (!buf)
1541 return GPG_ERR_ENOMEM;
1543 fd = open(filename, O_RDONLY);
1544 if (fd == -1)
1545 rc = gpg_error_from_syserror();
1546 else {
1547 len = read(fd, buf, st.st_size);
1548 if (len == st.st_size) {
1549 assuan_begin_confidential(crypto->agent->ctx);
1550 rc = assuan_send_data(crypto->agent->ctx, buf, len);
1551 assuan_end_confidential(crypto->agent->ctx);
1553 else if (len == -1)
1554 rc = gpg_error_from_syserror();
1555 else
1556 rc = GPG_ERR_BUFFER_TOO_SHORT;
1559 close(fd);
1560 gcry_free(buf);
1561 return rc;
1564 gpg_error_t export_common(struct crypto_s *crypto, const gchar *hexgrip,
1565 const gchar *sign_hexgrip, gboolean no_passphrase,
1566 const gpointer data, gsize datalen, const gchar *outfile,
1567 const gchar *keyparams, const gchar *keyfile)
1569 gpg_error_t rc = 0;
1571 if (!sign_hexgrip && hexgrip)
1572 sign_hexgrip = hexgrip;
1574 if (sign_hexgrip) {
1575 if (crypto->sigpkey_sexp)
1576 gcry_sexp_release(crypto->sigpkey_sexp);
1578 crypto->sigpkey_sexp = NULL;
1579 rc = get_pubkey(crypto, sign_hexgrip, &crypto->save.sigpkey);
1580 if (rc)
1581 return rc;
1583 gcry_pk_get_keygrip(crypto->save.sigpkey, crypto->sign_grip);
1586 if (hexgrip) {
1587 rc = get_pubkey(crypto, hexgrip, &crypto->save.pkey);
1588 if (!rc)
1589 gcry_pk_get_keygrip(crypto->save.pkey, crypto->grip);
1591 else {
1592 struct inquire_data_s idata = {0};
1593 gchar *params = keyparams ? g_strdup(keyparams)
1594 : default_key_params(crypto);
1596 pthread_cleanup_push(g_free, params);
1597 log_write(_("Generating a new keypair ..."));
1598 if (keyfile) {
1599 log_write(_("Using passphrase obtained from file '%s'"), keyfile);
1600 rc = set_pinentry_mode(crypto->agent, "loopback");
1601 crypto->agent->inquire_cb = inquire_keyfile;
1602 crypto->agent->inquire_data = crypto;
1603 crypto->agent->inquire_data2 = (gchar *)keyfile;
1604 crypto->agent->inquire_data3 = params;
1606 else {
1607 idata.line = params;
1608 idata.len = strlen(params);
1609 idata.crypto = crypto;
1610 crypto->agent->inquire_cb = inquire_cb;
1611 crypto->agent->inquire_data = &idata;
1614 if (!rc) {
1615 rc = generate_key(crypto, params, no_passphrase, TRUE);
1616 gcry_pk_get_keygrip(crypto->save.pkey, crypto->grip);
1619 (void)set_pinentry_mode(crypto->agent, "ask");
1620 pthread_cleanup_pop(1);
1623 if (!rc) {
1624 rc = encrypt_data_file(NULL, crypto, crypto->save.pkey,
1625 crypto->save.sigpkey, outfile, data, datalen);
1626 if (!rc) {
1627 gchar *tmp = bin2hex(crypto->grip, sizeof(crypto->grip));
1629 log_write(_("Success! Keygrip is %s."), tmp);
1630 rc = send_to_agent(crypto->agent, NULL, NULL,
1631 "CLEAR_PASSPHRASE --mode=normal %s", tmp);
1632 g_free(tmp);
1634 if (sign_hexgrip) {
1635 tmp = bin2hex(crypto->sign_grip, sizeof(crypto->sign_grip));
1636 log_write(_("Signed with keygrip %s."), tmp);
1637 g_free(tmp);
1642 return rc;
1645 gchar *default_key_params(struct crypto_s *crypto)
1647 gint len = get_key_file_integer(NULL, "nbits");
1648 gchar buf[32];
1649 gchar *algo = get_key_file_string(NULL, "algo");
1650 gchar *result;
1652 g_snprintf(buf, sizeof(buf), "%i", len);
1653 result = g_strdup_printf("(genkey (%s (nbits %lu:%i)))", algo, strlen(buf),
1654 len);
1655 g_free(algo);
1656 return result;
1659 gpg_error_t agent_passwd(struct crypto_s *crypto)
1661 struct inquire_data_s idata = {0};
1662 gpg_error_t rc;
1663 gchar *tmp = bin2hex(crypto->grip, 20);
1665 idata.crypto = crypto;
1666 crypto->agent->inquire_cb = inquire_cb;
1667 crypto->agent->inquire_data = &idata;
1668 rc = send_to_agent(crypto->agent, NULL, NULL, "PASSWD --preset %s", tmp);
1669 g_free(tmp);
1670 return rc;
1673 gpg_error_t kill_scd(struct agent_s *agent)
1675 gpg_error_t rc = 0;
1677 if (get_key_file_boolean(NULL, "kill_scd")) {
1678 rc = send_to_agent(agent, NULL, NULL, "SCD KILLSCD");
1679 if (rc && gpg_err_code(rc) != GPG_ERR_NO_SCDAEMON)
1680 log_write("%s: %s", __FUNCTION__, pwmd_strerror(rc));
1683 return rc;