From 69930f6884a934207f7aa523cf6d2b8e22dfe666 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 8 Nov 2018 20:52:38 +0900 Subject: gpgcompose: Fix --sk-esk. * g10/gpgcompose.c (sk_esk): Copy the result content correctly. Don't forget to free the result. -- Fixes-commit: 0131d4369a81a51bf7bb328cc81a3bb082ed1a94 Signed-off-by: NIIBE Yutaka --- g10/gpgcompose.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'g10/gpgcompose.c') diff --git a/g10/gpgcompose.c b/g10/gpgcompose.c index b3f7ecdce..9b6901599 100644 --- a/g10/gpgcompose.c +++ b/g10/gpgcompose.c @@ -2281,16 +2281,27 @@ sk_esk (const char *option, int argc, char *argv[], void *cookie) /* Encrypt the session key using the s2k specifier. */ { DEK *sesdekp = &sesdek; + void *enckey; + size_t enckeylen; /* Now encrypt the session key (or rather, the algorithm used to - encrypt the SKESK plus the session key) using ENCKEY. */ - err = encrypt_seskey (&s2kdek, 0, &sesdekp, - (void**)&ske->seskey, (size_t *)&ske->seskeylen); + encrypt the SKESK plus the session key) using S2KDEK. */ + err = encrypt_seskey (&s2kdek, 0, &sesdekp, &enckey, &enckeylen); + if (err) log_fatal ("encrypt_seskey failed: %s\n", gpg_strerror (err)); + if (enckeylen - 1 > sesdek.keylen) + log_fatal ("key size is too big: %z\n", enckeylen); + else + { + ske->seskeylen = (byte)enckeylen; + memcpy (ske->seskey, enckey, enckeylen); + } + /* Save the session key for later. */ session_key = sesdek; + xfree (enckey); } pkt.pkttype = PKT_SYMKEY_ENC; -- cgit From bbed4746edcd20946ef9f90d25a69c151238de0a Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sun, 11 Nov 2018 12:20:34 +0100 Subject: gpg: Fix format string in gpgcompose.c -- For size_t use "%zu" For ssize_t use "%zd" Signed-off-by: Werner Koch --- g10/gpgcompose.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'g10/gpgcompose.c') diff --git a/g10/gpgcompose.c b/g10/gpgcompose.c index 9b6901599..6f573ce46 100644 --- a/g10/gpgcompose.c +++ b/g10/gpgcompose.c @@ -2292,7 +2292,7 @@ sk_esk (const char *option, int argc, char *argv[], void *cookie) log_fatal ("encrypt_seskey failed: %s\n", gpg_strerror (err)); if (enckeylen - 1 > sesdek.keylen) - log_fatal ("key size is too big: %z\n", enckeylen); + log_fatal ("key size is too big: %zu\n", enckeylen); else { ske->seskeylen = (byte)enckeylen; -- cgit From ec13b1c562e34c0fcbc7b848ab6dc187b79cf2c1 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sat, 26 Jan 2019 23:10:38 +0100 Subject: gpg: Move S2K encoding function to a shared file. * g10/passphrase.c (encode_s2k_iterations): Move function to ... * common/openpgp-s2k.c: new file. Remove default intialization code. * common/openpgpdefs.h (S2K_DECODE_COUNT): New to keep only one copy. * g10/call-agent.c (agent_get_s2k_count): Change to return the count and print an error. * agent/protect.c: Include openpgpdefs.h * g10/card-util.c (gen_kdf_data): Adjust for changes * g10/gpgcompose.c: Include call-agent.h. (sk_esk): Adjust for changes. * g10/passphrase (passphrase_to_dek): Adjust for changes. * g10/main.h (S2K_DECODE_COUNT): Remove macro. Signed-off-by: Werner Koch --- agent/protect.c | 4 +--- common/Makefile.am | 2 +- common/openpgp-s2k.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ common/openpgpdefs.h | 10 ++++++++ common/ttyio.c | 2 ++ g10/call-agent.c | 26 ++++++++++++++------ g10/call-agent.h | 2 +- g10/card-util.c | 2 +- g10/gpgcompose.c | 10 +++++--- g10/keydb.h | 1 - g10/main.h | 2 -- g10/passphrase.c | 54 ++---------------------------------------- 12 files changed, 111 insertions(+), 71 deletions(-) create mode 100644 common/openpgp-s2k.c (limited to 'g10/gpgcompose.c') diff --git a/agent/protect.c b/agent/protect.c index f95527f78..eda247f27 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -41,6 +41,7 @@ #include "cvt-openpgp.h" #include "../common/sexp-parse.h" +#include "../common/openpgpdefs.h" /* For s2k functions. */ /* The protection mode for encryption. The supported modes for @@ -49,9 +50,6 @@ #define PROT_CIPHER_STRING "aes" #define PROT_CIPHER_KEYLEN (128/8) -/* Decode an rfc4880 encoded S2K count. */ -#define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6)) - /* A table containing the information needed to create a protected private key. */ diff --git a/common/Makefile.am b/common/Makefile.am index d288fa36b..b6a6605f1 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -83,7 +83,7 @@ common_sources = \ localename.c \ session-env.c session-env.h \ userids.c userids.h \ - openpgp-oid.c \ + openpgp-oid.c openpgp-s2k.c \ ssh-utils.c ssh-utils.h \ agent-opt.c \ helpfile.c \ diff --git a/common/openpgp-s2k.c b/common/openpgp-s2k.c new file mode 100644 index 000000000..2b0ba604b --- /dev/null +++ b/common/openpgp-s2k.c @@ -0,0 +1,67 @@ +/* openpgp-s2ks.c - OpenPGP S2K helper functions + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005, 2006 Free Software Foundation, Inc. + * Copyright (C) 2010, 2019 g10 Code GmbH + * + * This file is part of GnuPG. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either + * + * - the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * or + * + * - the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * or both in parallel, as here. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "util.h" +#include "openpgpdefs.h" + + +/* Pack an s2k iteration count into the form specified in RFC-48800. + * If we're in between valid values, round up. */ +unsigned char +encode_s2k_iterations (int iterations) +{ + unsigned char c=0; + unsigned char result; + unsigned int count; + + if (iterations <= 1024) + return 0; /* Command line arg compatibility. */ + + if (iterations >= 65011712) + return 255; + + /* Need count to be in the range 16-31 */ + for (count=iterations>>6; count>=32; count>>=1) + c++; + + result = (c<<4)|(count-16); + + if (S2K_DECODE_COUNT(result) < iterations) + result++; + + return result; +} diff --git a/common/openpgpdefs.h b/common/openpgpdefs.h index 8699a178d..aadda434b 100644 --- a/common/openpgpdefs.h +++ b/common/openpgpdefs.h @@ -197,4 +197,14 @@ typedef enum compress_algo_t; + + +/* Decode an rfc4880 encoded S2K count. */ +#define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6)) + + +/*--openpgp-s2k.c --*/ +unsigned char encode_s2k_iterations (int iterations); + + #endif /*GNUPG_COMMON_OPENPGPDEFS_H*/ diff --git a/common/ttyio.c b/common/ttyio.c index c7c9d85ab..374b9f38a 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -564,6 +564,8 @@ do_get( const char *prompt, int hidden ) } + +/* Note: This function never returns NULL. */ char * tty_get( const char *prompt ) { diff --git a/g10/call-agent.c b/g10/call-agent.c index c958b84b7..91af2be39 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -1461,19 +1461,19 @@ gpg_agent_get_confirmation (const char *desc) } -/* Return the S2K iteration count as computed by gpg-agent. */ -gpg_error_t -agent_get_s2k_count (unsigned long *r_count) +/* Return the S2K iteration count as computed by gpg-agent. On error + * print a warning and return a default value. */ +unsigned long +agent_get_s2k_count (void) { gpg_error_t err; membuf_t data; char *buf; - - *r_count = 0; + unsigned long count = 0; err = start_agent (NULL, 0); if (err) - return err; + goto leave; init_membuf (&data, 32); err = assuan_transact (agent_ctx, "GETINFO s2k_count", @@ -1489,10 +1489,22 @@ agent_get_s2k_count (unsigned long *r_count) err = gpg_error_from_syserror (); else { - *r_count = strtoul (buf, NULL, 10); + count = strtoul (buf, NULL, 10); xfree (buf); } } + + leave: + if (err || count < 65536) + { + /* Don't print an error if an older agent is used. */ + if (err && gpg_err_code (err) != GPG_ERR_ASS_PARAMETER) + log_error (_("problem with the agent: %s\n"), gpg_strerror (err)); + + /* Default to 65536 which was used up to 2.0.13. */ + return 65536; + } + return err; } diff --git a/g10/call-agent.h b/g10/call-agent.h index 8ea8ffea6..8619a34f8 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -146,7 +146,7 @@ gpg_error_t agent_clear_passphrase (const char *cache_id); gpg_error_t gpg_agent_get_confirmation (const char *desc); /* Return the S2K iteration count as computed by gpg-agent. */ -gpg_error_t agent_get_s2k_count (unsigned long *r_count); +unsigned long agent_get_s2k_count (void); /* Check whether a secret key for public key PK is available. Returns 0 if the secret key is available. */ diff --git a/g10/card-util.c b/g10/card-util.c index eca248433..08844bae3 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -2039,7 +2039,7 @@ gen_kdf_data (unsigned char *data, int single_salt) p = data; - s2k_char = encode_s2k_iterations (0); + s2k_char = encode_s2k_iterations (agent_get_s2k_count ()); iterations = S2K_DECODE_COUNT (s2k_char); count_4byte[0] = (iterations >> 24) & 0xff; count_4byte[1] = (iterations >> 16) & 0xff; diff --git a/g10/gpgcompose.c b/g10/gpgcompose.c index 6f573ce46..5c0857590 100644 --- a/g10/gpgcompose.c +++ b/g10/gpgcompose.c @@ -25,6 +25,7 @@ #include "keydb.h" #include "main.h" #include "options.h" +#include "call-agent.h" static int do_debug; #define debug(fmt, ...) \ @@ -2248,9 +2249,12 @@ sk_esk (const char *option, int argc, char *argv[], void *cookie) log_assert (sizeof (si.salt) == sizeof (ske->s2k.salt)); memcpy (ske->s2k.salt, si.salt, sizeof (ske->s2k.salt)); if (! si.s2k_is_session_key) - /* 0 means get the default. */ - ske->s2k.count = encode_s2k_iterations (si.iterations); - + { + if (!si.iterations) + ske->s2k.count = encode_s2k_iterations (agent_get_s2k_count ()); + else + ske->s2k.count = encode_s2k_iterations (si.iterations); + } /* Derive the symmetric key that is either the session key or the key used to encrypt the session key. */ diff --git a/g10/keydb.h b/g10/keydb.h index 1def2bb81..acb424455 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -276,7 +276,6 @@ gpg_error_t build_sk_list (ctrl_t ctrl, strlist_t locusr, SK_LIST *ret_sk_list, unsigned use); /*-- passphrase.h --*/ -unsigned char encode_s2k_iterations (int iterations); int have_static_passphrase(void); const char *get_static_passphrase (void); void set_passphrase_from_string(const char *pass); diff --git a/g10/main.h b/g10/main.h index 86f8589b2..867f6975b 100644 --- a/g10/main.h +++ b/g10/main.h @@ -507,8 +507,6 @@ gpg_error_t card_generate_subkey (ctrl_t ctrl, kbnode_t pub_keyblock); int card_store_subkey (KBNODE node, int use); #endif -#define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6)) - /*-- migrate.c --*/ void migrate_secring (ctrl_t ctrl); diff --git a/g10/passphrase.c b/g10/passphrase.c index 10574ec6a..99a2c0dc2 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -48,57 +48,6 @@ static char *next_pw = NULL; static char *last_pw = NULL; - -/* Pack an s2k iteration count into the form specified in 2440. If - we're in between valid values, round up. With value 0 return the - old default. */ -unsigned char -encode_s2k_iterations (int iterations) -{ - gpg_error_t err; - unsigned char c=0; - unsigned char result; - unsigned int count; - - if (!iterations) - { - unsigned long mycnt; - - /* Ask the gpg-agent for a useful iteration count. */ - err = agent_get_s2k_count (&mycnt); - if (err || mycnt < 65536) - { - /* Don't print an error if an older agent is used. */ - if (err && gpg_err_code (err) != GPG_ERR_ASS_PARAMETER) - log_error (_("problem with the agent: %s\n"), gpg_strerror (err)); - /* Default to 65536 which we used up to 2.0.13. */ - return 96; - } - else if (mycnt >= 65011712) - return 255; /* Largest possible value. */ - else - return encode_s2k_iterations ((int)mycnt); - } - - if (iterations <= 1024) - return 0; /* Command line arg compatibility. */ - - if (iterations >= 65011712) - return 255; - - /* Need count to be in the range 16-31 */ - for (count=iterations>>6; count>=32; count>>=1) - c++; - - result = (c<<4)|(count-16); - - if (S2K_DECODE_COUNT(result) < iterations) - result++; - - return result; -} - - int have_static_passphrase() { @@ -106,6 +55,7 @@ have_static_passphrase() && (opt.batch || opt.pinentry_mode == PINENTRY_MODE_LOOPBACK)); } + /* Return a static passphrase. The returned value is only valid as long as no other passphrase related function is called. NULL may be returned if no passphrase has been set; better use @@ -342,7 +292,7 @@ passphrase_to_dek (int cipher_algo, STRING2KEY *s2k, call out to gpg-agent and that should not be done during option processing in main(). */ if (!opt.s2k_count) - opt.s2k_count = encode_s2k_iterations (0); + opt.s2k_count = encode_s2k_iterations (agent_get_s2k_count ()); s2k->count = opt.s2k_count; } } -- cgit From f64477db86568bdc28c313bfeb8b95d8edf05a3c Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 15 Mar 2019 19:11:32 +0100 Subject: gpg: During secret key import print "sec" instead of "pub". * g10/keyedit.c (show_basic_key_info): New arg 'print_sec'. Remove useless code for "sub" and "ssb". * g10/import.c (import_one): Pass FROM_SK to show_basic_key_info. Do not print the first keyinfo in FROM_SK mode. printing. -- Signed-off-by: Werner Koch --- g10/gpgcompose.c | 5 +++-- g10/import.c | 11 +++++++---- g10/keyedit.c | 23 ++++++++++++++--------- g10/keyedit.h | 2 +- 4 files changed, 25 insertions(+), 16 deletions(-) (limited to 'g10/gpgcompose.c') diff --git a/g10/gpgcompose.c b/g10/gpgcompose.c index 5c0857590..e882fa8e3 100644 --- a/g10/gpgcompose.c +++ b/g10/gpgcompose.c @@ -3075,10 +3075,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, } void -show_basic_key_info (ctrl_t ctrl, KBNODE keyblock) +show_basic_key_info (ctrl_t ctrl, KBNODE keyblock, int made_from_sec) { (void)ctrl; - (void) keyblock; + (void)keyblock; + (void)made_from_sec; } int diff --git a/g10/import.c b/g10/import.c index 25c9a6632..359a14e20 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1666,7 +1666,8 @@ update_key_origin (kbnode_t keyblock, u32 curtime, int origin, const char *url) * the internal errorcount, so that invalid input can be detected by * programs which called gpg. If SILENT is no messages are printed - * even most error messages are suppressed. ORIGIN is the origin of - * the key (0 for unknown) and URL the corresponding URL. + * the key (0 for unknown) and URL the corresponding URL. FROM_SK + * indicates that the key has been made from a secret key. */ static gpg_error_t import_one (ctrl_t ctrl, @@ -1710,9 +1711,11 @@ import_one (ctrl_t ctrl, keyid_from_pk( pk, keyid ); uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); - if (opt.verbose && !opt.interactive && !silent) + if (opt.verbose && !opt.interactive && !silent && !from_sk) { - log_info( "pub %s/%s %s ", + /* Note that we do not print this info in FROM_SK mode + * because import_one already printed that. */ + log_info ("pub %s/%s %s ", pubkey_string (pk, pkstrbuf, sizeof pkstrbuf), keystr_from_pk(pk), datestr_from_pk(pk) ); if (uidnode) @@ -1745,7 +1748,7 @@ import_one (ctrl_t ctrl, print_import_check (pk, uidnode->pkt->pkt.user_id); merge_keys_and_selfsig (ctrl, keyblock); tty_printf ("\n"); - show_basic_key_info (ctrl, keyblock); + show_basic_key_info (ctrl, keyblock, from_sk); tty_printf ("\n"); if (!cpr_get_answer_is_yes ("import.okay", "Do you want to import this key? (y/N) ")) diff --git a/g10/keyedit.c b/g10/keyedit.c index 34b7679e4..4ec6ce503 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -3677,13 +3677,14 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp, /* Display basic key information. This function is suitable to show - information on the key without any dependencies on the trustdb or - any other internal GnuPG stuff. KEYBLOCK may either be a public or - a secret key. This function may be called with KEYBLOCK containing - secret keys and thus the printing of "pub" vs. "sec" does only - depend on the packet type and not by checking with gpg-agent. */ + * information on the key without any dependencies on the trustdb or + * any other internal GnuPG stuff. KEYBLOCK may either be a public or + * a secret key. This function may be called with KEYBLOCK containing + * secret keys and thus the printing of "pub" vs. "sec" does only + * depend on the packet type and not by checking with gpg-agent. If + * PRINT_SEC ist set "sec" is printed instead of "pub". */ void -show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock) +show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock, int print_sec) { KBNODE node; int i; @@ -3696,13 +3697,17 @@ show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock) || node->pkt->pkttype == PKT_SECRET_KEY) { PKT_public_key *pk = node->pkt->pkt.public_key; + const char *tag; + + if (node->pkt->pkttype == PKT_SECRET_KEY || print_sec) + tag = "sec"; + else + tag = "pub"; /* Note, we use the same format string as in other show functions to make the translation job easier. */ tty_printf ("%s %s/%s ", - node->pkt->pkttype == PKT_PUBLIC_KEY ? "pub" : - node->pkt->pkttype == PKT_PUBLIC_SUBKEY ? "sub" : - node->pkt->pkttype == PKT_SECRET_KEY ? "sec" :"ssb", + tag, pubkey_string (pk, pkstrbuf, sizeof pkstrbuf), keystr_from_pk (pk)); tty_printf (_("created: %s"), datestr_from_pk (pk)); diff --git a/g10/keyedit.h b/g10/keyedit.h index d1f453a6f..af5e99664 100644 --- a/g10/keyedit.h +++ b/g10/keyedit.h @@ -50,7 +50,7 @@ void keyedit_quick_set_expire (ctrl_t ctrl, char **subkeyfprs); void keyedit_quick_set_primary (ctrl_t ctrl, const char *username, const char *primaryuid); -void show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock); +void show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock, int print_sec); int keyedit_print_one_sig (ctrl_t ctrl, estream_t fp, int rc, kbnode_t keyblock, kbnode_t node, int *inv_sigs, int *no_key, -- cgit