Remove GLib dependency.
[pwmd.git] / src / agent.c
bloba3fab9329021c9f2ee036539caaadbaa34223fb7
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 static gpg_error_t write_file(struct crypto_s *crypto, const char *filename,
993 void * data, size_t data_len, void * sexp, size_t sexp_len,
994 gcry_sexp_t pubkey, gcry_sexp_t sigpkey)
996 char tmp[FILENAME_MAX] = { 0 };
997 mode_t mode = 0;
998 struct stat st;
999 int fd;
1000 gpg_error_t rc = 0;
1001 size_t len;
1002 #ifdef WITH_LIBACL
1003 acl_t acl = NULL;
1004 #endif
1006 if (filename) {
1007 if (lstat(filename, &st) == 0) {
1008 mode = st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
1010 if (!(mode & S_IWUSR))
1011 return GPG_ERR_EACCES;
1013 else if (errno != ENOENT)
1014 return gpg_error_from_syserror();
1016 snprintf(tmp, sizeof(tmp), "%s.XXXXXX", filename);
1017 fd = mkstemp(tmp);
1018 if (fd == -1) {
1019 rc = gpg_error_from_syserror();
1020 log_write("%s: %s", tmp, pwmd_strerror(rc));
1021 return rc;
1024 else {
1025 // xml_import() or convert_file() from command line.
1026 fd = STDOUT_FILENO;
1029 pthread_cleanup_push(cleanup_unlink_cb, tmp);
1030 crypto->save.hdr.version = VERSION_HEX;
1031 len = write(fd, &crypto->save.hdr, sizeof(file_header_t));
1032 if (len == sizeof(file_header_t)) {
1033 unsigned char grip[20];
1035 gcry_pk_get_keygrip(pubkey, grip);
1036 len = write(fd, grip, sizeof(grip));
1037 if (len == sizeof(grip)) {
1038 gcry_pk_get_keygrip(sigpkey, grip);
1039 len = write(fd, grip, sizeof(grip));
1040 if (len == sizeof(grip)) {
1041 len = write(fd, data, data_len);
1042 if (len == data_len) {
1043 len = write(fd, sexp, sexp_len);
1044 if (len != sexp_len)
1045 rc = gpg_error_from_syserror();
1047 else
1048 rc = gpg_error_from_syserror();
1051 else
1052 rc = gpg_error_from_syserror();
1054 else
1055 rc = gpg_error_from_syserror();
1057 #ifdef WITH_LIBACL
1058 pthread_cleanup_push(acl_free, acl);
1059 #endif
1060 if (!rc) {
1061 if (fsync(fd) != -1) {
1062 if (filename && close(fd) != -1) {
1063 if (mode && config_get_boolean(filename, "backup")) {
1064 char tmp2[FILENAME_MAX];
1066 snprintf(tmp2, sizeof(tmp2), "%s.backup", filename);
1067 #ifdef WITH_LIBACL
1068 acl = acl_get_file(filename, ACL_TYPE_ACCESS);
1069 if (!acl)
1070 log_write("ACL: %s: %s", filename,
1071 pwmd_strerror(gpg_error_from_syserror()));
1072 #endif
1074 if (rename(filename, tmp2) == -1)
1075 rc = gpg_error_from_syserror();
1077 else if (filename) {
1078 #ifdef WITH_LIBACL
1079 acl = acl_get_file(".", ACL_TYPE_DEFAULT);
1080 if (!acl)
1081 log_write("ACL: %s: %s", filename,
1082 pwmd_strerror(gpg_error_from_syserror()));
1083 #endif
1086 else if (filename)
1087 rc = gpg_error_from_syserror();
1089 else
1090 rc = gpg_error_from_syserror();
1093 if (!rc) {
1094 if (filename && rename(tmp, filename) != -1) {
1095 tmp[0] = 0;
1096 if (filename && mode)
1097 chmod(filename, mode);
1099 #ifdef WITH_LIBACL
1100 if (filename && acl && acl_set_file(filename, ACL_TYPE_ACCESS, acl))
1101 log_write("ACL: %s: %s", filename,
1102 pwmd_strerror(gpg_error_from_syserror()));
1103 #endif
1105 else
1106 rc = gpg_error_from_syserror();
1109 #ifdef WITH_LIBACL
1110 pthread_cleanup_pop(1);
1111 #endif
1112 pthread_cleanup_pop(rc ? 1 : 0); // unlink
1113 return rc;
1116 gpg_error_t encrypt_data_file(assuan_context_t ctx, struct crypto_s *crypto,
1117 gcry_sexp_t pubkey, gcry_sexp_t sigpkey, const char *filename, const
1118 void * xml, size_t len)
1120 gpg_error_t rc;
1121 void * data = NULL;
1122 size_t data_len = 0;
1123 void * enc_xml = NULL;
1124 size_t enc_xml_len = 0;
1125 unsigned char *iv = NULL;
1126 size_t iv_len = 0;
1127 int algo = cipher_to_gcrypt(crypto->save.hdr.flags);
1128 void * key = NULL;
1129 size_t keysize;
1130 unsigned char sig_grip[20];
1131 unsigned char grip[20];
1133 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
1134 if (rc)
1135 return rc;
1137 pthread_cleanup_push(gcry_free, key);
1138 key = gcry_random_bytes_secure(keysize, GCRY_STRONG_RANDOM);
1139 pthread_testcancel(); // may have been a long operation
1140 pthread_cleanup_pop(0);
1141 if (!key)
1142 return GPG_ERR_ENOMEM;
1144 gcry_pk_get_keygrip(pubkey, grip);
1145 gcry_pk_get_keygrip(sigpkey, sig_grip);
1146 pthread_cleanup_push(xfree, iv);
1147 pthread_cleanup_push(gcry_free, key);
1148 rc = encrypt_xml(ctx, key, keysize, algo, xml, len, &enc_xml, &enc_xml_len,
1149 &iv, &iv_len, crypto->save.hdr.iterations);
1150 if (!rc) {
1151 gcry_sexp_t sig_sexp = NULL;
1152 char *hexgrip = bin2hex(sig_grip, 20);
1154 pthread_cleanup_push(gcry_free, enc_xml);
1155 rc = sign(&sig_sexp, hexgrip, crypto, enc_xml, enc_xml_len);
1156 xfree(hexgrip);
1158 if (!rc) {
1159 rc = verify(sigpkey, sig_sexp, enc_xml, enc_xml_len);
1161 if (!rc) {
1162 gcry_sexp_t tmp_sexp;
1164 rc = gcry_sexp_build(&tmp_sexp, NULL,
1165 "(data (flags pkcs1) (value %b))", keysize, key);
1166 if (!rc) {
1167 gcry_sexp_t key_sexp;
1169 pthread_cleanup_push((void (*)(void*))gcry_sexp_release,
1170 (void *)sig_sexp);
1171 rc = gcry_pk_encrypt(&key_sexp, tmp_sexp, pubkey);
1172 pthread_cleanup_pop(0);
1173 gcry_sexp_release(tmp_sexp);
1175 if (!rc) {
1176 memcpy(crypto->save.hdr.iv, iv, iv_len);
1177 crypto->save.hdr.datalen = enc_xml_len;
1178 rc = gcry_sexp_build(&tmp_sexp, NULL, "%S%S", key_sexp,
1179 sig_sexp);
1180 gcry_sexp_release(key_sexp);
1182 if (!rc) {
1183 data_len = gcry_sexp_sprint(tmp_sexp,
1184 GCRYSEXP_FMT_CANON, NULL, 0);
1185 data = xmalloc(data_len);
1186 if (data)
1187 gcry_sexp_sprint(tmp_sexp, GCRYSEXP_FMT_CANON,
1188 data, data_len);
1189 else
1190 rc = GPG_ERR_ENOMEM;
1192 gcry_sexp_release(tmp_sexp);
1199 pthread_cleanup_pop(0); // enc_xml
1201 if (sig_sexp)
1202 gcry_sexp_release(sig_sexp);
1205 pthread_cleanup_pop(1); // key
1206 pthread_cleanup_pop(1); // iv
1208 if (!rc) {
1209 pthread_cleanup_push(gcry_free, enc_xml);
1210 rc = write_file(crypto, filename, enc_xml, enc_xml_len, data, data_len,
1211 pubkey, sigpkey);
1212 pthread_cleanup_pop(1); // enc_xml
1213 if (!rc)
1214 memcpy(&crypto->hdr, &crypto->save.hdr, sizeof(file_header_t));
1217 xfree(data);
1218 return rc;
1221 void cleanup_save(struct save_s *save)
1223 if (!save)
1224 return;
1226 if (save->pkey)
1227 gcry_sexp_release(save->pkey);
1229 if (save->sigpkey)
1230 gcry_sexp_release(save->sigpkey);
1232 memset(save, 0, sizeof(struct save_s));
1235 /* Keep the agent ctx to retain pinentry options which will be freed in
1236 * cleanup_cb(). Also keep .pubkey since it may be needed for a SAVE. */
1237 void cleanup_crypto_stage1(struct crypto_s *cr)
1239 if (!cr)
1240 return;
1242 cleanup_save(&cr->save);
1244 if (cr->ciphertext_sexp)
1245 gcry_sexp_release(cr->ciphertext_sexp);
1247 if (cr->plaintext)
1248 gcry_free(cr->plaintext);
1250 xfree(cr->ciphertext);
1251 xfree(cr->filename);
1252 cr->filename = NULL;
1253 cr->ciphertext_sexp = NULL;
1254 cr->ciphertext = NULL;
1255 cr->ciphertext_len = 0;
1256 cr->plaintext = NULL;
1257 cr->plaintext_len = 0;
1260 void cleanup_crypto_stage2(struct crypto_s *cr)
1262 if (!cr)
1263 return;
1265 cleanup_crypto_stage1(cr);
1266 set_header_defaults(&cr->hdr);
1269 void cleanup_crypto(struct crypto_s **c)
1271 struct crypto_s *cr = *c;
1273 if (!cr)
1274 return;
1276 cleanup_crypto_stage2(cr);
1278 if (cr->pkey_sexp)
1279 gcry_sexp_release(cr->pkey_sexp);
1281 if (cr->sigpkey_sexp)
1282 gcry_sexp_release(cr->sigpkey_sexp);
1284 if (cr->agent)
1285 cleanup_agent(cr->agent);
1287 xfree(cr);
1288 *c = NULL;
1291 gpg_error_t init_client_crypto(struct crypto_s **crypto)
1293 struct crypto_s *new = xcalloc(1, sizeof(struct crypto_s));
1294 gpg_error_t rc;
1296 if (!new) {
1297 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
1298 return GPG_ERR_ENOMEM;
1301 rc = agent_init(&new->agent);
1302 if (!rc) {
1303 rc = send_agent_common_options(new->agent);
1304 if (!rc)
1305 rc = set_pinentry_options(new->agent);
1308 if (rc) {
1309 xfree(new);
1310 return rc;
1313 set_header_defaults(&new->hdr);
1314 *crypto = new;
1315 return 0;
1318 gpg_error_t generate_key(struct crypto_s *crypto, char *sexpstr,
1319 int empty, int preset)
1321 gpg_error_t rc;
1322 char *pkey;
1323 size_t plen;
1325 if (crypto->save.s2k_count) {
1326 rc = send_to_agent(crypto->agent, NULL, NULL,
1327 "OPTION s2k-count=%lu", crypto->save.s2k_count);
1328 if (rc)
1329 return rc;
1332 if (!crypto->agent->inquire_cb)
1333 crypto->agent->inquire_cb = inquire_cb;
1335 rc = send_to_agent(crypto->agent, &pkey, &plen, "GENKEY %s%s",
1336 preset ? "--preset " : "",
1337 empty ? "--no-protection" : "");
1338 if (rc)
1339 return rc;
1341 if (crypto->save.pkey)
1342 gcry_sexp_release(crypto->save.pkey);
1344 crypto->save.pkey = NULL;
1345 rc = gcry_sexp_new(&crypto->save.pkey, pkey, plen, 1);
1346 if (!rc) {
1347 unsigned char grip[20];
1349 gcry_pk_get_keygrip(crypto->save.pkey, grip);
1350 char *hexgrip = bin2hex(grip, sizeof(grip));
1351 log_write1(_("Keygrip is %s"), hexgrip);
1352 xfree(hexgrip);
1354 if (!crypto->save.sigpkey) {
1355 gcry_sexp_build((gcry_sexp_t *)&crypto->save.sigpkey, NULL, "%S",
1356 crypto->save.pkey);
1360 xfree(pkey);
1361 return rc;
1364 gpg_error_t set_agent_option(struct agent_s *agent, const char *name,
1365 const char *value)
1367 return send_to_agent(agent, NULL, NULL, "OPTION %s=%s", name, value);
1370 gpg_error_t set_agent_passphrase(struct crypto_s *crypto, const char *key,
1371 size_t len)
1373 char *hexgrip;
1374 struct inquire_data_s idata;
1375 gpg_error_t rc;
1376 int i;
1378 /* This is for use with key files or passphrases obtained from an inquire.
1379 * gpg-agent uses strings as passphrases and will truncate the passphrase
1380 * at the first encountered null byte. It's only a warning because the
1381 * passphrase may belong to a key shared outside of pwmd. */
1382 for (i = 0; i < len; i++) {
1383 if (key[i] == 0) {
1384 log_write(_("WARNING: keylen=%i, truncated to %i."), len, i);
1385 break;
1389 hexgrip = bin2hex(crypto->grip, 20);
1390 crypto->agent->inquire_cb = inquire_cb;
1391 crypto->agent->inquire_data = &idata;
1392 idata.crypto = crypto;
1393 idata.line = (char *)key,
1394 idata.len = len;
1395 idata.preset = 1;
1396 assuan_begin_confidential(crypto->agent->ctx);
1397 rc = send_to_agent(crypto->agent, NULL, NULL,
1398 "PRESET_PASSPHRASE --inquire %s -1", hexgrip);
1399 assuan_end_confidential(crypto->agent->ctx);
1400 idata.preset = 0;
1401 xfree(hexgrip);
1402 return rc;
1405 gpg_error_t set_pinentry_mode(struct agent_s *agent, const char *mode)
1407 return set_agent_option(agent, "pinentry-mode", mode);
1410 gpg_error_t get_pubkey_bin(struct crypto_s *crypto, const unsigned char *grip,
1411 gcry_sexp_t *result)
1413 char *hexgrip = bin2hex(grip, 20);
1414 gpg_error_t rc;
1416 if (!hexgrip)
1417 return GPG_ERR_ENOMEM;
1419 rc = get_pubkey(crypto, hexgrip, result);
1420 xfree(hexgrip);
1421 return rc;
1424 gpg_error_t get_pubkey(struct crypto_s *crypto, const char *grip,
1425 gcry_sexp_t *result)
1427 char *pkey = NULL;
1428 size_t plen;
1429 gpg_error_t rc;
1431 rc = send_to_agent(crypto->agent, &pkey, &plen, "READKEY %s", grip);
1432 if (!rc)
1433 rc = gcry_sexp_new(result, pkey, plen, 1);
1435 xfree(pkey);
1436 return rc;
1439 gpg_error_t set_pinentry_options(struct agent_s *agent)
1441 gpg_error_t rc = 0;
1443 if (getenv("DISPLAY")) {
1444 rc = set_agent_option(agent, "display", getenv("DISPLAY"));
1445 if (!rc) {
1446 xfree(agent->display);
1447 agent->display = str_dup(getenv("DISPLAY"));
1450 else if (ttyname(STDOUT_FILENO)) {
1451 rc = set_agent_option(agent, "ttyname", ttyname(STDOUT_FILENO));
1452 if (!rc) {
1453 rc = set_agent_option(agent, "ttytype", getenv("TERM"));
1454 if (!rc) {
1455 xfree(agent->ttyname);
1456 xfree(agent->ttytype);
1457 agent->ttyname = str_dup(ttyname(STDOUT_FILENO));
1458 agent->ttytype = str_dup(getenv("TERM"));
1463 return rc;
1466 static gpg_error_t inquire_keyfile(void * user, const char *keyword)
1468 struct crypto_s *crypto = user;
1469 char *filename = crypto->agent->inquire_data2;
1470 char *params = crypto->agent->inquire_data3;
1471 int fd;
1472 struct stat st;
1473 unsigned char *buf;
1474 size_t len;
1475 gpg_error_t rc;
1477 if (!strcmp(keyword, "KEYPARAM"))
1478 return assuan_send_data(crypto->agent->ctx, params, strlen(params));
1480 // This function is only used when generating a new keypair.
1481 if (strcmp(keyword, "NEW_PASSPHRASE"))
1482 return gpg_error(GPG_ERR_ASS_UNKNOWN_INQUIRE);
1484 if (stat(filename, &st) == -1)
1485 return gpg_error_from_syserror();
1487 if (crypto->agent->inquire_maxlen
1488 && st.st_size > crypto->agent->inquire_maxlen) {
1489 log_write(_("The passphrase is too large: have=%u, max=%u."),
1490 (unsigned)st.st_size, crypto->agent->inquire_maxlen);
1491 return GPG_ERR_TOO_LARGE;
1494 buf = gcry_malloc_secure(st.st_size);
1495 if (!buf)
1496 return GPG_ERR_ENOMEM;
1498 fd = open(filename, O_RDONLY);
1499 if (fd == -1)
1500 rc = gpg_error_from_syserror();
1501 else {
1502 len = read(fd, buf, st.st_size);
1503 if (len == st.st_size) {
1504 assuan_begin_confidential(crypto->agent->ctx);
1505 rc = assuan_send_data(crypto->agent->ctx, buf, len);
1506 assuan_end_confidential(crypto->agent->ctx);
1508 else if (len == -1)
1509 rc = gpg_error_from_syserror();
1510 else
1511 rc = GPG_ERR_BUFFER_TOO_SHORT;
1514 close(fd);
1515 gcry_free(buf);
1516 return rc;
1519 gpg_error_t export_common(struct crypto_s *crypto, const char *hexgrip,
1520 const char *sign_hexgrip, int no_passphrase,
1521 const void * data, size_t datalen, const char *outfile,
1522 const char *keyparams, const char *keyfile)
1524 gpg_error_t rc = 0;
1526 if (!sign_hexgrip && hexgrip)
1527 sign_hexgrip = hexgrip;
1529 if (sign_hexgrip) {
1530 if (crypto->sigpkey_sexp)
1531 gcry_sexp_release(crypto->sigpkey_sexp);
1533 crypto->sigpkey_sexp = NULL;
1534 rc = get_pubkey(crypto, sign_hexgrip, &crypto->save.sigpkey);
1535 if (rc)
1536 return rc;
1538 gcry_pk_get_keygrip(crypto->save.sigpkey, crypto->sign_grip);
1541 if (hexgrip) {
1542 rc = get_pubkey(crypto, hexgrip, &crypto->save.pkey);
1543 if (!rc)
1544 gcry_pk_get_keygrip(crypto->save.pkey, crypto->grip);
1546 else {
1547 struct inquire_data_s idata = {0};
1548 char *params = keyparams ? str_dup(keyparams)
1549 : default_key_params(crypto);
1551 pthread_cleanup_push(xfree, params);
1552 log_write(_("Generating a new keypair ..."));
1553 if (keyfile) {
1554 log_write(_("Using passphrase obtained from file '%s'"), keyfile);
1555 rc = set_pinentry_mode(crypto->agent, "loopback");
1556 crypto->agent->inquire_cb = inquire_keyfile;
1557 crypto->agent->inquire_data = crypto;
1558 crypto->agent->inquire_data2 = (char *)keyfile;
1559 crypto->agent->inquire_data3 = params;
1561 else {
1562 idata.line = params;
1563 idata.len = strlen(params);
1564 idata.crypto = crypto;
1565 crypto->agent->inquire_cb = inquire_cb;
1566 crypto->agent->inquire_data = &idata;
1569 if (!rc) {
1570 rc = generate_key(crypto, params, no_passphrase, 1);
1571 gcry_pk_get_keygrip(crypto->save.pkey, crypto->grip);
1574 (void)set_pinentry_mode(crypto->agent, "ask");
1575 pthread_cleanup_pop(1);
1578 if (!rc) {
1579 rc = encrypt_data_file(NULL, crypto, crypto->save.pkey,
1580 crypto->save.sigpkey, outfile, data, datalen);
1581 if (!rc) {
1582 char *tmp = bin2hex(crypto->grip, sizeof(crypto->grip));
1584 log_write(_("Success! Keygrip is %s."), tmp);
1585 rc = send_to_agent(crypto->agent, NULL, NULL,
1586 "CLEAR_PASSPHRASE --mode=normal %s", tmp);
1587 xfree(tmp);
1589 if (sign_hexgrip) {
1590 tmp = bin2hex(crypto->sign_grip, sizeof(crypto->sign_grip));
1591 log_write(_("Signed with keygrip %s."), tmp);
1592 xfree(tmp);
1597 return rc;
1600 char *default_key_params(struct crypto_s *crypto)
1602 int len = config_get_integer(NULL, "nbits");
1603 char buf[32];
1604 char *algo = config_get_string(NULL, "algo");
1605 char *result;
1607 snprintf(buf, sizeof(buf), "%i", len);
1608 result = str_asprintf("(genkey (%s (nbits %lu:%i)))", algo, strlen(buf),
1609 len);
1610 xfree(algo);
1611 return result;
1614 gpg_error_t agent_passwd(struct crypto_s *crypto)
1616 struct inquire_data_s idata = {0};
1617 gpg_error_t rc;
1618 char *tmp = bin2hex(crypto->grip, 20);
1620 idata.crypto = crypto;
1621 crypto->agent->inquire_cb = inquire_cb;
1622 crypto->agent->inquire_data = &idata;
1623 rc = send_to_agent(crypto->agent, NULL, NULL, "PASSWD --preset %s", tmp);
1624 xfree(tmp);
1625 return rc;
1628 gpg_error_t kill_scd(struct agent_s *agent)
1630 gpg_error_t rc = 0;
1632 if (config_get_boolean(NULL, "kill_scd")) {
1633 rc = send_to_agent(agent, NULL, NULL, "SCD KILLSCD");
1634 if (rc && gpg_err_code(rc) != GPG_ERR_NO_SCDAEMON)
1635 log_write("%s: %s", __FUNCTION__, pwmd_strerror(rc));
1638 return rc;