Fix ACL's.
[pwmd.git] / src / agent.c
blobc0d7d85925b13c4bea9ec93fd0315ddb285e20ff
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd 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 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <pwd.h>
27 #include <sys/types.h>
28 #include <signal.h>
29 #include <sys/wait.h>
30 #include <fcntl.h>
31 #include <dirent.h>
33 #include "pwmd-error.h"
34 #include "mem.h"
35 #include "common.h"
36 #include "commands.h"
37 #include "agent.h"
38 #include "util-misc.h"
39 #include "util-string.h"
40 #include "mutex.h"
41 #include "rcfile.h"
42 #include "cache.h"
43 #include "cipher.h"
45 #ifdef WITH_LIBACL
46 #include <acl/libacl.h>
47 #endif
49 #ifdef HAVE_LIMITS_H
50 #include <limits.h>
51 #endif
53 static uint8_t pwmd_magic[5] = { '\177', 'P', 'W', 'M', 'D' };
55 static gpg_error_t mem_realloc_cb(void *data, const void *buffer, size_t len)
57 membuf_t *mem = (membuf_t *)data;
58 void *p;
60 if (!buffer)
61 return 0;
63 if ((p = xrealloc(mem->buf, mem->len + len)) == NULL)
64 return 1;
66 mem->buf = p;
67 memcpy((char *)mem->buf + mem->len, buffer, len);
68 mem->len += len;
69 return 0;
72 static gpg_error_t status_cb(void * data, const char *line)
74 struct agent_s *agent = data;
76 agent->inquire_maxlen = 0;
78 if (!strncmp(line, "INQUIRE_MAXLEN ", 15)) {
79 agent->inquire_maxlen = atoi(line+15);
80 if (!agent->client_ctx)
81 return 0;
84 return send_status(agent->client_ctx, STATUS_AGENT, "%s", line);
87 static gpg_error_t assuan_command(struct agent_s *a, char **result,
88 size_t *len, const char *cmd)
90 gpg_error_t rc;
92 a->data.len = 0;
93 a->data.buf = NULL;
94 if (result)
95 *result = NULL;
96 if (len)
97 *len = 0;
98 rc = assuan_transact(a->ctx, cmd, mem_realloc_cb, &a->data,
99 a->inquire_cb, a->inquire_data, status_cb, a);
101 if (rc)
102 xfree(a->data.buf);
103 else {
104 if (a->data.buf) {
105 mem_realloc_cb(&a->data, "", 1);
106 if (result)
107 *result = (char *)a->data.buf;
108 else
109 xfree(a->data.buf);
111 if (len)
112 *len = a->data.len;
116 return rc;
119 /* This commands are sent from launch_agent() after reconnecting to the agent
120 * and also from the initial client connection. */
121 static gpg_error_t send_agent_common_options(struct agent_s *agent)
123 gpg_error_t rc;
125 rc = send_to_agent(agent, NULL, NULL, "OPTION cache-ttl-opt-preset=-1");
126 return rc;
129 static gpg_error_t launch_agent(struct agent_s *agent)
131 gpg_error_t rc;
132 assuan_context_t ctx;
133 const char *t = NULL;
134 static struct assuan_malloc_hooks mhooks = { xmalloc, xrealloc, xfree };
135 char *s, buf[LINE_MAX];
136 FILE *fp;
138 s = config_get_string("global", "agent_env_file");
139 if (s) {
140 char *ss = expand_homedir(s);
142 xfree(s);
143 fp = fopen(ss, "r");
144 xfree(ss);
146 if (fp) {
147 while ((s = fgets(buf, sizeof(buf), fp))) {
148 s = str_chomp(s);
149 if (!strncmp(s, "GPG_AGENT_INFO=", strlen("GPG_AGENT_INFO="))) {
150 setenv("GPG_AGENT_INFO", s+strlen("GPG_AGENT_INFO="), 1);
151 break;
155 fclose(fp);
157 else
158 log_write("%s: %s", s, pwmd_strerror(gpg_error_from_syserror()));
161 t = getenv("GPG_AGENT_INFO");
162 if (!t)
163 return gpg_err_code(GPG_ERR_NO_AGENT);
165 rc = assuan_new_ext(&ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks,
166 debug_level ? assuan_log_cb : NULL, "AGENT ");
167 if (rc)
168 return rc;
170 char **fields = str_split(t, ":", 0);
171 rc = assuan_socket_connect(ctx, fields[0], ASSUAN_INVALID_PID, 0);
172 strv_free(fields);
173 if (rc) {
174 assuan_release(ctx);
175 return rc;
178 if (agent->ctx) {
179 /* Restore the previous agent settings for this new context. */
180 assuan_release(agent->ctx);
181 agent->ctx = ctx;
182 rc = send_agent_common_options(agent);
183 if (!rc && agent->display)
184 rc = set_agent_option(agent, "display", agent->display);
186 if (!rc && agent->ttyname)
187 rc = set_agent_option(agent, "ttyname", agent->ttyname);
189 if (!rc && agent->ttytype)
190 rc = set_agent_option(agent, "ttytype", agent->ttytype);
192 if (!rc && agent->lc_messages)
193 rc = set_agent_option(agent, "lc-messages", agent->lc_messages);
195 if (!rc && agent->lc_ctype)
196 rc = set_agent_option(agent, "lc-ctype", agent->lc_ctype);
199 agent->ctx = ctx;
200 return 0;
203 gpg_error_t send_to_agent(struct agent_s *agent, char **result, size_t *len,
204 const char *fmt, ...)
206 gpg_error_t rc = 0;
207 va_list ap;
208 char *cmd;
210 if (!agent->ctx) {
211 rc = launch_agent(agent);
212 if (rc)
213 return rc;
216 va_start(ap, fmt);
217 if (str_vasprintf(&cmd, fmt, ap) > 0) {
218 rc = assuan_command(agent, result, len, cmd);
219 if (!agent->restart && gpg_err_source(rc) == GPG_ERR_SOURCE_DEFAULT
220 && (gpg_err_code(rc) == GPG_ERR_ASS_CONNECT_FAILED
221 || gpg_err_code(rc) == GPG_ERR_EPIPE)) {
222 unsetenv("GPG_AGENT_INFO");
223 agent->restart = 1;
224 rc = launch_agent(agent);
225 if (!rc)
226 rc = assuan_command(agent, result, len, cmd);
229 agent->restart = 0;
230 xfree(cmd);
232 else
233 rc = GPG_ERR_ENOMEM;
235 va_end(ap);
236 return rc;
239 static void agent_disconnect(struct agent_s *agent)
241 if (!agent)
242 return;
244 if (agent->ctx)
245 assuan_release(agent->ctx);
247 agent->ctx = NULL;
250 void cleanup_agent(struct agent_s *agent)
252 if (!agent)
253 return;
255 xfree(agent->desc);
256 xfree(agent->display);
257 xfree(agent->ttyname);
258 xfree(agent->ttytype);
259 xfree(agent->lc_messages);
260 xfree(agent->lc_ctype);
262 if (agent->ctx)
263 agent_disconnect(agent);
265 xfree(agent);
268 gpg_error_t agent_init(struct agent_s **agent)
270 struct agent_s *new = xcalloc(1, sizeof(struct agent_s));
272 if (!new)
273 return GPG_ERR_ENOMEM;
275 *agent = new;
276 return 0;
279 void set_header_defaults(file_header_t *hdr)
281 char *s = config_get_string(NULL, "cipher");
282 int flags = cipher_string_to_cipher(s);
284 xfree(s);
285 memset(hdr, 0, sizeof(file_header_t));
286 memcpy(hdr->magic, pwmd_magic, sizeof(hdr->magic));
287 if (flags == -1)
288 log_write(_("Invalid 'cipher' in configuration file. Using a default of aes256."));
289 hdr->flags = flags == -1 ? PWMD_CIPHER_AES256 : flags;
290 hdr->version = VERSION_HEX;
293 gpg_error_t read_data_header(const char *filename, file_header_t *rhdr,
294 struct stat *rst, int *rfd)
296 gpg_error_t rc = 0;
297 size_t len;
298 struct stat st;
299 file_header_t hdr;
300 int fd;
302 if (lstat(filename, &st) == -1)
303 return gpg_error_from_syserror();
305 if (!S_ISREG(st.st_mode))
306 return GPG_ERR_ENOANO;
308 fd = open(filename, O_RDONLY);
309 if (fd == -1)
310 return gpg_error_from_syserror();
312 len = read(fd, &hdr, sizeof(file_header_t));
313 if (len != sizeof(file_header_t))
314 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
316 if (!rc && memcmp(hdr.magic, pwmd_magic, sizeof(hdr.magic)))
317 rc = GPG_ERR_BAD_DATA;
318 else if (hdr.version < 0x030000)
319 rc = GPG_ERR_UNKNOWN_VERSION;
321 if (rc)
322 close(fd);
323 else {
324 if (rhdr)
325 *rhdr = hdr;
326 if (rst)
327 *rst = st;
328 if (rfd)
329 *rfd = fd;
330 else
331 close(fd);
334 return rc;
337 gpg_error_t read_data_file(const char *filename, struct crypto_s *crypto)
339 int fd;
340 gpg_error_t rc = 0;
341 size_t len, rlen;
342 char *buf = NULL;
343 struct stat st;
345 cleanup_crypto_stage1(crypto);
346 rc = read_data_header(filename, &crypto->hdr, &st, &fd);
347 if (rc)
348 return rc;
350 crypto->ciphertext_len = crypto->hdr.datalen;
351 crypto->ciphertext = xmalloc(crypto->hdr.datalen);
352 if (!crypto->ciphertext) {
353 rc = GPG_ERR_ENOMEM;
354 goto fail;
357 rlen = read(fd, crypto->grip, 20);
358 if (rlen != 20) {
359 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
360 goto fail;
363 rlen = read(fd, crypto->sign_grip, 20);
364 if (rlen != 20) {
365 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
366 goto fail;
369 len = read(fd, crypto->ciphertext, crypto->hdr.datalen);
370 if (len != crypto->hdr.datalen) {
371 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
372 goto fail;
375 len = st.st_size-sizeof(file_header_t)-crypto->hdr.datalen-40;
376 buf = xmalloc(len);
377 if (!buf) {
378 rc = GPG_ERR_ENOMEM;
379 goto fail;
382 rlen = read(fd, buf, len);
383 if (rlen != len) {
384 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
385 goto fail;
388 rc = gcry_sexp_new(&crypto->ciphertext_sexp, buf, rlen, 1);
389 if (rc)
390 goto fail;
392 if (crypto->pkey_sexp)
393 gcry_sexp_release(crypto->pkey_sexp);
395 if (crypto->sigpkey_sexp)
396 gcry_sexp_release(crypto->sigpkey_sexp);
398 crypto->pkey_sexp = crypto->sigpkey_sexp = NULL;
399 rc = get_pubkey_bin(crypto, crypto->grip, &crypto->pkey_sexp);
400 if (!rc)
401 rc = get_pubkey_bin(crypto, crypto->sign_grip, &crypto->sigpkey_sexp);
403 fail:
404 close(fd);
405 xfree(buf);
406 return rc;
409 static gpg_error_t inquire_cb(void * user, const char *keyword)
411 struct inquire_data_s *idata = user;
413 if (!idata->preset && (!strcmp(keyword, "PASSPHRASE")
414 || !strcmp(keyword, "NEW_PASSPHRASE"))) {
415 return agent_loopback_cb(idata->crypto, keyword);
417 // SAVE --inquire-keyparam
418 else if (idata->preset && !strcmp(keyword, "KEYPARAM")) {
419 idata->preset = 0;
420 return agent_loopback_cb(idata->crypto, keyword);
423 if (idata->crypto->agent->inquire_maxlen
424 && idata->len > idata->crypto->agent->inquire_maxlen) {
425 log_write(_("Inquired data too large: have=%u, max=%u"), idata->len,
426 idata->crypto->agent->inquire_maxlen);
427 return GPG_ERR_TOO_LARGE;
430 idata->crypto->agent->inquire_maxlen = 0;
431 return assuan_send_data(idata->crypto->agent->ctx, idata->line, idata->len);
434 static gpg_error_t extract_key(struct crypto_s *crypto, unsigned char **result,
435 size_t *result_len)
437 gpg_error_t rc;
438 gcry_sexp_t enc_sexp = NULL, tmp_sexp;
439 struct inquire_data_s idata = {0};
440 char *hexgrip = NULL;
441 char *key;
442 size_t keylen, keysize;
443 char *tmp;
444 int algo = cipher_to_gcrypt(crypto->hdr.flags);
445 int shadowed;
447 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
448 if (rc)
449 return rc;
451 tmp_sexp = gcry_sexp_find_token(crypto->ciphertext_sexp, "enc-val", 0);
452 if (!tmp_sexp)
453 return GPG_ERR_BAD_DATA;
455 hexgrip = bin2hex(crypto->grip, sizeof(crypto->grip));
456 if (!hexgrip) {
457 rc = GPG_ERR_ENOMEM;
458 goto fail;
461 rc = cache_is_shadowed(hexgrip);
462 if (rc && rc != GPG_ERR_NO_DATA)
463 goto fail;
465 shadowed = !rc ? 1 : 0;
466 if (!shadowed) {
467 gcry_sexp_t tmp2_sexp = gcry_sexp_cdr(tmp_sexp);
468 gcry_sexp_release(tmp_sexp);
469 tmp_sexp = gcry_sexp_nth(tmp2_sexp, 0);
470 gcry_sexp_release(tmp2_sexp);
471 rc = gcry_sexp_build(&enc_sexp, NULL, "(enc-val (flags pkcs1) %S)",
472 tmp_sexp);
474 else
475 rc = gcry_sexp_build(&enc_sexp, NULL, "%S", tmp_sexp);
477 gcry_sexp_release(tmp_sexp);
478 if (rc)
479 return rc;
481 crypto->agent->inquire_cb = inquire_cb;
482 idata.crypto = crypto;
483 idata.len = gcry_sexp_sprint(enc_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
484 idata.line = xmalloc(idata.len);
485 if (!idata.line) {
486 rc = GPG_ERR_ENOMEM;
487 goto fail;
490 idata.len = gcry_sexp_sprint(enc_sexp, GCRYSEXP_FMT_CANON, idata.line,
491 idata.len);
492 crypto->agent->inquire_data = &idata;
493 gcry_sexp_release(enc_sexp);
494 enc_sexp = NULL;
495 log_write1(_("Keygrip is %s, bits=%i"), hexgrip,
496 gcry_pk_get_nbits(crypto->pkey_sexp));
497 rc = send_to_agent(crypto->agent, NULL, NULL, "SETKEY %s", hexgrip);
498 if (rc)
499 goto fail;
501 if (!crypto->agent->desc) {
502 tmp = plus_escape(_(
503 "A %s is required to unlock the secret key for the "
504 "encrypted data file \"%s\". Please enter the %s "
505 "below."),
506 shadowed ? "PIN" : _("passphrase"), crypto->filename,
507 shadowed ? "PIN" : _("passphrase"));
509 else
510 tmp = plus_escape(crypto->agent->desc);
512 rc = send_to_agent(crypto->agent, NULL, NULL, "SETKEYDESC %s", tmp);
513 xfree(tmp);
514 if (rc)
515 goto fail;
517 assuan_begin_confidential(crypto->agent->ctx);
518 rc = send_to_agent(crypto->agent, &key, &keylen, "PKDECRYPT");
519 assuan_end_confidential(crypto->agent->ctx);
520 if (rc)
521 goto fail;
523 rc = gcry_sexp_new(&tmp_sexp, key, keylen, 1);
524 xfree(key);
525 if (rc)
526 goto fail;
528 key = (char *)gcry_sexp_nth_data(tmp_sexp, 1, result_len);
529 if (key) {
530 *result = gcry_malloc(*result_len);
531 if (!*result)
532 rc = GPG_ERR_ENOMEM;
533 else
534 memcpy(*result, key, *result_len);
536 else
537 rc = GPG_ERR_BAD_DATA;
539 gcry_sexp_release(tmp_sexp);
541 fail:
542 xfree(idata.line);
543 xfree(hexgrip);
545 if (enc_sexp)
546 gcry_sexp_release(enc_sexp);
548 return rc;
551 static gpg_error_t verify(gcry_sexp_t pkey, gcry_sexp_t sig_sexp,
552 const void * data, size_t len)
554 gpg_error_t rc;
555 unsigned hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
556 unsigned char *hash;
557 gcry_sexp_t data_sexp;
559 hash = gcry_malloc(hashlen);
560 if (!hash)
561 return GPG_ERR_ENOMEM;
563 gcry_md_hash_buffer(GCRY_MD_SHA256, hash, data, len);
564 rc = gcry_sexp_build(&data_sexp, NULL,
565 "(data (flags pkcs1) (hash sha256 %b))", hashlen, hash);
566 gcry_free(hash);
567 if (!rc) {
568 rc = gcry_pk_verify(sig_sexp, data_sexp, pkey);
569 gcry_sexp_release(data_sexp);
572 return rc;
575 #define CRYPTO_BLOCKSIZE(c) (blocksize * 1024)
578 * Useful for a large amount of data. Rather than doing all of the data in one
579 * iteration do it in chunks. This lets the command be cancelable rather than
580 * waiting for it to complete.
582 static gpg_error_t iterate_crypto_once(gcry_cipher_hd_t h, unsigned char *inbuf,
583 size_t insize, size_t blocksize, status_msg_t which)
585 gpg_error_t rc = 0;
586 off_t len = CRYPTO_BLOCKSIZE(blocksize);
587 void * p = gcry_malloc(len);
588 off_t total = 0;
589 unsigned char *inbuf2;
591 if (!p)
592 return GPG_ERR_ENOMEM;
594 if (insize < CRYPTO_BLOCKSIZE(blocksize))
595 len = insize;
597 pthread_cleanup_push(gcry_free, p);
599 for (;;) {
600 inbuf2 = inbuf+total;
601 unsigned char *tmp;
603 if (len + total > insize)
604 len = blocksize;
606 if (which == STATUS_ENCRYPT)
607 rc = gcry_cipher_encrypt(h, p, len, inbuf2, len);
608 else
609 rc = gcry_cipher_decrypt(h, p, len, inbuf2, len);
611 if (rc)
612 break;
614 tmp = inbuf+total;
615 memmove(tmp, p, len);
616 total += len;
617 if (total >= insize)
618 break;
620 pthread_testcancel();
623 pthread_cleanup_pop(1);
624 return rc;
627 static void cleanup_cipher(void *arg)
629 gcry_cipher_close((gcry_cipher_hd_t)arg);
632 gpg_error_t decrypt_data(assuan_context_t ctx, struct crypto_s *crypto)
634 gpg_error_t rc;
635 unsigned char *key = NULL;
636 size_t keylen = 0;
637 gcry_cipher_hd_t h = NULL;
638 size_t blocksize, keysize;
639 int algo = cipher_to_gcrypt(crypto->hdr.flags);
640 void * outbuf = NULL;
641 gcry_sexp_t sig_sexp;
642 uint64_t n = crypto->hdr.iterations;
643 long progress = 0;
645 rc = extract_key(crypto, &key, &keylen);
646 if (rc)
647 return rc;
649 sig_sexp = gcry_sexp_find_token(crypto->ciphertext_sexp, "sig-val", 0);
650 if (!sig_sexp) {
651 gcry_free(key);
652 return GPG_ERR_BAD_DATA;
655 pthread_cleanup_push(gcry_free, key);
656 rc = verify(crypto->sigpkey_sexp, sig_sexp, crypto->ciphertext, crypto->ciphertext_len);
657 gcry_sexp_release(sig_sexp);
659 if (!rc) {
660 rc = gcry_cipher_open(&h, algo, GCRY_CIPHER_MODE_CBC, 0);
661 if (!rc) {
662 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL,
663 &keysize);
664 if (!rc) {
665 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_BLKLEN, NULL,
666 &blocksize);
667 if (!rc) {
668 rc = gcry_cipher_setiv(h, crypto->hdr.iv,
669 sizeof(crypto->hdr.iv));
670 if (!rc) {
671 rc = gcry_cipher_setkey(h, key, keylen);
678 pthread_cleanup_push(cleanup_cipher, rc ? NULL : h);
680 if (!rc) {
681 outbuf = gcry_malloc(crypto->hdr.datalen);
682 if (!outbuf)
683 rc = GPG_ERR_ENOMEM;
686 pthread_cleanup_push(gcry_free, outbuf);
688 if (!rc) {
689 memcpy(outbuf, crypto->ciphertext, crypto->hdr.datalen);
690 rc = iterate_crypto_once(h, outbuf, crypto->hdr.datalen, blocksize,
691 STATUS_DECRYPT);
692 if (!rc) {
693 key[0] ^= 1;
694 rc = gcry_cipher_setkey(h, key, keylen);
698 if (!rc) {
699 progress = config_get_long(NULL, "cipher_progress");
700 if (progress == -1)
701 progress = strtol(DEFAULT_ITERATION_PROGRESS, NULL, 10);
704 if (!rc && ctx && crypto->hdr.iterations)
705 rc = send_status(ctx, STATUS_DECRYPT, "%llu %llu", 0,
706 crypto->hdr.iterations);
708 for (n = 0; !rc && n < crypto->hdr.iterations; n++) {
709 if (ctx && !(n%progress)) {
710 rc = send_status(ctx, STATUS_DECRYPT, "%llu %llu", n,
711 crypto->hdr.iterations);
712 if (rc)
713 break;
716 rc = gcry_cipher_setiv(h, crypto->hdr.iv, sizeof(crypto->hdr.iv));
717 if (rc)
718 break;
720 rc = iterate_crypto_once(h, outbuf, crypto->hdr.datalen, blocksize,
721 STATUS_DECRYPT);
724 if (!rc && ctx && crypto->hdr.iterations)
725 rc = send_status(ctx, STATUS_DECRYPT, "%llu %llu", n,
726 crypto->hdr.iterations);
728 pthread_cleanup_pop(rc ? 1 : 0); // outbuf
729 pthread_cleanup_pop(1); // cipher
730 pthread_cleanup_pop(1); // key
731 if (!rc) {
732 crypto->plaintext = outbuf;
733 crypto->plaintext_len = crypto->hdr.datalen;
736 return rc;
739 gpg_error_t decrypt_xml(struct crypto_s *crypto, const void * data,
740 size_t len)
742 gcry_cipher_hd_t h = NULL;
743 gpg_error_t rc;
745 rc = gcry_cipher_open(&h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
746 if (rc)
747 return rc;
749 gcry_free(crypto->plaintext);
750 crypto->plaintext = gcry_malloc(len);
751 if (!crypto->plaintext) {
752 rc = GPG_ERR_ENOMEM;
753 goto done;
756 rc = gcry_cipher_setiv(h, cache_iv, cache_blocksize);
757 if (rc)
758 goto done;
760 rc = gcry_cipher_setkey(h, cache_key, cache_keysize);
761 if (rc)
762 goto done;
764 rc = gcry_cipher_decrypt(h, crypto->plaintext, len, data, len);
765 if (rc) {
766 gcry_free(crypto->plaintext);
767 crypto->plaintext = NULL;
770 crypto->plaintext_len = len;
772 done:
773 if (h)
774 gcry_cipher_close(h);
776 return rc;
779 gpg_error_t encrypt_xml(assuan_context_t ctx, void * key, size_t keylen,
780 int algo, const void * xml, size_t len, void * *result, size_t
781 *result_len, unsigned char **iv, size_t *iv_len, uint64_t iter)
783 gpg_error_t rc;
784 gcry_cipher_hd_t h;
785 size_t blocksize, keysize;
786 void * inbuf = NULL;
787 size_t olen = len;
788 uint64_t n;
789 long progress;
790 unsigned char *tmpkey = NULL;
791 int free_iv = *(iv_len) == 0;
793 rc = gcry_cipher_open(&h, algo, GCRY_CIPHER_MODE_CBC, 0);
794 if (rc)
795 return rc;
797 pthread_cleanup_push(cleanup_cipher, h);
798 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
799 if (!rc)
800 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_BLKLEN, NULL, &blocksize);
802 if (!rc && *(iv_len) == 0) {
803 *(iv) = xmalloc(blocksize);
804 if (!*(iv))
805 rc = GPG_ERR_ENOMEM;
807 gcry_create_nonce(*(iv), blocksize);
810 pthread_cleanup_push(xfree, *(iv_len) == 0 ? *(iv) : NULL);
811 if (!rc) {
812 *iv_len = blocksize;
813 tmpkey = gcry_malloc(keylen);
814 if (!tmpkey)
815 rc = GPG_ERR_ENOMEM;
818 pthread_cleanup_push(gcry_free, tmpkey);
820 if (!rc) {
821 memcpy(tmpkey, key, keylen);
822 tmpkey[0] ^= 1;
823 rc = gcry_cipher_setkey(h, tmpkey, keylen);
824 if (!rc) {
825 if (len%blocksize)
826 len += blocksize-(len%blocksize);
830 if (!rc) {
831 inbuf = gcry_malloc(len);
832 if (!inbuf)
833 rc = GPG_ERR_ENOMEM;
836 pthread_cleanup_push(gcry_free, inbuf);
838 if (!rc) {
839 memset(inbuf, 0, len);
840 memcpy(inbuf, xml, olen);
841 progress = config_get_long(NULL, "cipher_progress");
842 if (progress == -1)
843 progress = strtol(DEFAULT_ITERATION_PROGRESS, NULL, 10);
845 if (!rc && ctx && iter)
846 rc = send_status(ctx, STATUS_ENCRYPT, "%llu %llu", 0, iter);
848 for (n = 0; !rc && n < iter; n++) {
849 if (ctx && !(n%progress)) {
850 rc = send_status(ctx, STATUS_ENCRYPT, "%llu %llu", n, iter);
851 if (rc)
852 break;
855 rc = gcry_cipher_setiv(h, *(iv), blocksize);
856 if (rc)
857 break;
859 rc = iterate_crypto_once(h, inbuf, len, blocksize, STATUS_ENCRYPT);
863 if (!rc && ctx && iter)
864 rc = send_status(ctx, STATUS_ENCRYPT, "%llu %llu", n, iter);
866 if (!rc) {
867 /* Do at least one iteration. */
868 rc = gcry_cipher_setiv(h, *(iv), blocksize);
869 if (!rc) {
870 rc = gcry_cipher_setkey(h, key, keylen);
871 if (!rc)
872 rc = iterate_crypto_once(h, inbuf, len, blocksize,
873 STATUS_ENCRYPT);
877 pthread_cleanup_pop(rc ? 1 : 0); // inbuf
878 pthread_cleanup_pop(1); // tmpkey
879 pthread_cleanup_pop(rc && free_iv ? 1 : 0); // iv
880 pthread_cleanup_pop(1); // cipher
881 *result = rc ? NULL : inbuf;
882 *result_len = len;
883 return rc;
886 gpg_error_t agent_loopback_cb(void * user, const char *keyword)
888 struct crypto_s *crypto = user;
889 gpg_error_t rc;
890 unsigned char *result;
891 size_t len;
892 int keyparam = 0;
894 if (!strcmp(keyword, "KEYPARAM")) {
895 keyparam = 1;
896 rc = assuan_inquire(crypto->client_ctx, keyword, &result, &len, 0);
898 else { // PASSPHRASE or NEW_PASSPHRASE
899 assuan_begin_confidential(crypto->client_ctx);
900 rc = assuan_inquire(crypto->client_ctx, keyword, &result, &len, 0);
901 assuan_end_confidential(crypto->client_ctx);
904 if (!rc) {
905 if (keyparam && !len) {
906 char *tmp = default_key_params(crypto);
908 if (!tmp)
909 return gpg_error(GPG_ERR_ENOMEM);
911 len = strlen(tmp);
912 result = xmalloc(len);
913 memcpy(result, tmp, len);
914 xfree(tmp);
917 pthread_cleanup_push(xfree, result);
919 if (keyparam)
920 rc = assuan_send_data(crypto->agent->ctx, result, len);
921 else {
922 assuan_begin_confidential(crypto->agent->ctx);
923 rc = assuan_send_data(crypto->agent->ctx, result, len);
924 assuan_end_confidential(crypto->agent->ctx);
927 pthread_cleanup_pop(1);
929 else if (gpg_err_code(rc) == GPG_ERR_ASS_CANCELED) {
930 gpg_error_t arc = assuan_write_line(crypto->agent->ctx, "CAN");
932 if (!arc) {
933 char *line;
934 size_t len;
936 arc = assuan_read_line(crypto->agent->ctx, &line, &len);
937 if (arc)
938 rc = arc;
940 else
941 rc = arc;
944 return rc;
947 static gpg_error_t sign(gcry_sexp_t *rsexp, const char *sign_hexgrip,
948 struct crypto_s *crypto, const void * data, size_t len)
950 gpg_error_t rc;
951 char *result;
952 char *tmp = sign_hexgrip ? str_dup(sign_hexgrip)
953 : bin2hex(crypto->grip, sizeof(crypto->grip));
955 pthread_cleanup_push(xfree, tmp);
956 log_write1(_("Sign keygrip is %s"), tmp);
957 rc = send_to_agent(crypto->agent, NULL, NULL, "SIGKEY %s", tmp);
958 pthread_cleanup_pop(1);
959 if (!rc) {
960 unsigned char *hash;
961 unsigned hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
963 hash = gcry_malloc(hashlen);
964 if (!hash)
965 return GPG_ERR_ENOMEM;
967 gcry_md_hash_buffer(GCRY_MD_SHA256, hash, data, len);
968 tmp = bin2hex(hash, hashlen);
969 gcry_free(hash);
970 pthread_cleanup_push(xfree, tmp);
971 rc = send_to_agent(crypto->agent, NULL, NULL,
972 "SETHASH --hash=sha256 %s", tmp);
973 pthread_cleanup_pop(1);
976 if (!rc) {
977 struct inquire_data_s idata = {0};
979 idata.crypto = crypto;
980 crypto->agent->inquire_data = &idata;
981 crypto->agent->inquire_cb = inquire_cb;
982 rc = send_to_agent(crypto->agent, &result, &len, "PKSIGN");
983 if (!rc) {
984 rc = gcry_sexp_sscan(rsexp, NULL, result, len);
985 xfree(result);
989 return rc;
992 #ifdef WITH_LIBACL
993 static void cleanup_acl(void *arg)
995 acl_t acl = *(acl_t *)arg;
997 if (acl)
998 acl_free(acl);
1000 #endif
1002 static gpg_error_t write_file(struct crypto_s *crypto, const char *filename,
1003 void * data, size_t data_len, void * sexp, size_t sexp_len,
1004 gcry_sexp_t pubkey, gcry_sexp_t sigpkey)
1006 char tmp[FILENAME_MAX] = { 0 };
1007 mode_t mode = 0;
1008 struct stat st;
1009 int fd;
1010 gpg_error_t rc = 0;
1011 size_t len;
1012 #ifdef WITH_LIBACL
1013 acl_t acl = NULL;
1014 #endif
1016 if (filename) {
1017 if (lstat(filename, &st) == 0) {
1018 mode = st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
1020 if (!(mode & S_IWUSR))
1021 return GPG_ERR_EACCES;
1023 else if (errno != ENOENT)
1024 return gpg_error_from_syserror();
1026 snprintf(tmp, sizeof(tmp), "%s.XXXXXX", filename);
1027 fd = mkstemp(tmp);
1028 if (fd == -1) {
1029 rc = gpg_error_from_syserror();
1030 log_write("%s: %s", tmp, pwmd_strerror(rc));
1031 return rc;
1034 else {
1035 // xml_import() or convert_file() from command line.
1036 fd = STDOUT_FILENO;
1039 pthread_cleanup_push(cleanup_unlink_cb, tmp);
1040 crypto->save.hdr.version = VERSION_HEX;
1041 len = write(fd, &crypto->save.hdr, sizeof(file_header_t));
1042 if (len == sizeof(file_header_t)) {
1043 unsigned char grip[20];
1045 gcry_pk_get_keygrip(pubkey, grip);
1046 len = write(fd, grip, sizeof(grip));
1047 if (len == sizeof(grip)) {
1048 gcry_pk_get_keygrip(sigpkey, grip);
1049 len = write(fd, grip, sizeof(grip));
1050 if (len == sizeof(grip)) {
1051 len = write(fd, data, data_len);
1052 if (len == data_len) {
1053 len = write(fd, sexp, sexp_len);
1054 if (len != sexp_len)
1055 rc = gpg_error_from_syserror();
1057 else
1058 rc = gpg_error_from_syserror();
1061 else
1062 rc = gpg_error_from_syserror();
1064 else
1065 rc = gpg_error_from_syserror();
1067 #ifdef WITH_LIBACL
1068 pthread_cleanup_push(cleanup_acl, &acl);
1069 #endif
1070 if (!rc) {
1071 if (fsync(fd) != -1) {
1072 if (filename && close(fd) != -1) {
1073 #ifdef WITH_LIBACL
1074 acl = acl_get_file(filename, ACL_TYPE_ACCESS);
1075 if (!acl && errno == ENOENT)
1076 acl = acl_get_file(".", ACL_TYPE_DEFAULT);
1077 if (!acl)
1078 log_write("ACL: %s: %s", filename,
1079 pwmd_strerror(gpg_error_from_syserror()));
1080 #endif
1082 if (mode && config_get_boolean(filename, "backup")) {
1083 char tmp2[FILENAME_MAX];
1085 snprintf(tmp2, sizeof(tmp2), "%s.backup", filename);
1086 if (rename(filename, tmp2) == -1)
1087 rc = gpg_error_from_syserror();
1090 else if (filename)
1091 rc = gpg_error_from_syserror();
1093 else
1094 rc = gpg_error_from_syserror();
1097 if (!rc) {
1098 if (filename && rename(tmp, filename) != -1) {
1099 tmp[0] = 0;
1100 if (filename && mode)
1101 chmod(filename, mode);
1103 #ifdef WITH_LIBACL
1104 if (acl && acl_set_file(filename, ACL_TYPE_ACCESS, acl))
1105 log_write("ACL: %s: %s", filename,
1106 pwmd_strerror(gpg_error_from_syserror()));
1107 #endif
1109 else
1110 rc = gpg_error_from_syserror();
1113 #ifdef WITH_LIBACL
1114 pthread_cleanup_pop(1);
1115 #endif
1116 pthread_cleanup_pop(rc ? 1 : 0); // unlink
1117 return rc;
1120 gpg_error_t encrypt_data_file(assuan_context_t ctx, struct crypto_s *crypto,
1121 gcry_sexp_t pubkey, gcry_sexp_t sigpkey, const char *filename, const
1122 void * xml, size_t len)
1124 gpg_error_t rc;
1125 void * data = NULL;
1126 size_t data_len = 0;
1127 void * enc_xml = NULL;
1128 size_t enc_xml_len = 0;
1129 unsigned char *iv = NULL;
1130 size_t iv_len = 0;
1131 int algo = cipher_to_gcrypt(crypto->save.hdr.flags);
1132 void * key = NULL;
1133 size_t keysize;
1134 unsigned char sig_grip[20];
1135 unsigned char grip[20];
1137 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
1138 if (rc)
1139 return rc;
1141 pthread_cleanup_push(gcry_free, key);
1142 key = gcry_random_bytes_secure(keysize, GCRY_STRONG_RANDOM);
1143 pthread_testcancel(); // may have been a long operation
1144 pthread_cleanup_pop(0);
1145 if (!key)
1146 return GPG_ERR_ENOMEM;
1148 gcry_pk_get_keygrip(pubkey, grip);
1149 gcry_pk_get_keygrip(sigpkey, sig_grip);
1150 pthread_cleanup_push(xfree, iv);
1151 pthread_cleanup_push(gcry_free, key);
1152 rc = encrypt_xml(ctx, key, keysize, algo, xml, len, &enc_xml, &enc_xml_len,
1153 &iv, &iv_len, crypto->save.hdr.iterations);
1154 if (!rc) {
1155 gcry_sexp_t sig_sexp = NULL;
1156 char *hexgrip = bin2hex(sig_grip, 20);
1158 pthread_cleanup_push(gcry_free, enc_xml);
1159 rc = sign(&sig_sexp, hexgrip, crypto, enc_xml, enc_xml_len);
1160 xfree(hexgrip);
1162 if (!rc) {
1163 rc = verify(sigpkey, sig_sexp, enc_xml, enc_xml_len);
1165 if (!rc) {
1166 gcry_sexp_t tmp_sexp;
1168 rc = gcry_sexp_build(&tmp_sexp, NULL,
1169 "(data (flags pkcs1) (value %b))", keysize, key);
1170 if (!rc) {
1171 gcry_sexp_t key_sexp;
1173 pthread_cleanup_push((void (*)(void*))gcry_sexp_release,
1174 (void *)sig_sexp);
1175 rc = gcry_pk_encrypt(&key_sexp, tmp_sexp, pubkey);
1176 pthread_cleanup_pop(0);
1177 gcry_sexp_release(tmp_sexp);
1179 if (!rc) {
1180 memcpy(crypto->save.hdr.iv, iv, iv_len);
1181 crypto->save.hdr.datalen = enc_xml_len;
1182 rc = gcry_sexp_build(&tmp_sexp, NULL, "%S%S", key_sexp,
1183 sig_sexp);
1184 gcry_sexp_release(key_sexp);
1186 if (!rc) {
1187 data_len = gcry_sexp_sprint(tmp_sexp,
1188 GCRYSEXP_FMT_CANON, NULL, 0);
1189 data = xmalloc(data_len);
1190 if (data)
1191 gcry_sexp_sprint(tmp_sexp, GCRYSEXP_FMT_CANON,
1192 data, data_len);
1193 else
1194 rc = GPG_ERR_ENOMEM;
1196 gcry_sexp_release(tmp_sexp);
1203 pthread_cleanup_pop(0); // enc_xml
1205 if (sig_sexp)
1206 gcry_sexp_release(sig_sexp);
1209 pthread_cleanup_pop(1); // key
1210 pthread_cleanup_pop(1); // iv
1212 if (!rc) {
1213 pthread_cleanup_push(gcry_free, enc_xml);
1214 rc = write_file(crypto, filename, enc_xml, enc_xml_len, data, data_len,
1215 pubkey, sigpkey);
1216 pthread_cleanup_pop(1); // enc_xml
1217 if (!rc)
1218 memcpy(&crypto->hdr, &crypto->save.hdr, sizeof(file_header_t));
1221 xfree(data);
1222 return rc;
1225 void cleanup_save(struct save_s *save)
1227 if (!save)
1228 return;
1230 if (save->pkey)
1231 gcry_sexp_release(save->pkey);
1233 if (save->sigpkey)
1234 gcry_sexp_release(save->sigpkey);
1236 memset(save, 0, sizeof(struct save_s));
1239 /* Keep the agent ctx to retain pinentry options which will be freed in
1240 * cleanup_cb(). Also keep .pubkey since it may be needed for a SAVE. */
1241 void cleanup_crypto_stage1(struct crypto_s *cr)
1243 if (!cr)
1244 return;
1246 cleanup_save(&cr->save);
1248 if (cr->ciphertext_sexp)
1249 gcry_sexp_release(cr->ciphertext_sexp);
1251 if (cr->plaintext)
1252 gcry_free(cr->plaintext);
1254 xfree(cr->ciphertext);
1255 xfree(cr->filename);
1256 cr->filename = NULL;
1257 cr->ciphertext_sexp = NULL;
1258 cr->ciphertext = NULL;
1259 cr->ciphertext_len = 0;
1260 cr->plaintext = NULL;
1261 cr->plaintext_len = 0;
1264 void cleanup_crypto_stage2(struct crypto_s *cr)
1266 if (!cr)
1267 return;
1269 cleanup_crypto_stage1(cr);
1270 set_header_defaults(&cr->hdr);
1273 void cleanup_crypto(struct crypto_s **c)
1275 struct crypto_s *cr = *c;
1277 if (!cr)
1278 return;
1280 cleanup_crypto_stage2(cr);
1282 if (cr->pkey_sexp)
1283 gcry_sexp_release(cr->pkey_sexp);
1285 if (cr->sigpkey_sexp)
1286 gcry_sexp_release(cr->sigpkey_sexp);
1288 if (cr->agent)
1289 cleanup_agent(cr->agent);
1291 xfree(cr);
1292 *c = NULL;
1295 gpg_error_t init_client_crypto(struct crypto_s **crypto)
1297 struct crypto_s *new = xcalloc(1, sizeof(struct crypto_s));
1298 gpg_error_t rc;
1300 if (!new) {
1301 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
1302 return GPG_ERR_ENOMEM;
1305 rc = agent_init(&new->agent);
1306 if (!rc) {
1307 rc = send_agent_common_options(new->agent);
1308 if (!rc)
1309 rc = set_pinentry_options(new->agent);
1312 if (rc) {
1313 xfree(new);
1314 return rc;
1317 set_header_defaults(&new->hdr);
1318 *crypto = new;
1319 return 0;
1322 gpg_error_t generate_key(struct crypto_s *crypto, char *sexpstr,
1323 int empty, int preset)
1325 gpg_error_t rc;
1326 char *pkey;
1327 size_t plen;
1329 if (crypto->save.s2k_count) {
1330 rc = send_to_agent(crypto->agent, NULL, NULL,
1331 "OPTION s2k-count=%lu", crypto->save.s2k_count);
1332 if (rc)
1333 return rc;
1336 if (!crypto->agent->inquire_cb)
1337 crypto->agent->inquire_cb = inquire_cb;
1339 rc = send_to_agent(crypto->agent, &pkey, &plen, "GENKEY %s%s",
1340 preset ? "--preset " : "",
1341 empty ? "--no-protection" : "");
1342 if (rc)
1343 return rc;
1345 if (crypto->save.pkey)
1346 gcry_sexp_release(crypto->save.pkey);
1348 crypto->save.pkey = NULL;
1349 rc = gcry_sexp_new(&crypto->save.pkey, pkey, plen, 1);
1350 if (!rc) {
1351 unsigned char grip[20];
1353 gcry_pk_get_keygrip(crypto->save.pkey, grip);
1354 char *hexgrip = bin2hex(grip, sizeof(grip));
1355 log_write1(_("Keygrip is %s"), hexgrip);
1356 xfree(hexgrip);
1358 if (!crypto->save.sigpkey) {
1359 gcry_sexp_build((gcry_sexp_t *)&crypto->save.sigpkey, NULL, "%S",
1360 crypto->save.pkey);
1364 xfree(pkey);
1365 return rc;
1368 gpg_error_t set_agent_option(struct agent_s *agent, const char *name,
1369 const char *value)
1371 return send_to_agent(agent, NULL, NULL, "OPTION %s=%s", name, value);
1374 gpg_error_t set_agent_passphrase(struct crypto_s *crypto, const char *key,
1375 size_t len)
1377 char *hexgrip;
1378 struct inquire_data_s idata;
1379 gpg_error_t rc;
1380 int i;
1382 /* This is for use with key files or passphrases obtained from an inquire.
1383 * gpg-agent uses strings as passphrases and will truncate the passphrase
1384 * at the first encountered null byte. It's only a warning because the
1385 * passphrase may belong to a key shared outside of pwmd. */
1386 for (i = 0; i < len; i++) {
1387 if (key[i] == 0) {
1388 log_write(_("WARNING: keylen=%i, truncated to %i."), len, i);
1389 break;
1393 hexgrip = bin2hex(crypto->grip, 20);
1394 crypto->agent->inquire_cb = inquire_cb;
1395 crypto->agent->inquire_data = &idata;
1396 idata.crypto = crypto;
1397 idata.line = (char *)key,
1398 idata.len = len;
1399 idata.preset = 1;
1400 assuan_begin_confidential(crypto->agent->ctx);
1401 rc = send_to_agent(crypto->agent, NULL, NULL,
1402 "PRESET_PASSPHRASE --inquire %s -1", hexgrip);
1403 assuan_end_confidential(crypto->agent->ctx);
1404 idata.preset = 0;
1405 xfree(hexgrip);
1406 return rc;
1409 gpg_error_t set_pinentry_mode(struct agent_s *agent, const char *mode)
1411 return set_agent_option(agent, "pinentry-mode", mode);
1414 gpg_error_t get_pubkey_bin(struct crypto_s *crypto, const unsigned char *grip,
1415 gcry_sexp_t *result)
1417 char *hexgrip = bin2hex(grip, 20);
1418 gpg_error_t rc;
1420 if (!hexgrip)
1421 return GPG_ERR_ENOMEM;
1423 rc = get_pubkey(crypto, hexgrip, result);
1424 xfree(hexgrip);
1425 return rc;
1428 gpg_error_t get_pubkey(struct crypto_s *crypto, const char *grip,
1429 gcry_sexp_t *result)
1431 char *pkey = NULL;
1432 size_t plen;
1433 gpg_error_t rc;
1435 rc = send_to_agent(crypto->agent, &pkey, &plen, "READKEY %s", grip);
1436 if (!rc)
1437 rc = gcry_sexp_new(result, pkey, plen, 1);
1439 xfree(pkey);
1440 return rc;
1443 gpg_error_t set_pinentry_options(struct agent_s *agent)
1445 gpg_error_t rc = 0;
1447 if (getenv("DISPLAY")) {
1448 rc = set_agent_option(agent, "display", getenv("DISPLAY"));
1449 if (!rc) {
1450 xfree(agent->display);
1451 agent->display = str_dup(getenv("DISPLAY"));
1454 else if (ttyname(STDOUT_FILENO)) {
1455 rc = set_agent_option(agent, "ttyname", ttyname(STDOUT_FILENO));
1456 if (!rc) {
1457 rc = set_agent_option(agent, "ttytype", getenv("TERM"));
1458 if (!rc) {
1459 xfree(agent->ttyname);
1460 xfree(agent->ttytype);
1461 agent->ttyname = str_dup(ttyname(STDOUT_FILENO));
1462 agent->ttytype = str_dup(getenv("TERM"));
1467 return rc;
1470 static gpg_error_t inquire_keyfile(void * user, const char *keyword)
1472 struct crypto_s *crypto = user;
1473 char *filename = crypto->agent->inquire_data2;
1474 char *params = crypto->agent->inquire_data3;
1475 int fd;
1476 struct stat st;
1477 unsigned char *buf;
1478 size_t len;
1479 gpg_error_t rc;
1481 if (!strcmp(keyword, "KEYPARAM"))
1482 return assuan_send_data(crypto->agent->ctx, params, strlen(params));
1484 // This function is only used when generating a new keypair.
1485 if (strcmp(keyword, "NEW_PASSPHRASE"))
1486 return gpg_error(GPG_ERR_ASS_UNKNOWN_INQUIRE);
1488 if (stat(filename, &st) == -1)
1489 return gpg_error_from_syserror();
1491 if (crypto->agent->inquire_maxlen
1492 && st.st_size > crypto->agent->inquire_maxlen) {
1493 log_write(_("The passphrase is too large: have=%u, max=%u."),
1494 (unsigned)st.st_size, crypto->agent->inquire_maxlen);
1495 return GPG_ERR_TOO_LARGE;
1498 buf = gcry_malloc_secure(st.st_size);
1499 if (!buf)
1500 return GPG_ERR_ENOMEM;
1502 fd = open(filename, O_RDONLY);
1503 if (fd == -1)
1504 rc = gpg_error_from_syserror();
1505 else {
1506 len = read(fd, buf, st.st_size);
1507 if (len == st.st_size) {
1508 assuan_begin_confidential(crypto->agent->ctx);
1509 rc = assuan_send_data(crypto->agent->ctx, buf, len);
1510 assuan_end_confidential(crypto->agent->ctx);
1512 else if (len == -1)
1513 rc = gpg_error_from_syserror();
1514 else
1515 rc = GPG_ERR_BUFFER_TOO_SHORT;
1518 close(fd);
1519 gcry_free(buf);
1520 return rc;
1523 gpg_error_t export_common(struct crypto_s *crypto, const char *hexgrip,
1524 const char *sign_hexgrip, int no_passphrase,
1525 const void * data, size_t datalen, const char *outfile,
1526 const char *keyparams, const char *keyfile)
1528 gpg_error_t rc = 0;
1530 if (!sign_hexgrip && hexgrip)
1531 sign_hexgrip = hexgrip;
1533 if (sign_hexgrip) {
1534 if (crypto->sigpkey_sexp)
1535 gcry_sexp_release(crypto->sigpkey_sexp);
1537 crypto->sigpkey_sexp = NULL;
1538 rc = get_pubkey(crypto, sign_hexgrip, &crypto->save.sigpkey);
1539 if (rc)
1540 return rc;
1542 gcry_pk_get_keygrip(crypto->save.sigpkey, crypto->sign_grip);
1545 if (hexgrip) {
1546 rc = get_pubkey(crypto, hexgrip, &crypto->save.pkey);
1547 if (!rc)
1548 gcry_pk_get_keygrip(crypto->save.pkey, crypto->grip);
1550 else {
1551 struct inquire_data_s idata = {0};
1552 char *params = keyparams ? str_dup(keyparams)
1553 : default_key_params(crypto);
1555 pthread_cleanup_push(xfree, params);
1556 log_write(_("Generating a new keypair ..."));
1557 if (keyfile) {
1558 log_write(_("Using passphrase obtained from file '%s'"), keyfile);
1559 rc = set_pinentry_mode(crypto->agent, "loopback");
1560 crypto->agent->inquire_cb = inquire_keyfile;
1561 crypto->agent->inquire_data = crypto;
1562 crypto->agent->inquire_data2 = (char *)keyfile;
1563 crypto->agent->inquire_data3 = params;
1565 else {
1566 idata.line = params;
1567 idata.len = strlen(params);
1568 idata.crypto = crypto;
1569 crypto->agent->inquire_cb = inquire_cb;
1570 crypto->agent->inquire_data = &idata;
1573 if (!rc) {
1574 rc = generate_key(crypto, params, no_passphrase, 1);
1575 gcry_pk_get_keygrip(crypto->save.pkey, crypto->grip);
1578 (void)set_pinentry_mode(crypto->agent, "ask");
1579 pthread_cleanup_pop(1);
1582 if (!rc) {
1583 rc = encrypt_data_file(NULL, crypto, crypto->save.pkey,
1584 crypto->save.sigpkey, outfile, data, datalen);
1585 if (!rc) {
1586 char *tmp = bin2hex(crypto->grip, sizeof(crypto->grip));
1588 log_write(_("Success! Keygrip is %s."), tmp);
1589 rc = send_to_agent(crypto->agent, NULL, NULL,
1590 "CLEAR_PASSPHRASE --mode=normal %s", tmp);
1591 xfree(tmp);
1593 if (sign_hexgrip) {
1594 tmp = bin2hex(crypto->sign_grip, sizeof(crypto->sign_grip));
1595 log_write(_("Signed with keygrip %s."), tmp);
1596 xfree(tmp);
1601 return rc;
1604 char *default_key_params(struct crypto_s *crypto)
1606 int len = config_get_integer(NULL, "nbits");
1607 char buf[32];
1608 char *algo = config_get_string(NULL, "algo");
1609 char *result;
1611 snprintf(buf, sizeof(buf), "%i", len);
1612 result = str_asprintf("(genkey (%s (nbits %lu:%i)))", algo, strlen(buf),
1613 len);
1614 xfree(algo);
1615 return result;
1618 gpg_error_t agent_passwd(struct crypto_s *crypto)
1620 struct inquire_data_s idata = {0};
1621 gpg_error_t rc;
1622 char *tmp = bin2hex(crypto->grip, 20);
1624 idata.crypto = crypto;
1625 crypto->agent->inquire_cb = inquire_cb;
1626 crypto->agent->inquire_data = &idata;
1627 rc = send_to_agent(crypto->agent, NULL, NULL, "PASSWD --preset %s", tmp);
1628 xfree(tmp);
1629 return rc;
1632 gpg_error_t kill_scd(struct agent_s *agent)
1634 gpg_error_t rc = 0;
1636 if (config_get_boolean(NULL, "kill_scd")) {
1637 rc = send_to_agent(agent, NULL, NULL, "SCD KILLSCD");
1638 if (rc && gpg_err_code(rc) != GPG_ERR_NO_SCDAEMON)
1639 log_write("%s: %s", __FUNCTION__, pwmd_strerror(rc));
1642 return rc;