1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
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/>.
27 #include <glib/gprintf.h>
28 #include <glib/gstdio.h>
32 #include <sys/types.h>
36 #include "pwmd-error.h"
48 #include <acl/libacl.h>
52 #include <sys/types.h>
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
;
66 if ((p
= xrealloc(mem
->buf
, mem
->len
+ len
)) == NULL
)
70 memcpy((char *)mem
->buf
+ mem
->len
, buffer
, len
);
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
)
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
)
101 rc
= assuan_transact(a
->ctx
, cmd
, mem_realloc_cb
, &a
->data
,
102 a
->inquire_cb
, a
->inquire_data
, status_cb
, a
);
108 mem_realloc_cb(&a
->data
, "", 1);
110 *result
= (gchar
*)a
->data
.buf
;
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
)
128 rc
= send_to_agent(agent
, NULL
, NULL
, "OPTION cache-ttl-opt-preset=-1");
132 static gpg_error_t
launch_agent(struct agent_s
*agent
)
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
];
141 s
= get_key_file_string("global", "agent_env_file");
143 gchar
*ss
= expand_homedir(s
);
150 while ((s
= fgets(buf
, sizeof(buf
), fp
))) {
152 if (g_str_has_prefix(s
, "GPG_AGENT_INFO=")) {
153 g_setenv("GPG_AGENT_INFO", s
+strlen("GPG_AGENT_INFO="), TRUE
);
161 log_write("%s: %s", s
, pwmd_strerror(gpg_error_from_syserror()));
164 t
= g_getenv("GPG_AGENT_INFO");
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 ");
173 gchar
**fields
= g_strsplit(t
, ":", 0);
174 rc
= assuan_socket_connect(ctx
, fields
[0], ASSUAN_INVALID_PID
, 0);
182 /* Restore the previous agent settings for this new context. */
183 assuan_release(agent
->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
);
206 gpg_error_t
send_to_agent(struct agent_s
*agent
, gchar
**result
, gsize
*len
,
207 const gchar
*fmt
, ...)
214 rc
= launch_agent(agent
);
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
);
229 rc
= assuan_command(agent
, result
, len
, cmd
);
232 agent
->restart
= FALSE
;
242 static void agent_disconnect(struct agent_s
*agent
)
248 assuan_release(agent
->ctx
);
253 void cleanup_agent(struct agent_s
*agent
)
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
);
266 agent_disconnect(agent
);
271 gpg_error_t
agent_init(struct agent_s
**agent
)
273 struct agent_s
*new = g_malloc0(sizeof(struct agent_s
));
276 return GPG_ERR_ENOMEM
;
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
);
288 memset(hdr
, 0, sizeof(file_header_t
));
289 memcpy(hdr
->magic
, pwmd_magic
, sizeof(hdr
->magic
));
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
)
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
);
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
;
340 gpg_error_t
read_data_file(const gchar
*filename
, struct crypto_s
*crypto
)
347 cleanup_crypto_stage1(crypto
);
348 rc
= read_data_header(filename
, &crypto
->hdr
, &crypto
->st
, &fd
);
352 crypto
->ciphertext_len
= crypto
->hdr
.datalen
;
353 crypto
->ciphertext
= g_malloc(crypto
->hdr
.datalen
);
354 if (!crypto
->ciphertext
) {
359 len
= read(fd
, crypto
->ciphertext
, crypto
->hdr
.datalen
);
360 if (len
!= crypto
->hdr
.datalen
) {
361 rc
= rc
== -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA
;
365 rlen
= read(fd
, crypto
->grip
, 20);
367 rc
= rc
== -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA
;
371 rlen
= read(fd
, crypto
->sign_grip
, 20);
373 rc
= rc
== -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA
;
377 len
= crypto
->st
.st_size
-sizeof(file_header_t
)-crypto
->hdr
.datalen
-40;
384 rlen
= read(fd
, buf
, len
);
386 rc
= rc
== -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA
;
390 rc
= gcry_sexp_new(&crypto
->ciphertext_sexp
, buf
, rlen
, 1);
394 if (crypto
->pkey_sexp
)
395 gcry_sexp_release(crypto
->pkey_sexp
);
397 if (crypto
->sigpkey_sexp
)
398 gcry_sexp_release(crypto
->sigpkey_sexp
);
400 crypto
->pkey_sexp
= crypto
->sigpkey_sexp
= NULL
;
401 rc
= get_pubkey_bin(crypto
, crypto
->grip
, &crypto
->pkey_sexp
);
403 rc
= get_pubkey_bin(crypto
, crypto
->sign_grip
, &crypto
->sigpkey_sexp
);
411 static gpg_error_t
inquire_cb(gpointer user
, const char *keyword
)
413 struct inquire_data_s
*idata
= user
;
415 if (!idata
->preset
&& (!g_strcmp0(keyword
, "PASSPHRASE")
416 || !g_strcmp0(keyword
, "NEW_PASSPHRASE"))) {
417 return agent_loopback_cb(idata
->crypto
, keyword
);
419 // SAVE --inquire-keyparam
420 else if (idata
->preset
&& !g_strcmp0(keyword
, "KEYPARAM")) {
421 idata
->preset
= FALSE
;
422 return agent_loopback_cb(idata
->crypto
, keyword
);
425 if (idata
->crypto
->agent
->inquire_maxlen
426 && idata
->len
> idata
->crypto
->agent
->inquire_maxlen
) {
427 log_write(_("Inquired data too large: have=%u, max=%u"), idata
->len
,
428 idata
->crypto
->agent
->inquire_maxlen
);
429 return GPG_ERR_TOO_LARGE
;
432 idata
->crypto
->agent
->inquire_maxlen
= 0;
433 return assuan_send_data(idata
->crypto
->agent
->ctx
, idata
->line
, idata
->len
);
436 static gpg_error_t
extract_key(struct crypto_s
*crypto
, guchar
**result
,
440 gcry_sexp_t enc_sexp
= NULL
, tmp_sexp
;
441 struct inquire_data_s idata
= {0};
442 gchar
*hexgrip
= NULL
;
444 gsize keylen
, keysize
;
446 gint algo
= cipher_to_gcrypt(crypto
->hdr
.flags
);
449 rc
= gcry_cipher_algo_info(algo
, GCRYCTL_GET_KEYLEN
, NULL
, &keysize
);
453 tmp_sexp
= gcry_sexp_find_token(crypto
->ciphertext_sexp
, "enc-val", 0);
455 return GPG_ERR_BAD_DATA
;
457 hexgrip
= bin2hex(crypto
->grip
, sizeof(crypto
->grip
));
463 rc
= cache_is_shadowed(hexgrip
);
464 if (rc
&& rc
!= GPG_ERR_NO_DATA
)
467 shadowed
= !rc
? TRUE
: FALSE
;
469 gcry_sexp_t tmp2_sexp
= gcry_sexp_cdr(tmp_sexp
);
470 gcry_sexp_release(tmp_sexp
);
471 tmp_sexp
= gcry_sexp_nth(tmp2_sexp
, 0);
472 gcry_sexp_release(tmp2_sexp
);
473 rc
= gcry_sexp_build(&enc_sexp
, NULL
, "(enc-val (flags pkcs1) %S)",
477 rc
= gcry_sexp_build(&enc_sexp
, NULL
, "%S", tmp_sexp
);
479 gcry_sexp_release(tmp_sexp
);
483 crypto
->agent
->inquire_cb
= inquire_cb
;
484 idata
.crypto
= crypto
;
485 idata
.len
= gcry_sexp_sprint(enc_sexp
, GCRYSEXP_FMT_CANON
, NULL
, 0);
486 idata
.line
= g_malloc(idata
.len
);
492 idata
.len
= gcry_sexp_sprint(enc_sexp
, GCRYSEXP_FMT_CANON
, idata
.line
,
494 crypto
->agent
->inquire_data
= &idata
;
495 gcry_sexp_release(enc_sexp
);
497 log_write1(_("Keygrip is %s, bits=%i"), hexgrip
,
498 gcry_pk_get_nbits(crypto
->pkey_sexp
));
499 rc
= send_to_agent(crypto
->agent
, NULL
, NULL
, "SETKEY %s", hexgrip
);
503 if (!crypto
->agent
->desc
) {
505 "A %s is required to unlock the secret key for the "
506 "encrypted data file \"%s\". Please enter the %s "
508 shadowed
? "PIN" : _("passphrase"), crypto
->filename
,
509 shadowed
? "PIN" : _("passphrase"));
512 tmp
= plus_escape(crypto
->agent
->desc
);
514 rc
= send_to_agent(crypto
->agent
, NULL
, NULL
, "SETKEYDESC %s", tmp
);
519 assuan_begin_confidential(crypto
->agent
->ctx
);
520 rc
= send_to_agent(crypto
->agent
, &key
, &keylen
, "PKDECRYPT");
521 assuan_end_confidential(crypto
->agent
->ctx
);
525 rc
= gcry_sexp_new(&tmp_sexp
, key
, keylen
, 1);
530 key
= (gchar
*)gcry_sexp_nth_data(tmp_sexp
, 1, result_len
);
532 *result
= gcry_malloc(*result_len
);
536 memcpy(*result
, key
, *result_len
);
539 rc
= GPG_ERR_BAD_DATA
;
541 gcry_sexp_release(tmp_sexp
);
548 gcry_sexp_release(enc_sexp
);
553 static gpg_error_t
verify(gcry_sexp_t pkey
, gcry_sexp_t sig_sexp
,
554 const gpointer data
, gsize len
)
557 guint hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
559 gcry_sexp_t data_sexp
;
561 hash
= gcry_malloc(hashlen
);
563 return GPG_ERR_ENOMEM
;
565 gcry_md_hash_buffer(GCRY_MD_SHA256
, hash
, data
, len
);
566 rc
= gcry_sexp_build(&data_sexp
, NULL
,
567 "(data (flags pkcs1) (hash sha256 %b))", hashlen
, hash
);
570 rc
= gcry_pk_verify(sig_sexp
, data_sexp
, pkey
);
571 gcry_sexp_release(data_sexp
);
577 gpg_error_t
decrypt_data(struct crypto_s
*crypto
)
582 gcry_cipher_hd_t h
= NULL
;
583 gsize blocksize
, keysize
;
584 gint algo
= cipher_to_gcrypt(crypto
->hdr
.flags
);
585 gpointer outbuf
= NULL
;
586 gcry_sexp_t sig_sexp
;
588 rc
= extract_key(crypto
, &key
, &keylen
);
592 sig_sexp
= gcry_sexp_find_token(crypto
->ciphertext_sexp
, "sig-val", 0);
594 rc
= GPG_ERR_BAD_DATA
;
598 rc
= verify(crypto
->sigpkey_sexp
, sig_sexp
, crypto
->ciphertext
, crypto
->ciphertext_len
);
599 gcry_sexp_release(sig_sexp
);
603 rc
= gcry_cipher_open(&h
, algo
, GCRY_CIPHER_MODE_CBC
, 0);
607 rc
= gcry_cipher_algo_info(algo
, GCRYCTL_GET_KEYLEN
, NULL
, &keysize
);
610 rc
= gcry_cipher_algo_info(algo
, GCRYCTL_GET_BLKLEN
, NULL
, &blocksize
);
614 rc
= gcry_cipher_setiv(h
, crypto
->hdr
.iv
, sizeof(crypto
->hdr
.iv
));
618 rc
= gcry_cipher_setkey(h
, key
, keylen
);
622 outbuf
= gcry_malloc(crypto
->hdr
.datalen
);
628 rc
= gcry_cipher_decrypt(h
, outbuf
, crypto
->hdr
.datalen
,
629 crypto
->ciphertext
, crypto
->hdr
.datalen
);
633 crypto
->plaintext
= outbuf
;
634 crypto
->plaintext_len
= crypto
->hdr
.datalen
;
639 gcry_cipher_close(h
);
643 static gpg_error_t
encrypt_xml(gpointer key
, gsize keylen
, gint algo
,
644 const gpointer xml
, gsize len
, gpointer
*result
, gsize
*result_len
,
645 guchar
**iv
, gsize
*iv_len
)
649 gsize blocksize
, keysize
;
650 gpointer inbuf
= NULL
;
653 rc
= gcry_cipher_open(&h
, algo
, GCRY_CIPHER_MODE_CBC
, 0);
657 rc
= gcry_cipher_algo_info(algo
, GCRYCTL_GET_KEYLEN
, NULL
, &keysize
);
661 rc
= gcry_cipher_algo_info(algo
, GCRYCTL_GET_BLKLEN
, NULL
, &blocksize
);
665 *(iv
) = g_malloc(blocksize
);
670 gcry_create_nonce(*(iv
), blocksize
);
671 rc
= gcry_cipher_setiv(h
, *(iv
), blocksize
);
675 rc
= gcry_cipher_setkey(h
, key
, keylen
);
680 len
+= blocksize
-(len
%blocksize
);
682 inbuf
= gcry_malloc(len
);
688 memset(inbuf
, 0, len
);
689 memcpy(inbuf
, xml
, olen
);
690 rc
= gcry_cipher_encrypt(h
, inbuf
, len
, NULL
, 0);
696 gcry_cipher_close(h
);
706 gcry_cipher_close(h
);
710 gpg_error_t
agent_loopback_cb(gpointer user
, const gchar
*keyword
)
712 struct crypto_s
*crypto
= user
;
716 gboolean keyparam
= FALSE
;
718 if (!g_strcmp0(keyword
, "KEYPARAM")) {
720 rc
= assuan_inquire(crypto
->client_ctx
, keyword
, &result
, &len
, 0);
722 else { // PASSPHRASE or NEW_PASSPHRASE
723 assuan_begin_confidential(crypto
->client_ctx
);
724 rc
= assuan_inquire(crypto
->client_ctx
, keyword
, &result
, &len
, 0);
725 assuan_end_confidential(crypto
->client_ctx
);
729 if (keyparam
&& !len
) {
730 gchar
*tmp
= default_key_params(crypto
);
733 return gpg_error(GPG_ERR_ENOMEM
);
736 result
= xmalloc(len
);
737 memcpy(result
, tmp
, len
);
741 pthread_cleanup_push(xfree
, result
);
744 rc
= assuan_send_data(crypto
->agent
->ctx
, result
, len
);
746 assuan_begin_confidential(crypto
->agent
->ctx
);
747 rc
= assuan_send_data(crypto
->agent
->ctx
, result
, len
);
748 assuan_end_confidential(crypto
->agent
->ctx
);
751 pthread_cleanup_pop(1);
753 else if (gpg_err_code(rc
) == GPG_ERR_ASS_CANCELED
) {
754 gpg_error_t arc
= assuan_write_line(crypto
->agent
->ctx
, "CAN");
760 arc
= assuan_read_line(crypto
->agent
->ctx
, &line
, &len
);
771 static gpg_error_t
sign(gcry_sexp_t
*rsexp
, const gchar
*sign_hexgrip
,
772 struct crypto_s
*crypto
, const gpointer data
, gsize len
)
776 gchar
*tmp
= sign_hexgrip
? g_strdup(sign_hexgrip
)
777 : bin2hex(crypto
->grip
, sizeof(crypto
->grip
));
779 pthread_cleanup_push(g_free
, tmp
);
780 log_write1(_("Sign keygrip is %s"), tmp
);
781 rc
= send_to_agent(crypto
->agent
, NULL
, NULL
, "SIGKEY %s", tmp
);
782 pthread_cleanup_pop(1);
785 guint hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
787 hash
= gcry_malloc(hashlen
);
789 return GPG_ERR_ENOMEM
;
791 gcry_md_hash_buffer(GCRY_MD_SHA256
, hash
, data
, len
);
792 tmp
= bin2hex(hash
, hashlen
);
794 pthread_cleanup_push(g_free
, tmp
);
795 rc
= send_to_agent(crypto
->agent
, NULL
, NULL
,
796 "SETHASH --hash=sha256 %s", tmp
);
797 pthread_cleanup_pop(1);
801 struct inquire_data_s idata
= {0};
803 idata
.crypto
= crypto
;
804 crypto
->agent
->inquire_data
= &idata
;
805 crypto
->agent
->inquire_cb
= inquire_cb
;
806 rc
= send_to_agent(crypto
->agent
, &result
, &len
, "PKSIGN");
808 rc
= gcry_sexp_sscan(rsexp
, NULL
, result
, len
);
816 static gpg_error_t
write_file(struct crypto_s
*crypto
, const gchar
*filename
,
817 gpointer data
, gsize data_len
, gpointer sexp
, gsize sexp_len
)
819 gchar tmp
[FILENAME_MAX
] = { 0 };
830 if (g_lstat(filename
, &st
) == 0) {
831 mode
= st
.st_mode
& (S_IRWXU
|S_IRWXG
|S_IRWXO
);
833 if (!(mode
& S_IWUSR
))
834 return GPG_ERR_EACCES
;
836 else if (errno
!= ENOENT
)
837 return gpg_error_from_syserror();
839 g_snprintf(tmp
, sizeof(tmp
), "%s.XXXXXX", filename
);
840 #if GLIB_CHECK_VERSION(2, 22, 0)
841 fd
= g_mkstemp_full(tmp
, O_WRONLY
, 0600);
846 rc
= gpg_error_from_syserror();
847 log_write("%s: %s", tmp
, pwmd_strerror(rc
));
852 // xml_import() or convert_file() from command line.
856 pthread_cleanup_push(cleanup_unlink_cb
, tmp
);
857 crypto
->save
.hdr
.version
= VERSION_HEX
;
858 len
= write(fd
, &crypto
->save
.hdr
, sizeof(file_header_t
));
859 if (len
== sizeof(file_header_t
)) {
860 len
= write(fd
, data
, data_len
);
861 if (len
== data_len
) {
862 len
= write(fd
, sexp
, sexp_len
);
864 rc
= gpg_error_from_syserror();
867 rc
= gpg_error_from_syserror();
870 rc
= gpg_error_from_syserror();
873 pthread_cleanup_push(acl_free
, acl
);
876 if (fsync(fd
) != -1) {
877 if (filename
&& close(fd
) != -1) {
878 if (mode
&& get_key_file_boolean(filename
, "backup")) {
879 gchar tmp2
[FILENAME_MAX
];
881 g_snprintf(tmp2
, sizeof(tmp2
), "%s.backup", filename
);
883 acl
= acl_get_file(filename
, ACL_TYPE_ACCESS
);
885 log_write("ACL: %s: %s", filename
,
886 pwmd_strerror(gpg_error_from_syserror()));
889 if (g_rename(filename
, tmp2
) == -1)
890 rc
= gpg_error_from_syserror();
894 acl
= acl_get_file(".", ACL_TYPE_DEFAULT
);
896 log_write("ACL: %s: %s", filename
,
897 pwmd_strerror(gpg_error_from_syserror()));
902 rc
= gpg_error_from_syserror();
905 rc
= gpg_error_from_syserror();
909 if (filename
&& g_rename(tmp
, filename
) != -1) {
911 if (filename
&& mode
)
912 g_chmod(filename
, mode
);
915 if (filename
&& acl
&& acl_set_file(filename
, ACL_TYPE_ACCESS
, acl
))
916 log_write("ACL: %s: %s", filename
,
917 pwmd_strerror(gpg_error_from_syserror()));
920 /* Be sure the file entry has been written to disk. On FreeBSD I
921 * noticed delays causing a following command to return
922 * GPG_ERR_CHECKSUM. Recommended from fsync(2) (Linux).
926 gchar
*s
= get_key_file_string("global", "data_directory");
928 path
= expand_homedir(s
);
937 rc
= gpg_error_from_syserror();
942 rc
= gpg_error_from_syserror();
945 rc
= gpg_error_from_syserror();
949 pthread_cleanup_pop(1);
951 pthread_cleanup_pop(rc
? 1 : 0); // unlink
955 gpg_error_t
encrypt_data_file(struct crypto_s
*crypto
, gcry_sexp_t pubkey
,
956 gcry_sexp_t sigpkey
, const gchar
*filename
, const gpointer xml
,
960 gpointer data
= NULL
;
962 gpointer enc_xml
= NULL
;
963 gsize enc_xml_len
= 0;
966 gint algo
= cipher_to_gcrypt(crypto
->save
.hdr
.flags
);
972 rc
= gcry_cipher_algo_info(algo
, GCRYCTL_GET_KEYLEN
, NULL
, &keysize
);
976 pthread_cleanup_push(gcry_free
, key
);
977 key
= gcry_random_bytes_secure(keysize
, GCRY_STRONG_RANDOM
);
978 pthread_testcancel(); // may have been a long operation
979 pthread_cleanup_pop(0);
981 return GPG_ERR_ENOMEM
;
983 gcry_pk_get_keygrip(pubkey
, grip
);
984 gcry_pk_get_keygrip(sigpkey
, sig_grip
);
985 pthread_cleanup_push(g_free
, iv
);
986 pthread_cleanup_push(gcry_free
, key
);
987 rc
= encrypt_xml(key
, keysize
, algo
, xml
, len
, &enc_xml
, &enc_xml_len
,
990 gcry_sexp_t sig_sexp
= NULL
;
991 gchar
*hexgrip
= bin2hex(sig_grip
, 20);
993 pthread_cleanup_push(gcry_free
, enc_xml
);
994 rc
= sign(&sig_sexp
, hexgrip
, crypto
, enc_xml
, enc_xml_len
);
998 rc
= verify(sigpkey
, sig_sexp
, enc_xml
, enc_xml_len
);
1001 gcry_sexp_t tmp_sexp
;
1003 rc
= gcry_sexp_build(&tmp_sexp
, NULL
,
1004 "(data (flags pkcs1) (value %b))", keysize
, key
);
1006 gcry_sexp_t key_sexp
;
1008 pthread_cleanup_push((void (*)(void*))gcry_sexp_release
,
1010 rc
= gcry_pk_encrypt(&key_sexp
, tmp_sexp
, pubkey
);
1011 pthread_cleanup_pop(0);
1012 gcry_sexp_release(tmp_sexp
);
1015 memcpy(crypto
->save
.hdr
.iv
, iv
, iv_len
);
1016 crypto
->save
.hdr
.datalen
= enc_xml_len
;
1017 rc
= gcry_sexp_build(&tmp_sexp
, NULL
, "%S%S", key_sexp
,
1019 gcry_sexp_release(key_sexp
);
1022 data_len
= gcry_sexp_sprint(tmp_sexp
,
1023 GCRYSEXP_FMT_CANON
, NULL
, 0);
1024 data
= g_malloc(data_len
+40); // +40 for keygrips
1026 gcry_sexp_sprint(tmp_sexp
, GCRYSEXP_FMT_CANON
,
1031 rc
= GPG_ERR_ENOMEM
;
1033 gcry_sexp_release(tmp_sexp
);
1040 pthread_cleanup_pop(0); // enc_xml
1043 gcry_sexp_release(sig_sexp
);
1046 pthread_cleanup_pop(1); // key
1047 pthread_cleanup_pop(1); // iv
1050 pthread_cleanup_push(gcry_free
, enc_xml
);
1051 memcpy(data
, grip
, 20);
1052 memcpy(data
+20, sig_grip
, 20);
1053 rc
= write_file(crypto
, filename
, enc_xml
, enc_xml_len
, data
, data_len
);
1054 pthread_cleanup_pop(1); // enc_xml
1057 g_lstat(filename
, &crypto
->st
);
1059 memcpy(&crypto
->hdr
, &crypto
->save
.hdr
, sizeof(file_header_t
));
1067 void cleanup_save(struct save_s
*save
)
1073 gcry_sexp_release(save
->pkey
);
1076 gcry_sexp_release(save
->sigpkey
);
1078 memset(save
, 0, sizeof(struct save_s
));
1081 /* Keep the agent ctx to retain pinentry options which will be freed in
1082 * cleanup_cb(). Also keep .pubkey since it may be needed for a SAVE. */
1083 void cleanup_crypto_stage1(struct crypto_s
*cr
)
1088 cleanup_save(&cr
->save
);
1090 if (cr
->ciphertext_sexp
)
1091 gcry_sexp_release(cr
->ciphertext_sexp
);
1094 gcry_free(cr
->plaintext
);
1096 g_free(cr
->ciphertext
);
1097 g_free(cr
->filename
);
1098 cr
->filename
= NULL
;
1099 cr
->ciphertext_sexp
= NULL
;
1100 cr
->ciphertext
= NULL
;
1101 cr
->ciphertext_len
= 0;
1102 cr
->plaintext
= NULL
;
1103 cr
->plaintext_len
= 0;
1106 void cleanup_crypto_stage2(struct crypto_s
*cr
)
1111 cleanup_crypto_stage1(cr
);
1112 set_header_defaults(&cr
->hdr
);
1115 void cleanup_crypto(struct crypto_s
**c
)
1117 struct crypto_s
*cr
= *c
;
1122 cleanup_crypto_stage2(cr
);
1125 gcry_sexp_release(cr
->pkey_sexp
);
1127 if (cr
->sigpkey_sexp
)
1128 gcry_sexp_release(cr
->sigpkey_sexp
);
1131 cleanup_agent(cr
->agent
);
1137 gpg_error_t
init_client_crypto(struct crypto_s
**crypto
)
1139 struct crypto_s
*new = g_malloc0(sizeof(struct crypto_s
));
1143 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
1144 return GPG_ERR_ENOMEM
;
1147 rc
= agent_init(&new->agent
);
1149 rc
= send_agent_common_options(new->agent
);
1151 rc
= set_pinentry_options(new->agent
);
1159 set_header_defaults(&new->hdr
);
1164 gpg_error_t
generate_key(struct crypto_s
*crypto
, gchar
*sexpstr
,
1165 gboolean empty
, gboolean preset
)
1171 if (crypto
->save
.s2k_count
) {
1172 rc
= send_to_agent(crypto
->agent
, NULL
, NULL
,
1173 "OPTION s2k-count=%lu", crypto
->save
.s2k_count
);
1178 if (!crypto
->agent
->inquire_cb
)
1179 crypto
->agent
->inquire_cb
= inquire_cb
;
1181 rc
= send_to_agent(crypto
->agent
, &pkey
, &plen
, "GENKEY %s%s",
1182 preset
? "--preset " : "",
1183 empty
? "--no-protection" : "");
1187 if (crypto
->save
.pkey
)
1188 gcry_sexp_release(crypto
->save
.pkey
);
1190 crypto
->save
.pkey
= NULL
;
1191 rc
= gcry_sexp_new(&crypto
->save
.pkey
, pkey
, plen
, 1);
1195 gcry_pk_get_keygrip(crypto
->save
.pkey
, grip
);
1196 gchar
*hexgrip
= bin2hex(grip
, sizeof(grip
));
1197 log_write1(_("Keygrip is %s"), hexgrip
);
1200 if (!crypto
->save
.sigpkey
) {
1201 gcry_sexp_build((gcry_sexp_t
*)&crypto
->save
.sigpkey
, NULL
, "%S",
1210 gpg_error_t
set_agent_option(struct agent_s
*agent
, const gchar
*name
,
1213 return send_to_agent(agent
, NULL
, NULL
, "OPTION %s=%s", name
, value
);
1216 gpg_error_t
set_agent_passphrase(struct crypto_s
*crypto
, const gchar
*key
,
1220 struct inquire_data_s idata
;
1224 /* This is for use with key files or passphrases obtained from an inquire.
1225 * gpg-agent uses strings as passphrases and will truncate the passphrase
1226 * at the first encountered null byte. It's only a warning because the
1227 * passphrase may belong to a key shared outside of pwmd. */
1228 for (i
= 0; i
< len
; i
++) {
1230 log_write(_("WARNING: keylen=%i, truncated to %i."), len
, i
);
1235 hexgrip
= bin2hex(crypto
->grip
, 20);
1236 crypto
->agent
->inquire_cb
= inquire_cb
;
1237 crypto
->agent
->inquire_data
= &idata
;
1238 idata
.crypto
= crypto
;
1239 idata
.line
= (gchar
*)key
,
1241 idata
.preset
= TRUE
;
1242 assuan_begin_confidential(crypto
->agent
->ctx
);
1243 rc
= send_to_agent(crypto
->agent
, NULL
, NULL
,
1244 "PRESET_PASSPHRASE --inquire %s -1", hexgrip
);
1245 assuan_end_confidential(crypto
->agent
->ctx
);
1246 idata
.preset
= FALSE
;
1251 gpg_error_t
set_pinentry_mode(struct agent_s
*agent
, const gchar
*mode
)
1253 return set_agent_option(agent
, "pinentry-mode", mode
);
1256 gpg_error_t
get_pubkey_bin(struct crypto_s
*crypto
, const guchar
*grip
,
1257 gcry_sexp_t
*result
)
1259 gchar
*hexgrip
= bin2hex(grip
, 20);
1263 return GPG_ERR_ENOMEM
;
1265 rc
= get_pubkey(crypto
, hexgrip
, result
);
1270 gpg_error_t
get_pubkey(struct crypto_s
*crypto
, const gchar
*grip
,
1271 gcry_sexp_t
*result
)
1277 rc
= send_to_agent(crypto
->agent
, &pkey
, &plen
, "READKEY %s", grip
);
1279 rc
= gcry_sexp_new(result
, pkey
, plen
, 1);
1285 gpg_error_t
set_pinentry_options(struct agent_s
*agent
)
1289 if (getenv("DISPLAY")) {
1290 rc
= set_agent_option(agent
, "display", getenv("DISPLAY"));
1292 g_free(agent
->display
);
1293 agent
->display
= g_strdup(getenv("DISPLAY"));
1296 else if (ttyname(STDOUT_FILENO
)) {
1297 rc
= set_agent_option(agent
, "ttyname", ttyname(STDOUT_FILENO
));
1299 rc
= set_agent_option(agent
, "ttytype", getenv("TERM"));
1301 g_free(agent
->ttyname
);
1302 g_free(agent
->ttytype
);
1303 agent
->ttyname
= g_strdup(ttyname(STDOUT_FILENO
));
1304 agent
->ttytype
= g_strdup(getenv("TERM"));
1312 static gpg_error_t
inquire_keyfile(gpointer user
, const gchar
*keyword
)
1314 struct crypto_s
*crypto
= user
;
1315 gchar
*filename
= crypto
->agent
->inquire_data2
;
1316 gchar
*params
= crypto
->agent
->inquire_data3
;
1323 if (!g_strcmp0(keyword
, "KEYPARAM"))
1324 return assuan_send_data(crypto
->agent
->ctx
, params
, strlen(params
));
1326 // This function is only used when generating a new keypair.
1327 if (g_strcmp0(keyword
, "NEW_PASSPHRASE"))
1328 return gpg_error(GPG_ERR_ASS_UNKNOWN_INQUIRE
);
1330 if (stat(filename
, &st
) == -1)
1331 return gpg_error_from_syserror();
1333 if (crypto
->agent
->inquire_maxlen
1334 && st
.st_size
> crypto
->agent
->inquire_maxlen
) {
1335 log_write(_("The passphrase is too large: have=%u, max=%u."),
1336 (unsigned)st
.st_size
, crypto
->agent
->inquire_maxlen
);
1337 return GPG_ERR_TOO_LARGE
;
1340 buf
= gcry_malloc_secure(st
.st_size
);
1342 return GPG_ERR_ENOMEM
;
1344 fd
= open(filename
, O_RDONLY
);
1346 rc
= gpg_error_from_syserror();
1348 len
= read(fd
, buf
, st
.st_size
);
1349 if (len
== st
.st_size
) {
1350 assuan_begin_confidential(crypto
->agent
->ctx
);
1351 rc
= assuan_send_data(crypto
->agent
->ctx
, buf
, len
);
1352 assuan_end_confidential(crypto
->agent
->ctx
);
1355 rc
= gpg_error_from_syserror();
1357 rc
= GPG_ERR_BUFFER_TOO_SHORT
;
1365 gpg_error_t
export_common(struct crypto_s
*crypto
, const gchar
*hexgrip
,
1366 const gchar
*sign_hexgrip
, gboolean no_passphrase
,
1367 const gpointer data
, gsize datalen
, const gchar
*outfile
,
1368 const gchar
*keyparams
, const gchar
*keyfile
)
1372 if (!sign_hexgrip
&& hexgrip
)
1373 sign_hexgrip
= hexgrip
;
1376 if (crypto
->sigpkey_sexp
)
1377 gcry_sexp_release(crypto
->sigpkey_sexp
);
1379 crypto
->sigpkey_sexp
= NULL
;
1380 rc
= get_pubkey(crypto
, sign_hexgrip
, &crypto
->save
.sigpkey
);
1384 gcry_pk_get_keygrip(crypto
->save
.sigpkey
, crypto
->sign_grip
);
1388 rc
= get_pubkey(crypto
, hexgrip
, &crypto
->save
.pkey
);
1390 gcry_pk_get_keygrip(crypto
->save
.pkey
, crypto
->grip
);
1393 struct inquire_data_s idata
= {0};
1394 gchar
*params
= keyparams
? g_strdup(keyparams
)
1395 : default_key_params(crypto
);
1397 pthread_cleanup_push(g_free
, params
);
1398 log_write(_("Generating a new keypair ..."));
1400 log_write(N_("Using passphrase obtained from file '%s'"), keyfile
);
1401 rc
= set_pinentry_mode(crypto
->agent
, "loopback");
1402 crypto
->agent
->inquire_cb
= inquire_keyfile
;
1403 crypto
->agent
->inquire_data
= crypto
;
1404 crypto
->agent
->inquire_data2
= (gchar
*)keyfile
;
1405 crypto
->agent
->inquire_data3
= params
;
1408 idata
.line
= params
;
1409 idata
.len
= strlen(params
);
1410 idata
.crypto
= crypto
;
1411 crypto
->agent
->inquire_cb
= inquire_cb
;
1412 crypto
->agent
->inquire_data
= &idata
;
1416 rc
= generate_key(crypto
, params
, no_passphrase
, TRUE
);
1417 gcry_pk_get_keygrip(crypto
->save
.pkey
, crypto
->grip
);
1420 (void)set_pinentry_mode(crypto
->agent
, "ask");
1421 pthread_cleanup_pop(1);
1425 rc
= encrypt_data_file(crypto
, crypto
->save
.pkey
, crypto
->save
.sigpkey
,
1426 outfile
, data
, datalen
);
1428 gchar
*tmp
= bin2hex(crypto
->grip
, sizeof(crypto
->grip
));
1430 log_write(_("Success! Keygrip is %s."), tmp
);
1431 rc
= send_to_agent(crypto
->agent
, NULL
, NULL
,
1432 "CLEAR_PASSPHRASE --mode=normal %s", tmp
);
1436 tmp
= bin2hex(crypto
->sign_grip
, sizeof(crypto
->sign_grip
));
1437 log_write(_("Signed with keygrip %s."), tmp
);
1446 gchar
*default_key_params(struct crypto_s
*crypto
)
1448 gint len
= get_key_file_integer(NULL
, "nbits");
1450 gchar
*algo
= get_key_file_string(NULL
, "algo");
1453 g_snprintf(buf
, sizeof(buf
), "%i", len
);
1454 result
= g_strdup_printf("(genkey (%s (nbits %lu:%i)))", algo
, strlen(buf
),
1460 gpg_error_t
agent_passwd(struct crypto_s
*crypto
)
1462 struct inquire_data_s idata
= {0};
1464 gchar
*tmp
= bin2hex(crypto
->grip
, 20);
1466 idata
.crypto
= crypto
;
1467 crypto
->agent
->inquire_cb
= inquire_cb
;
1468 crypto
->agent
->inquire_data
= &idata
;
1469 rc
= send_to_agent(crypto
->agent
, NULL
, NULL
, "PASSWD --preset %s", tmp
);