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/>.
27 #include <sys/types.h>
37 #include "pwmd-error.h"
38 #include "util-misc.h"
43 #include "util-string.h"
51 mem_realloc_cb (void *data
, const void *buffer
, size_t len
)
53 membuf_t
*mem
= (membuf_t
*) data
;
59 if ((p
= xrealloc (mem
->buf
, mem
->len
+ len
)) == NULL
)
63 memcpy ((char *) mem
->buf
+ mem
->len
, buffer
, len
);
69 status_cb (void *data
, const char *line
)
71 struct agent_s
*agent
= data
;
73 agent
->inquire_maxlen
= 0;
75 if (!strncmp (line
, "INQUIRE_MAXLEN ", 15))
77 agent
->inquire_maxlen
= atoi (line
+ 15);
78 if (!agent
->client_ctx
)
82 return send_status (agent
->client_ctx
, STATUS_AGENT
, "%s", line
);
86 assuan_command (struct agent_s
*a
, char **result
,
87 size_t * len
, const char *cmd
)
98 rc
= assuan_transact (a
->ctx
, cmd
, mem_realloc_cb
, &a
->data
,
99 a
->inquire_cb
, a
->inquire_data
, status_cb
, a
);
106 mem_realloc_cb (&a
->data
, "", 1);
108 *result
= (char *) a
->data
.buf
;
120 /* This commands are sent from launch_agent() after reconnecting to the agent
121 * and also from the initial client connection. */
123 send_agent_common_options (struct agent_s
*agent
)
127 rc
= send_to_agent (agent
, NULL
, NULL
, "OPTION cache-ttl-opt-preset=-1");
132 launch_agent (struct agent_s
*agent
)
135 assuan_context_t ctx
= NULL
;
136 const char *t
= NULL
;
137 static struct assuan_malloc_hooks mhooks
= { xmalloc
, xrealloc
, xfree
};
138 char *s
, buf
[LINE_MAX
];
141 s
= config_get_string ("global", "agent_env_file");
144 char *ss
= expand_homedir (s
);
147 fp
= fopen (ss
, "r");
152 while ((p
= fgets (buf
, sizeof (buf
), fp
)))
155 if (!strncmp (p
, "GPG_AGENT_INFO=", strlen ("GPG_AGENT_INFO=")))
157 setenv ("GPG_AGENT_INFO", p
+ strlen ("GPG_AGENT_INFO="),
166 log_write ("%s: %s", s
, pwmd_strerror (gpg_error_from_syserror ()));
171 t
= getenv ("GPG_AGENT_INFO");
173 return gpg_error (GPG_ERR_NO_AGENT
);
175 rc
= assuan_new_ext (&ctx
, GPG_ERR_SOURCE_DEFAULT
, &mhooks
,
176 debug_level
? assuan_log_cb
: NULL
, "AGENT ");
180 char **fields
= str_split (t
, ":", 0);
181 rc
= assuan_socket_connect (ctx
, fields
[0], ASSUAN_INVALID_PID
, 0);
186 assuan_release (ctx
);
191 assuan_release (agent
->ctx
);
194 rc
= send_agent_common_options (agent
);
195 if (!rc
&& agent
->pinentry_opts
.display
)
196 rc
= set_agent_option (agent
, "display", agent
->pinentry_opts
.display
);
198 if (!rc
&& agent
->pinentry_opts
.ttyname
)
199 rc
= set_agent_option (agent
, "ttyname", agent
->pinentry_opts
.ttyname
);
201 if (!rc
&& agent
->pinentry_opts
.ttytype
)
202 rc
= set_agent_option (agent
, "ttytype", agent
->pinentry_opts
.ttytype
);
204 if (!rc
&& agent
->pinentry_opts
.lc_messages
)
205 rc
= set_agent_option (agent
, "lc-messages",
206 agent
->pinentry_opts
.lc_messages
);
208 if (!rc
&& agent
->pinentry_opts
.lc_ctype
)
209 rc
= set_agent_option (agent
, "lc-ctype", agent
->pinentry_opts
.lc_ctype
);
215 send_to_agent (struct agent_s
* agent
, char **result
, size_t * len
,
216 const char *fmt
, ...)
224 rc
= launch_agent (agent
);
230 if (str_vasprintf (&cmd
, fmt
, ap
) > 0)
232 rc
= assuan_command (agent
, result
, len
, cmd
);
233 if (!agent
->restart
&& gpg_err_source (rc
) == GPG_ERR_SOURCE_DEFAULT
234 && (gpg_err_code (rc
) == GPG_ERR_ASS_CONNECT_FAILED
235 || gpg_err_code (rc
) == GPG_ERR_EPIPE
))
237 unsetenv ("GPG_AGENT_INFO");
239 rc
= launch_agent (agent
);
241 rc
= assuan_command (agent
, result
, len
, cmd
);
255 agent_disconnect (struct agent_s
*agent
)
261 assuan_release (agent
->ctx
);
267 cleanup_agent (struct agent_s
*agent
)
272 pinentry_free_opts (&agent
->pinentry_opts
);
273 agent_disconnect (agent
);
278 agent_init (struct agent_s
**agent
)
280 struct agent_s
*new = xcalloc (1, sizeof (struct agent_s
));
283 return GPG_ERR_ENOMEM
;
290 inquire_cb (void *user
, const char *keyword
)
292 struct inquire_data_s
*idata
= user
;
294 if (!idata
->preset
&& (!strcmp (keyword
, "PASSPHRASE")
295 || !strcmp (keyword
, "NEW_PASSPHRASE")))
297 return agent_loopback_cb (idata
->crypto
, keyword
);
299 // SAVE --inquire-keyparam
300 else if (idata
->preset
&& !strcmp (keyword
, "KEYPARAM"))
303 return agent_loopback_cb (idata
->crypto
, keyword
);
306 if (idata
->crypto
->agent
->inquire_maxlen
307 && idata
->len
> idata
->crypto
->agent
->inquire_maxlen
)
309 log_write (_("Inquired data too large: have=%u, max=%u"), idata
->len
,
310 idata
->crypto
->agent
->inquire_maxlen
);
311 return GPG_ERR_TOO_LARGE
;
314 idata
->crypto
->agent
->inquire_maxlen
= 0;
315 return assuan_send_data (idata
->crypto
->agent
->ctx
, idata
->line
,
320 agent_extract_key (struct crypto_s
*crypto
, unsigned char **result
,
324 gcry_sexp_t enc_sexp
= NULL
, tmp_sexp
;
325 struct inquire_data_s idata
= { 0 };
326 char *hexgrip
= NULL
;
328 size_t keylen
, keysize
;
330 int algo
= cipher_to_gcrypt (crypto
->hdr
.flags
);
333 rc
= gcry_cipher_algo_info (algo
, GCRYCTL_GET_KEYLEN
, NULL
, &keysize
);
337 tmp_sexp
= gcry_sexp_find_token (crypto
->ciphertext_sexp
, "enc-val", 0);
339 return GPG_ERR_BAD_DATA
;
341 hexgrip
= bin2hex (crypto
->grip
, sizeof (crypto
->grip
));
348 rc
= cache_is_shadowed (hexgrip
);
349 if (rc
&& rc
!= GPG_ERR_NO_DATA
)
352 shadowed
= !rc
? 1 : 0;
355 gcry_sexp_t tmp2_sexp
= gcry_sexp_cdr (tmp_sexp
);
356 gcry_sexp_release (tmp_sexp
);
357 tmp_sexp
= gcry_sexp_nth (tmp2_sexp
, 0);
358 gcry_sexp_release (tmp2_sexp
);
359 rc
= gcry_sexp_build (&enc_sexp
, NULL
, "(enc-val (flags pkcs1) %S)",
363 rc
= gcry_sexp_build (&enc_sexp
, NULL
, "%S", tmp_sexp
);
365 gcry_sexp_release (tmp_sexp
);
369 crypto
->agent
->inquire_cb
= inquire_cb
;
370 idata
.crypto
= crypto
;
371 idata
.len
= gcry_sexp_sprint (enc_sexp
, GCRYSEXP_FMT_CANON
, NULL
, 0);
372 idata
.line
= xmalloc (idata
.len
);
379 idata
.len
= gcry_sexp_sprint (enc_sexp
, GCRYSEXP_FMT_CANON
, idata
.line
,
381 crypto
->agent
->inquire_data
= &idata
;
382 gcry_sexp_release (enc_sexp
);
384 log_write1 (_("Keygrip is %s, bits=%i"), hexgrip
,
385 gcry_pk_get_nbits (crypto
->pkey_sexp
));
386 rc
= send_to_agent (crypto
->agent
, NULL
, NULL
, "SETKEY %s", hexgrip
);
390 if (!crypto
->agent
->pinentry_opts
.desc
)
394 ("A %s is required to unlock the secret key for the "
395 "encrypted data file \"%s\". Please enter the %s "
396 "below."), shadowed
? "PIN" : _("passphrase"),
397 crypto
->filename
, shadowed
? "PIN" : _("passphrase"));
400 tmp
= plus_escape (crypto
->agent
->pinentry_opts
.desc
);
402 rc
= send_to_agent (crypto
->agent
, NULL
, NULL
, "SETKEYDESC %s", tmp
);
407 assuan_begin_confidential (crypto
->agent
->ctx
);
408 rc
= send_to_agent (crypto
->agent
, &key
, &keylen
, "PKDECRYPT");
409 assuan_end_confidential (crypto
->agent
->ctx
);
413 rc
= gcry_sexp_new (&tmp_sexp
, key
, keylen
, 1);
418 key
= (char *) gcry_sexp_nth_data (tmp_sexp
, 1, result_len
);
421 *result
= gcry_malloc (*result_len
);
425 memcpy (*result
, key
, *result_len
);
428 rc
= GPG_ERR_BAD_DATA
;
430 gcry_sexp_release (tmp_sexp
);
437 gcry_sexp_release (enc_sexp
);
443 agent_verify (gcry_sexp_t pkey
, gcry_sexp_t sig_sexp
, const void *data
, size_t len
)
446 unsigned hashlen
= gcry_md_get_algo_dlen (GCRY_MD_SHA256
);
448 gcry_sexp_t data_sexp
;
450 hash
= gcry_malloc (hashlen
);
452 return GPG_ERR_ENOMEM
;
454 gcry_md_hash_buffer (GCRY_MD_SHA256
, hash
, data
, len
);
455 rc
= gcry_sexp_build (&data_sexp
, NULL
,
456 "(data (flags pkcs1) (hash sha256 %b))", hashlen
,
461 rc
= gcry_pk_verify (sig_sexp
, data_sexp
, pkey
);
462 gcry_sexp_release (data_sexp
);
469 agent_loopback_cb (void *user
, const char *keyword
)
471 struct crypto_s
*crypto
= user
;
473 unsigned char *result
;
477 if (!strcmp (keyword
, "KEYPARAM"))
480 rc
= assuan_inquire (crypto
->client_ctx
, keyword
, &result
, &len
, 0);
483 { // PASSPHRASE or NEW_PASSPHRASE
484 assuan_begin_confidential (crypto
->client_ctx
);
485 rc
= assuan_inquire (crypto
->client_ctx
, keyword
, &result
, &len
, 0);
486 assuan_end_confidential (crypto
->client_ctx
);
491 if (keyparam
&& !len
)
493 char *tmp
= default_key_params (crypto
);
496 return gpg_error (GPG_ERR_ENOMEM
);
499 result
= xmalloc (len
);
500 memcpy (result
, tmp
, len
);
504 pthread_cleanup_push (xfree
, result
);
507 rc
= assuan_send_data (crypto
->agent
->ctx
, result
, len
);
510 assuan_begin_confidential (crypto
->agent
->ctx
);
511 rc
= assuan_send_data (crypto
->agent
->ctx
, result
, len
);
512 assuan_end_confidential (crypto
->agent
->ctx
);
515 pthread_cleanup_pop (1);
517 else if (gpg_err_code (rc
) == GPG_ERR_ASS_CANCELED
)
519 gpg_error_t arc
= assuan_write_line (crypto
->agent
->ctx
, "CAN");
526 arc
= assuan_read_line (crypto
->agent
->ctx
, &line
, &len
);
538 sign (gcry_sexp_t
* rsexp
, const char *sign_hexgrip
,
539 struct crypto_s
*crypto
, const void *data
, size_t len
)
543 char *tmp
= sign_hexgrip
? str_dup (sign_hexgrip
)
544 : bin2hex (crypto
->grip
, sizeof (crypto
->grip
));
546 pthread_cleanup_push (xfree
, tmp
);
547 log_write1 (_("Signed with keygrip %s"), tmp
);
548 rc
= send_to_agent (crypto
->agent
, NULL
, NULL
, "SIGKEY %s", tmp
);
549 pthread_cleanup_pop (1);
553 unsigned hashlen
= gcry_md_get_algo_dlen (GCRY_MD_SHA256
);
555 hash
= gcry_malloc (hashlen
);
557 return GPG_ERR_ENOMEM
;
559 gcry_md_hash_buffer (GCRY_MD_SHA256
, hash
, data
, len
);
560 tmp
= bin2hex (hash
, hashlen
);
562 pthread_cleanup_push (xfree
, tmp
);
563 rc
= send_to_agent (crypto
->agent
, NULL
, NULL
,
564 "SETHASH --hash=sha256 %s", tmp
);
565 pthread_cleanup_pop (1);
570 struct inquire_data_s idata
= { 0 };
572 idata
.crypto
= crypto
;
573 crypto
->agent
->inquire_data
= &idata
;
574 crypto
->agent
->inquire_cb
= inquire_cb
;
575 rc
= send_to_agent (crypto
->agent
, &result
, &len
, "PKSIGN");
578 rc
= gcry_sexp_sscan (rsexp
, NULL
, result
, len
);
587 encrypt_data_file (assuan_context_t ctx
, struct crypto_s
* crypto
,
588 gcry_sexp_t pubkey
, gcry_sexp_t sigpkey
,
589 const char *filename
, const void *xml
, size_t len
)
594 void *enc_xml
= NULL
;
595 size_t enc_xml_len
= 0;
596 unsigned char *iv
= NULL
;
598 int algo
= cipher_to_gcrypt (crypto
->save
.hdr
.flags
);
601 unsigned char sig_grip
[20];
602 unsigned char grip
[20];
604 rc
= gcry_cipher_algo_info (algo
, GCRYCTL_GET_KEYLEN
, NULL
, &keysize
);
608 pthread_cleanup_push (gcry_free
, key
);
609 key
= gcry_random_bytes_secure (keysize
, GCRY_STRONG_RANDOM
);
610 #ifdef HAVE_PTHREAD_TESTCANCEL
611 pthread_testcancel (); // may have been a long operation
613 pthread_cleanup_pop (0);
615 return GPG_ERR_ENOMEM
;
617 gcry_pk_get_keygrip (pubkey
, grip
);
618 gcry_pk_get_keygrip (sigpkey
, sig_grip
);
619 pthread_cleanup_push (xfree
, iv
);
620 pthread_cleanup_push (gcry_free
, key
);
621 rc
= encrypt_xml (ctx
, key
, keysize
, algo
, xml
, len
, &enc_xml
, &enc_xml_len
,
622 &iv
, &iv_len
, crypto
->save
.hdr
.iterations
);
625 gcry_sexp_t sig_sexp
= NULL
;
626 char *hexgrip
= bin2hex (grip
, 20);
628 log_write1 (_("Encrypted with keygrip %s"), hexgrip
);
630 hexgrip
= bin2hex (sig_grip
, 20);
631 pthread_cleanup_push (gcry_free
, enc_xml
);
632 rc
= sign (&sig_sexp
, hexgrip
, crypto
, enc_xml
, enc_xml_len
);
637 rc
= agent_verify (sigpkey
, sig_sexp
, enc_xml
, enc_xml_len
);
641 gcry_sexp_t tmp_sexp
;
643 rc
= gcry_sexp_build (&tmp_sexp
, NULL
,
644 "(data (flags pkcs1) (value %b))",
648 gcry_sexp_t key_sexp
;
650 pthread_cleanup_push ((void (*)(void *)) gcry_sexp_release
,
652 rc
= gcry_pk_encrypt (&key_sexp
, tmp_sexp
, pubkey
);
653 pthread_cleanup_pop (0);
654 gcry_sexp_release (tmp_sexp
);
658 memcpy (crypto
->save
.hdr
.iv
, iv
, iv_len
);
659 crypto
->save
.hdr
.datalen
= enc_xml_len
;
660 rc
= gcry_sexp_build (&tmp_sexp
, NULL
, "%S%S", key_sexp
,
662 gcry_sexp_release (key_sexp
);
666 data_len
= gcry_sexp_sprint (tmp_sexp
,
669 data
= xmalloc (data_len
);
671 gcry_sexp_sprint (tmp_sexp
, GCRYSEXP_FMT_CANON
,
676 gcry_sexp_release (tmp_sexp
);
683 pthread_cleanup_pop (0); // enc_xml
686 gcry_sexp_release (sig_sexp
);
689 pthread_cleanup_pop (1); // key
690 pthread_cleanup_pop (1); // iv
694 pthread_cleanup_push (gcry_free
, enc_xml
);
695 rc
= write_file (crypto
, filename
, enc_xml
, enc_xml_len
, data
, data_len
,
697 pthread_cleanup_pop (1); // enc_xml
699 memcpy (&crypto
->hdr
, &crypto
->save
.hdr
, sizeof (file_header_t
));
710 generate_key (struct crypto_s
* crypto
, char *sexpstr
, int empty
, int preset
)
716 if (crypto
->save
.s2k_count
)
718 rc
= send_to_agent (crypto
->agent
, NULL
, NULL
,
719 "OPTION s2k-count=%lu", crypto
->save
.s2k_count
);
724 if (!crypto
->agent
->inquire_cb
)
725 crypto
->agent
->inquire_cb
= inquire_cb
;
727 rc
= send_to_agent (crypto
->agent
, &pkey
, &plen
, "GENKEY %s%s",
728 preset
? "--preset " : "",
729 empty
? "--no-protection" : "");
733 if (crypto
->save
.pkey
)
734 gcry_sexp_release (crypto
->save
.pkey
);
736 crypto
->save
.pkey
= NULL
;
737 rc
= gcry_sexp_new (&crypto
->save
.pkey
, pkey
, plen
, 1);
740 unsigned char grip
[20];
742 gcry_pk_get_keygrip (crypto
->save
.pkey
, grip
);
743 char *hexgrip
= bin2hex (grip
, sizeof (grip
));
744 log_write1 (_("Keygrip is %s"), hexgrip
);
747 if (!crypto
->save
.sigpkey
)
749 gcry_sexp_build ((gcry_sexp_t
*) & crypto
->save
.sigpkey
, NULL
, "%S",
759 set_agent_option (struct agent_s
* agent
, const char *name
, const char *value
)
761 return send_to_agent (agent
, NULL
, NULL
, "OPTION %s=%s", name
, value
);
765 set_agent_passphrase (struct crypto_s
* crypto
, const char *key
, size_t len
)
768 struct inquire_data_s idata
;
772 /* This is for use with key files or passphrases obtained from an inquire.
773 * gpg-agent uses strings as passphrases and will truncate the passphrase
774 * at the first encountered null byte. It's only a warning because the
775 * passphrase may belong to a key shared outside of pwmd. */
776 for (i
= 0; i
< len
; i
++)
780 log_write (_("WARNING: keylen=%i, truncated to %i."), len
, i
);
785 hexgrip
= bin2hex (crypto
->grip
, 20);
786 crypto
->agent
->inquire_cb
= inquire_cb
;
787 crypto
->agent
->inquire_data
= &idata
;
788 idata
.crypto
= crypto
;
789 idata
.line
= (char *) key
, idata
.len
= len
;
791 assuan_begin_confidential (crypto
->agent
->ctx
);
792 rc
= send_to_agent (crypto
->agent
, NULL
, NULL
,
793 "PRESET_PASSPHRASE --inquire %s -1", hexgrip
);
794 assuan_end_confidential (crypto
->agent
->ctx
);
801 set_pinentry_mode (struct agent_s
* agent
, const char *mode
)
803 return set_agent_option (agent
, "pinentry-mode", mode
);
807 get_pubkey_bin (struct crypto_s
* crypto
, const unsigned char *grip
,
808 gcry_sexp_t
* result
)
810 char *hexgrip
= bin2hex (grip
, 20);
814 return GPG_ERR_ENOMEM
;
816 rc
= get_pubkey (crypto
, hexgrip
, result
);
822 get_pubkey (struct crypto_s
* crypto
, const char *grip
, gcry_sexp_t
* result
)
828 rc
= send_to_agent (crypto
->agent
, &pkey
, &plen
, "READKEY %s", grip
);
830 rc
= gcry_sexp_new (result
, pkey
, plen
, 1);
837 agent_set_pinentry_options (struct agent_s
* agent
)
840 struct pinentry_option_s
*opts
= &agent
->pinentry_opts
;
842 if (!opts
->display
&& getenv ("DISPLAY"))
844 rc
= set_agent_option (agent
, "display", getenv ("DISPLAY"));
847 opts
->display
= str_dup (getenv ("DISPLAY"));
850 else if (!opts
->ttyname
&& ttyname (STDOUT_FILENO
))
852 rc
= set_agent_option (agent
, "ttyname", ttyname (STDOUT_FILENO
));
855 rc
= set_agent_option (agent
, "ttytype",
856 opts
->ttytype
? opts
->ttytype
: getenv ("TERM"));
859 xfree (opts
->ttyname
);
860 xfree (opts
->ttytype
);
861 opts
->ttyname
= str_dup (ttyname (STDOUT_FILENO
));
862 opts
->ttytype
= str_dup (getenv ("TERM"));
871 inquire_keyfile (void *user
, const char *keyword
)
873 struct crypto_s
*crypto
= user
;
874 char *filename
= crypto
->agent
->inquire_data2
;
875 char *params
= crypto
->agent
->inquire_data3
;
882 if (!strcmp (keyword
, "KEYPARAM"))
883 return assuan_send_data (crypto
->agent
->ctx
, params
, strlen (params
));
885 // This function is only used when generating a new keypair.
886 if (strcmp (keyword
, "NEW_PASSPHRASE"))
887 return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE
);
889 if (stat (filename
, &st
) == -1)
890 return gpg_error_from_syserror ();
892 if (crypto
->agent
->inquire_maxlen
893 && st
.st_size
> crypto
->agent
->inquire_maxlen
)
895 log_write (_("The passphrase is too large: have=%u, max=%u."),
896 (unsigned) st
.st_size
, crypto
->agent
->inquire_maxlen
);
897 return GPG_ERR_TOO_LARGE
;
900 buf
= gcry_malloc_secure (st
.st_size
);
902 return GPG_ERR_ENOMEM
;
904 fd
= open (filename
, O_RDONLY
);
906 rc
= gpg_error_from_syserror ();
909 len
= read (fd
, buf
, st
.st_size
);
910 if (len
== st
.st_size
)
912 assuan_begin_confidential (crypto
->agent
->ctx
);
913 rc
= assuan_send_data (crypto
->agent
->ctx
, buf
, len
);
914 assuan_end_confidential (crypto
->agent
->ctx
);
917 rc
= gpg_error_from_syserror ();
919 rc
= GPG_ERR_BUFFER_TOO_SHORT
;
928 agent_export_common (struct crypto_s
* crypto
, const char *hexgrip
,
929 const char *sign_hexgrip
, int no_passphrase
,
930 const void *data
, size_t datalen
, const char *outfile
,
931 const char *keyparams
, const char *keyfile
)
935 if (!sign_hexgrip
&& hexgrip
)
936 sign_hexgrip
= hexgrip
;
940 if (crypto
->sigpkey_sexp
)
941 gcry_sexp_release (crypto
->sigpkey_sexp
);
943 crypto
->sigpkey_sexp
= NULL
;
944 rc
= get_pubkey (crypto
, sign_hexgrip
, &crypto
->save
.sigpkey
);
948 gcry_pk_get_keygrip (crypto
->save
.sigpkey
, crypto
->sign_grip
);
953 rc
= get_pubkey (crypto
, hexgrip
, &crypto
->save
.pkey
);
955 gcry_pk_get_keygrip (crypto
->save
.pkey
, crypto
->grip
);
959 struct inquire_data_s idata
= { 0 };
960 char *params
= keyparams
? str_dup (keyparams
)
961 : default_key_params (crypto
);
963 pthread_cleanup_push (xfree
, params
);
964 log_write (_("Generating a new keypair ..."));
967 log_write (_("Using passphrase obtained from file '%s'"), keyfile
);
968 rc
= set_pinentry_mode (crypto
->agent
, "loopback");
969 crypto
->agent
->inquire_cb
= inquire_keyfile
;
970 crypto
->agent
->inquire_data
= crypto
;
971 crypto
->agent
->inquire_data2
= (char *) keyfile
;
972 crypto
->agent
->inquire_data3
= params
;
977 idata
.len
= strlen (params
);
978 idata
.crypto
= crypto
;
979 crypto
->agent
->inquire_cb
= inquire_cb
;
980 crypto
->agent
->inquire_data
= &idata
;
985 rc
= generate_key (crypto
, params
, no_passphrase
, 1);
986 gcry_pk_get_keygrip (crypto
->save
.pkey
, crypto
->grip
);
989 (void) set_pinentry_mode (crypto
->agent
, "ask");
990 pthread_cleanup_pop (1);
995 rc
= encrypt_data_file (NULL
, crypto
, crypto
->save
.pkey
,
996 crypto
->save
.sigpkey
, outfile
, data
, datalen
);
999 char *tmp
= bin2hex (crypto
->grip
, sizeof (crypto
->grip
));
1001 log_write (_("Success! Keygrip is %s."), tmp
);
1002 rc
= send_to_agent (crypto
->agent
, NULL
, NULL
,
1003 "CLEAR_PASSPHRASE --mode=normal %s", tmp
);
1008 tmp
= bin2hex (crypto
->sign_grip
, sizeof (crypto
->sign_grip
));
1009 log_write (_("Signed with keygrip %s."), tmp
);
1019 default_key_params (struct crypto_s
*crypto
)
1021 int len
= config_get_integer (NULL
, "nbits");
1023 char *algo
= config_get_string (NULL
, "algo");
1026 snprintf (buf
, sizeof (buf
), "%i", len
);
1027 result
= str_asprintf ("(genkey (%s (nbits %lu:%i)))", algo
, strlen (buf
),
1034 agent_passwd (struct crypto_s
* crypto
)
1036 struct inquire_data_s idata
= { 0 };
1038 char *tmp
= bin2hex (crypto
->grip
, 20);
1040 idata
.crypto
= crypto
;
1041 crypto
->agent
->inquire_cb
= inquire_cb
;
1042 crypto
->agent
->inquire_data
= &idata
;
1043 rc
= send_to_agent (crypto
->agent
, NULL
, NULL
, "PASSWD --preset %s", tmp
);
1049 kill_scd (struct agent_s
* agent
)
1056 if (config_get_boolean (NULL
, "kill_scd"))
1058 rc
= send_to_agent (agent
, NULL
, NULL
, "SCD KILLSCD");
1059 if (rc
&& gpg_err_code (rc
) != GPG_ERR_NO_SCDAEMON
)
1060 log_write ("%s: %s", __FUNCTION__
, pwmd_strerror (rc
));