summaryrefslogtreecommitdiff
path: root/sm
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2022-09-16 07:44:51 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2022-09-16 07:44:51 +0900
commitc5ff1325db87c374d0a7b3785ff1e1342a0be2ba (patch)
tree054a42ddf0c96da0f09b4b976f9ca5732cd308d3 /sm
parent43b7b348be0a4e502da85f9f372dad3472667777 (diff)
downloadgpg2-c5ff1325db87c374d0a7b3785ff1e1342a0be2ba.tar.gz
gpg2-c5ff1325db87c374d0a7b3785ff1e1342a0be2ba.tar.bz2
gpg2-c5ff1325db87c374d0a7b3785ff1e1342a0be2ba.zip
Imported Upstream version 2.2.28upstream/2.2.28
Diffstat (limited to 'sm')
-rw-r--r--sm/Makefile.in4
-rw-r--r--sm/call-dirmngr.c19
-rw-r--r--sm/certcheck.c1
-rw-r--r--sm/decrypt.c640
-rw-r--r--sm/encrypt.c6
-rw-r--r--sm/export.c4
-rw-r--r--sm/gpgsm.c132
-rw-r--r--sm/gpgsm.h13
-rw-r--r--sm/import.c5
-rw-r--r--sm/keydb.c101
-rw-r--r--sm/keydb.h3
-rw-r--r--sm/minip12.c26
-rw-r--r--sm/minip12.h2
-rw-r--r--sm/server.c25
-rw-r--r--sm/verify.c1
15 files changed, 706 insertions, 276 deletions
diff --git a/sm/Makefile.in b/sm/Makefile.in
index 849efe0..9dd355e 100644
--- a/sm/Makefile.in
+++ b/sm/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index 36afd22..1a411f2 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -198,7 +198,7 @@ warn_version_mismatch (ctrl_t ctrl, assuan_context_t ctx,
static void
prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
{
- struct keyserver_spec *server;
+ strlist_t server;
if (!err)
err = warn_version_mismatch (ctrl, ctx, DIRMNGR_NAME, 0);
@@ -219,12 +219,13 @@ prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
while (server)
{
char line[ASSUAN_LINELENGTH];
- char *user = server->user ? server->user : "";
- char *pass = server->pass ? server->pass : "";
- char *base = server->base ? server->base : "";
- snprintf (line, DIM (line), "LDAPSERVER %s:%i:%s:%s:%s",
- server->host, server->port, user, pass, base);
+ /* If the host is "ldap" we prefix the entire line with "ldap:"
+ * to avoid an ambiguity on the server due to the introduction
+ * of this optional prefix. */
+ snprintf (line, DIM (line), "LDAPSERVER %s%s",
+ !strncmp (server->d, "ldap:", 5)? "ldap:":"",
+ server->d);
assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
/* The code below is not required because we don't return an error. */
@@ -505,6 +506,8 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
struct inq_certificate_parm_s parm;
struct isvalid_status_parm_s stparm;
+ keydb_close_all_files ();
+
rc = start_dirmngr (ctrl);
if (rc)
return rc;
@@ -775,6 +778,8 @@ gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, const char *uri,
if ((names && uri) || (!names && !uri))
return gpg_error (GPG_ERR_INV_ARG);
+ keydb_close_all_files ();
+
/* The lookup function can be invoked from the callback of a lookup
function, for example to walk the chain. */
if (!dirmngr_ctx_locked)
@@ -1043,6 +1048,8 @@ gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
size_t len;
struct run_command_parm_s parm;
+ keydb_close_all_files ();
+
rc = start_dirmngr (ctrl);
if (rc)
return rc;
diff --git a/sm/certcheck.c b/sm/certcheck.c
index 12b3ec9..d6b967c 100644
--- a/sm/certcheck.c
+++ b/sm/certcheck.c
@@ -293,7 +293,6 @@ extract_pss_params (gcry_sexp_t s_sig, int *r_algo, unsigned int *r_saltlen)
if (*r_saltlen < 20)
{
log_error ("length of PSS salt too short\n");
- gcry_sexp_release (s_sig);
return gpg_error (GPG_ERR_DIGEST_ALGO);
}
if (!*r_algo)
diff --git a/sm/decrypt.c b/sm/decrypt.c
index 90eba88..38aa832 100644
--- a/sm/decrypt.c
+++ b/sm/decrypt.c
@@ -1,5 +1,7 @@
/* decrypt.c - Decrypt a message
* Copyright (C) 2001, 2003, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2001-2019 Werner Koch
+ * Copyright (C) 2015-2021 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -15,6 +17,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <config.h>
@@ -33,6 +36,16 @@
#include "keydb.h"
#include "../common/i18n.h"
#include "../common/compliance.h"
+#include "../common/tlv.h"
+
+/* We can provide an enum value which is only availabale with KSBA
+ * 1.6.0 so that we can compile even against older versions. Some
+ * calls will of course return an error in this case. This value is
+ * currently not used because the cipher mode is sufficient here. */
+/* #if KSBA_VERSION_NUMBER < 0x010600 /\* 1.6.0 *\/ */
+/* # define KSBA_CT_AUTHENVELOPED_DATA 10 */
+/* #endif */
+
struct decrypt_filter_parm_s
{
@@ -48,9 +61,388 @@ struct decrypt_filter_parm_s
char helpblock[16]; /* needed because there is no block buffering in
libgcrypt (yet) */
int helpblocklen;
+ int is_de_vs; /* Helper to track CO_DE_VS state. */
};
+/* Return the hash algorithm's algo id from its name given in the
+ * non-null termnated string in (buffer,buflen). Returns 0 on failure
+ * or if the algo is not known. */
+static char *
+string_from_gcry_buffer (gcry_buffer_t *buffer)
+{
+ char *string;
+
+ string = xtrymalloc (buffer->len + 1);
+ if (!string)
+ return NULL;
+ memcpy (string, buffer->data, buffer->len);
+ string[buffer->len] = 0;
+ return string;
+}
+
+
+/* Helper for pwri_decrypt to parse the derive info.
+ * Example data for (DER,DERLEN):
+ * SEQUENCE {
+ * OCTET STRING
+ * 60 76 4B E9 5E DF 3C F8 B2 F9 B6 C2 7D 5A FB 90
+ * 23 B6 47 DF
+ * INTEGER 10000
+ * SEQUENCE {
+ * OBJECT IDENTIFIER
+ * hmacWithSHA512 (1 2 840 113549 2 11)
+ * NULL
+ * }
+ * }
+ */
+static gpg_error_t
+pwri_parse_pbkdf2 (const unsigned char *der, size_t derlen,
+ unsigned char const **r_salt, unsigned int *r_saltlen,
+ unsigned long *r_iterations,
+ enum gcry_md_algos *r_digest)
+{
+ gpg_error_t err;
+ size_t objlen, hdrlen;
+ int class, tag, constructed, ndef;
+ char *oidstr;
+
+ err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > derlen || tag != TAG_SEQUENCE
+ || !constructed || ndef))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ return err;
+ derlen = objlen;
+
+ err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > derlen || tag != TAG_OCTET_STRING
+ || constructed || ndef))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ return err;
+ *r_salt = der;
+ *r_saltlen = objlen;
+ der += objlen;
+ derlen -= objlen;
+
+ err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > derlen || tag != TAG_INTEGER
+ || constructed || ndef))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ return err;
+ *r_iterations = 0;
+ for (; objlen; objlen--)
+ {
+ *r_iterations <<= 8;
+ *r_iterations |= (*der++) & 0xff;
+ derlen--;
+ }
+
+ err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > derlen || tag != TAG_SEQUENCE
+ || !constructed || ndef))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ return err;
+ derlen = objlen;
+
+ err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > derlen || tag != TAG_OBJECT_ID
+ || constructed || ndef))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ return err;
+
+ oidstr = ksba_oid_to_str (der, objlen);
+ if (!oidstr)
+ return gpg_error_from_syserror ();
+ *r_digest = gcry_md_map_name (oidstr);
+ if (*r_digest)
+ ;
+ else if (!strcmp (oidstr, "1.2.840.113549.2.7"))
+ *r_digest = GCRY_MD_SHA1;
+ else if (!strcmp (oidstr, "1.2.840.113549.2.8"))
+ *r_digest = GCRY_MD_SHA224;
+ else if (!strcmp (oidstr, "1.2.840.113549.2.9"))
+ *r_digest = GCRY_MD_SHA256;
+ else if (!strcmp (oidstr, "1.2.840.113549.2.10"))
+ *r_digest = GCRY_MD_SHA384;
+ else if (!strcmp (oidstr, "1.2.840.113549.2.11"))
+ *r_digest = GCRY_MD_SHA512;
+ else
+ err = gpg_error (GPG_ERR_DIGEST_ALGO);
+ ksba_free (oidstr);
+
+ return err;
+}
+
+
+/* Password based decryption.
+ * ENC_VAL has the form:
+ * (enc-val
+ * (pwri
+ * (derive-algo <oid>) --| both are optional
+ * (derive-parm <der>) --|
+ * (encr-algo <oid>)
+ * (encr-parm <iv>)
+ * (encr-key <key>))) -- this is the encrypted session key
+ *
+ */
+static gpg_error_t
+pwri_decrypt (ctrl_t ctrl, gcry_sexp_t enc_val,
+ unsigned char **r_result, unsigned int *r_resultlen,
+ struct decrypt_filter_parm_s *parm)
+{
+ gpg_error_t err;
+ gcry_buffer_t ioarray[5] = { {0} };
+ char *derive_algo_str = NULL;
+ char *encr_algo_str = NULL;
+ const unsigned char *dparm; /* Alias for ioarray[1]. */
+ unsigned int dparmlen;
+ const unsigned char *eparm; /* Alias for ioarray[3]. */
+ unsigned int eparmlen;
+ const unsigned char *ekey; /* Alias for ioarray[4]. */
+ unsigned int ekeylen;
+ unsigned char kek[32];
+ unsigned int keklen;
+ enum gcry_cipher_algos encr_algo;
+ enum gcry_cipher_modes encr_mode;
+ gcry_cipher_hd_t encr_hd = NULL;
+ unsigned char *result = NULL;
+ unsigned int resultlen;
+ unsigned int blklen;
+ const unsigned char *salt; /* Points int dparm. */
+ unsigned int saltlen;
+ unsigned long iterations;
+ enum gcry_md_algos digest_algo;
+ char *passphrase = NULL;
+
+
+ *r_resultlen = 0;
+ *r_result = NULL;
+
+ err = gcry_sexp_extract_param (enc_val, "enc-val!pwri",
+ "&'derive-algo'?'derive-parm'?"
+ "'encr-algo''encr-parm''encr-key'",
+ ioarray+0, ioarray+1,
+ ioarray+2, ioarray+3, ioarray+4, NULL);
+ if (err)
+ {
+ /* If this is not pwri element, it is likly a kekri element
+ * which we do not yet support. Change the error back to the
+ * original as returned by ksba_cms_get_issuer. */
+ if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+ err = gpg_error (GPG_ERR_UNSUPPORTED_CMS_OBJ);
+ else
+ log_error ("extracting PWRI parameter failed: %s\n",
+ gpg_strerror (err));
+ goto leave;
+ }
+
+ if (ioarray[0].data)
+ {
+ derive_algo_str = string_from_gcry_buffer (ioarray+0);
+ if (!derive_algo_str)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ }
+ dparm = ioarray[1].data;
+ dparmlen = ioarray[1].len;
+ encr_algo_str = string_from_gcry_buffer (ioarray+2);
+ if (!encr_algo_str)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ eparm = ioarray[3].data;
+ eparmlen = ioarray[3].len;
+ ekey = ioarray[4].data;
+ ekeylen = ioarray[4].len;
+
+ /* Check parameters. */
+ if (DBG_CRYPTO)
+ {
+ if (derive_algo_str)
+ {
+ log_debug ("derive algo: %s\n", derive_algo_str);
+ log_printhex (dparm, dparmlen, "derive parm:");
+ }
+ log_debug ("encr algo .: %s\n", encr_algo_str);
+ log_printhex (eparm, eparmlen, "encr parm .:");
+ log_printhex (ekey, ekeylen, "encr key .:");
+ }
+
+ if (!derive_algo_str)
+ {
+ err = gpg_error (GPG_ERR_NOT_SUPPORTED);
+ log_info ("PWRI with no key derivation detected\n");
+ goto leave;
+ }
+ if (strcmp (derive_algo_str, "1.2.840.113549.1.5.12"))
+ {
+ err = gpg_error (GPG_ERR_NOT_SUPPORTED);
+ log_info ("PWRI does not use PBKDF2 (but %s)\n", derive_algo_str);
+ goto leave;
+ }
+
+ digest_algo = 0; /*(silence cc warning)*/
+ err = pwri_parse_pbkdf2 (dparm, dparmlen,
+ &salt, &saltlen, &iterations, &digest_algo);
+ if (err)
+ {
+ log_error ("parsing PWRI parameter failed: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ parm->is_de_vs = (parm->is_de_vs
+ && gnupg_digest_is_compliant (CO_DE_VS, digest_algo));
+
+
+ encr_algo = gcry_cipher_map_name (encr_algo_str);
+ encr_mode = gcry_cipher_mode_from_oid (encr_algo_str);
+ if (!encr_algo || !encr_mode)
+ {
+ log_error ("PWRI uses unknown algorithm %s\n", encr_algo_str);
+ err = gpg_error (GPG_ERR_CIPHER_ALGO);
+ goto leave;
+ }
+
+ parm->is_de_vs =
+ (parm->is_de_vs
+ && gnupg_cipher_is_compliant (CO_DE_VS, encr_algo, encr_mode));
+
+ keklen = gcry_cipher_get_algo_keylen (encr_algo);
+ blklen = gcry_cipher_get_algo_blklen (encr_algo);
+ if (!keklen || keklen > sizeof kek || blklen != 16 )
+ {
+ log_error ("PWRI algorithm %s cannot be used\n", encr_algo_str);
+ err = gpg_error (GPG_ERR_INV_KEYLEN);
+ goto leave;
+ }
+ if ((ekeylen % blklen) || (ekeylen / blklen < 2))
+ {
+ /* Note that we need at least two full blocks. */
+ log_error ("PWRI uses a wrong length of encrypted key\n");
+ err = gpg_error (GPG_ERR_INV_KEYLEN);
+ goto leave;
+ }
+
+ err = gpgsm_agent_ask_passphrase
+ (ctrl,
+ i18n_utf8 (N_("Please enter the passphrase for decryption.")),
+ 0, &passphrase);
+ if (err)
+ goto leave;
+
+ err = gcry_kdf_derive (passphrase, strlen (passphrase),
+ GCRY_KDF_PBKDF2, digest_algo,
+ salt, saltlen, iterations,
+ keklen, kek);
+ if (passphrase)
+ {
+ wipememory (passphrase, strlen (passphrase));
+ xfree (passphrase);
+ passphrase = NULL;
+ }
+ if (err)
+ {
+ log_error ("deriving key from passphrase failed: %s\n",
+ gpg_strerror (err));
+ goto leave;
+ }
+
+ if (DBG_CRYPTO)
+ log_printhex (kek, keklen, "KEK .......:");
+
+ /* Unwrap the key. */
+ resultlen = ekeylen;
+ result = xtrymalloc_secure (resultlen);
+ if (!result)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ err = gcry_cipher_open (&encr_hd, encr_algo, encr_mode, 0);
+ if (err)
+ {
+ log_error ("PWRI failed to open cipher: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ err = gcry_cipher_setkey (encr_hd, kek, keklen);
+ wipememory (kek, sizeof kek);
+ if (!err)
+ err = gcry_cipher_setiv (encr_hd, ekey + ekeylen - 2 * blklen, blklen);
+ if (!err)
+ err = gcry_cipher_decrypt (encr_hd, result + ekeylen - blklen, blklen,
+ ekey + ekeylen - blklen, blklen);
+ if (!err)
+ err = gcry_cipher_setiv (encr_hd, result + ekeylen - blklen, blklen);
+ if (!err)
+ err = gcry_cipher_decrypt (encr_hd, result, ekeylen - blklen,
+ ekey, ekeylen - blklen);
+ /* (We assume that that eparm is the octet string with the IV) */
+ if (!err)
+ err = gcry_cipher_setiv (encr_hd, eparm, eparmlen);
+ if (!err)
+ err = gcry_cipher_decrypt (encr_hd, result, resultlen, NULL, 0);
+
+ if (err)
+ {
+ log_error ("KEK decryption failed for PWRI: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ if (DBG_CRYPTO)
+ log_printhex (result, resultlen, "Frame .....:");
+
+ if (result[0] < 8 /* At least 64 bits */
+ || (result[0] % 8) /* Multiple of 64 bits */
+ || result[0] > resultlen - 4 /* Not more than the size of the input */
+ || ( (result[1] ^ result[4]) /* Matching check bytes. */
+ & (result[2] ^ result[5])
+ & (result[3] ^ result[6]) ) != 0xff)
+ {
+ err = gpg_error (GPG_ERR_BAD_PASSPHRASE);
+ goto leave;
+ }
+
+ *r_resultlen = result[0];
+ *r_result = memmove (result, result + 4, result[0]);
+ result = NULL;
+
+ leave:
+ if (result)
+ {
+ wipememory (result, resultlen);
+ xfree (result);
+ }
+ if (passphrase)
+ {
+ wipememory (passphrase, strlen (passphrase));
+ xfree (passphrase);
+ }
+ gcry_cipher_close (encr_hd);
+ xfree (derive_algo_str);
+ xfree (encr_algo_str);
+ xfree (ioarray[0].data);
+ xfree (ioarray[1].data);
+ xfree (ioarray[2].data);
+ xfree (ioarray[3].data);
+ xfree (ioarray[4].data);
+ return err;
+}
+
/* Decrypt the session key and fill in the parm structure. The
algo and the IV is expected to be already in PARM. */
@@ -61,21 +453,44 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
{
char *seskey = NULL;
size_t n, seskeylen;
+ int pwri = !hexkeygrip;
int rc;
- rc = gpgsm_agent_pkdecrypt (ctrl, hexkeygrip, desc, enc_val,
- &seskey, &seskeylen);
- if (rc)
+ if (DBG_CRYPTO)
+ log_printcanon ("decrypting:", enc_val, 0);
+
+ if (!pwri)
{
- log_error ("error decrypting session key: %s\n", gpg_strerror (rc));
- goto leave;
+ rc = gpgsm_agent_pkdecrypt (ctrl, hexkeygrip, desc, enc_val,
+ &seskey, &seskeylen);
+ if (rc)
+ {
+ log_error ("error decrypting session key: %s\n", gpg_strerror (rc));
+ goto leave;
+ }
}
- if (DBG_CRYPTO)
- log_printhex (seskey, seskeylen, "pkcs1 encoded session key:");
-
n=0;
- if (seskeylen == 32 || seskeylen == 24 || seskeylen == 16)
+ if (pwri) /* Password based encryption. */
+ {
+ gcry_sexp_t s_enc_val;
+ unsigned char *decrypted;
+ unsigned int decryptedlen;
+
+ rc = gcry_sexp_sscan (&s_enc_val, NULL, enc_val,
+ gcry_sexp_canon_len (enc_val, 0, NULL, NULL));
+ if (rc)
+ goto leave;
+
+ rc = pwri_decrypt (ctrl, s_enc_val, &decrypted, &decryptedlen, parm);
+ gcry_sexp_release (s_enc_val);
+ if (rc)
+ goto leave;
+ xfree (seskey);
+ seskey = decrypted;
+ seskeylen = decryptedlen;
+ }
+ else if (seskeylen == 32 || seskeylen == 24 || seskeylen == 16)
{
/* Smells like an AES-128, 3-DES, or AES-256 key. This might
* happen because a SC has already done the unpacking. A better
@@ -117,6 +532,11 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
if (DBG_CRYPTO)
log_printhex (seskey+n, seskeylen-n, "session key:");
+ if (opt.verbose)
+ log_info (_("%s.%s encrypted data\n"),
+ gcry_cipher_algo_name (parm->algo),
+ cipher_mode_to_string (parm->mode));
+
rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
if (rc)
{
@@ -137,7 +557,20 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
goto leave;
}
- gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen);
+ rc = gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen);
+ if (rc)
+ {
+ log_error("IV setup failed: %s\n", gpg_strerror(rc) );
+ goto leave;
+ }
+
+ if (parm->mode == GCRY_CIPHER_MODE_GCM)
+ {
+ /* GCM mode really sucks in CMS. We need to know the AAD before
+ * we start decrypting but CMS puts the AAD after the content.
+ * Thus temporary files are required. Let's hope that no real
+ * messages with actual AAD are ever used. OCB Rules! */
+ }
leave:
xfree (seskey);
@@ -238,6 +671,36 @@ decrypt_filter (void *arg,
}
+/* This is the GCM version of decrypt_filter. */
+static gpg_error_t
+decrypt_gcm_filter (void *arg,
+ const void *inbuf, size_t inlen, size_t *inused,
+ void *outbuf, size_t maxoutlen, size_t *outlen)
+{
+ struct decrypt_filter_parm_s *parm = arg;
+
+ if (!inlen)
+ return gpg_error (GPG_ERR_BUG);
+
+ if (maxoutlen < parm->blklen)
+ return gpg_error (GPG_ERR_BUG);
+
+ if (inlen > maxoutlen)
+ inlen = maxoutlen;
+
+ *inused = inlen;
+ if (inlen)
+ {
+ gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen);
+ *outlen = inlen;
+ parm->any_data = 1;
+ }
+ else
+ *outlen = 0;
+ return 0;
+}
+
+
/* Perform a decrypt operation. */
int
@@ -326,7 +789,6 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
int algo, mode;
const char *algoid;
int any_key = 0;
- int is_de_vs; /* Computed compliance with CO_DE_VS. */
audit_log (ctrl->audit, AUDIT_GOT_DATA);
@@ -370,7 +832,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
}
/* For CMS, CO_DE_VS demands CBC mode. */
- is_de_vs = gnupg_cipher_is_compliant (CO_DE_VS, algo, mode);
+ dfparm.is_de_vs = gnupg_cipher_is_compliant (CO_DE_VS, algo, mode);
audit_log_i (ctrl->audit, AUDIT_DATA_CIPHER_ALGO, algo);
dfparm.algo = algo;
@@ -395,27 +857,41 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
ksba_sexp_t serial;
ksba_sexp_t enc_val;
char *hexkeygrip = NULL;
+ char *pkalgostr = NULL;
+ char *pkfpr = NULL;
char *desc = NULL;
char kidbuf[16+1];
+ int tmp_rc;
+ ksba_cert_t cert = NULL;
+ unsigned int nbits;
+ int pk_algo = 0;
+ int maybe_pwri = 0;
*kidbuf = 0;
- rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
- if (rc == -1 && recp)
+ tmp_rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
+ if (tmp_rc == -1 && recp)
break; /* no more recipients */
audit_log_i (ctrl->audit, AUDIT_NEW_RECP, recp);
- if (rc)
- log_error ("recp %d - error getting info: %s\n",
- recp, gpg_strerror (rc));
+ if (gpg_err_code (tmp_rc) == GPG_ERR_UNSUPPORTED_CMS_OBJ)
+ {
+ maybe_pwri = 1;
+ }
+ else if (tmp_rc)
+ {
+ log_error ("recp %d - error getting info: %s\n",
+ recp, gpg_strerror (tmp_rc));
+ }
else
{
- ksba_cert_t cert = NULL;
-
- log_debug ("recp %d - issuer: '%s'\n",
- recp, issuer? issuer:"[NONE]");
- log_debug ("recp %d - serial: ", recp);
- gpgsm_dump_serial (serial);
- log_printf ("\n");
+ if (opt.verbose)
+ {
+ log_debug ("recp %d - issuer: '%s'\n",
+ recp, issuer? issuer:"[NONE]");
+ log_debug ("recp %d - serial: ", recp);
+ gpgsm_dump_serial (serial);
+ log_printf ("\n");
+ }
if (ctrl->audit)
{
@@ -475,57 +951,63 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
desc = gpgsm_format_keydesc (cert);
+ pkfpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
+ pkalgostr = gpgsm_pubkey_algo_string (cert, NULL);
+ pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
+ if (!opt.quiet)
+ log_info (_("encrypted to %s key %s\n"), pkalgostr, pkfpr);
+
+ /* Check compliance. */
+ if (!gnupg_pk_is_allowed (opt.compliance,
+ PK_USE_DECRYPTION,
+ pk_algo, 0, NULL, nbits, NULL))
+ {
+ char kidstr[10+1];
+
+ snprintf (kidstr, sizeof kidstr, "0x%08lX",
+ gpgsm_get_short_fingerprint (cert, NULL));
+ log_info (_("key %s is not suitable for decryption"
+ " in %s mode\n"),
+ kidstr,
+ gnupg_compliance_option_string(opt.compliance));
+ rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
+ goto oops;
+ }
- {
- unsigned int nbits;
- int pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
-
- /* Check compliance. */
- if (!gnupg_pk_is_allowed (opt.compliance,
- PK_USE_DECRYPTION,
- pk_algo, 0, NULL, nbits, NULL))
- {
- char kidstr[10+1];
-
- snprintf (kidstr, sizeof kidstr, "0x%08lX",
- gpgsm_get_short_fingerprint (cert, NULL));
- log_info
- (_("key %s is not suitable for decryption"
- " in %s mode\n"),
- kidstr,
- gnupg_compliance_option_string (opt.compliance));
- rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
- goto oops;
- }
-
- /* Check that all certs are compliant with CO_DE_VS. */
- is_de_vs =
- (is_de_vs
- && gnupg_pk_is_compliant (CO_DE_VS, pk_algo, 0, NULL,
- nbits, NULL));
- }
+ /* Check that all certs are compliant with CO_DE_VS. */
+ dfparm.is_de_vs =
+ (dfparm.is_de_vs
+ && gnupg_pk_is_compliant (CO_DE_VS, pk_algo, 0,
+ NULL, nbits, NULL));
oops:
if (rc)
{
/* We cannot check compliance of certs that we
* don't have. */
- is_de_vs = 0;
+ dfparm.is_de_vs = 0;
}
xfree (issuer);
xfree (serial);
ksba_cert_release (cert);
}
- if (!hexkeygrip)
+ if ((!hexkeygrip || !pk_algo) && !maybe_pwri)
;
else if (!(enc_val = ksba_cms_get_enc_val (cms, recp)))
- log_error ("recp %d - error getting encrypted session key\n",
- recp);
+ {
+ log_error ("recp %d - error getting encrypted session key\n",
+ recp);
+ if (maybe_pwri)
+ log_info ("(possibly unsupported KEK info)\n");
+ }
else
{
- rc = prepare_decryption (ctrl,
- hexkeygrip, desc, enc_val, &dfparm);
+ if (maybe_pwri && opt.verbose)
+ log_info ("recp %d - KEKRI or PWRI\n", recp);
+
+ rc = prepare_decryption (ctrl, hexkeygrip,
+ desc, enc_val, &dfparm);
xfree (enc_val);
if (rc)
{
@@ -537,17 +1019,22 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
else
{ /* setup the bulk decrypter */
any_key = 1;
- ksba_writer_set_filter (writer,
- decrypt_filter,
- &dfparm);
-
- if (is_de_vs)
+ ksba_writer_set_filter
+ (writer,
+ dfparm.mode == GCRY_CIPHER_MODE_GCM?
+ decrypt_gcm_filter : decrypt_filter,
+ &dfparm);
+
+ if (dfparm.is_de_vs
+ && gnupg_gcrypt_is_compliant (CO_DE_VS))
gpgsm_status (ctrl, STATUS_DECRYPTION_COMPLIANCE_MODE,
gnupg_status_compliance_flag (CO_DE_VS));
}
audit_log_ok (ctrl->audit, AUDIT_RECP_RESULT, rc);
}
+ xfree (pkalgostr);
+ xfree (pkfpr);
xfree (hexkeygrip);
xfree (desc);
}
@@ -590,7 +1077,11 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
else if (stopreason == KSBA_SR_END_DATA)
{
ksba_writer_set_filter (writer, NULL, NULL);
- if (dfparm.any_data)
+ if (dfparm.mode == GCRY_CIPHER_MODE_GCM)
+ {
+ /* Nothing yet to do. We wait for the ready event. */
+ }
+ else if (dfparm.any_data )
{ /* write the last block with padding removed */
int i, npadding = dfparm.lastblock[dfparm.blklen-1];
if (!npadding || npadding > dfparm.blklen)
@@ -616,7 +1107,28 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
}
}
}
+ else if (stopreason == KSBA_SR_READY)
+ {
+ if (dfparm.mode == GCRY_CIPHER_MODE_GCM)
+ {
+ char *authtag;
+ size_t authtaglen;
+ rc = ksba_cms_get_message_digest (cms, 0, &authtag, &authtaglen);
+ if (rc)
+ {
+ log_error ("error getting authtag: %s\n", gpg_strerror (rc));
+ goto leave;
+ }
+ if (DBG_CRYPTO)
+ log_printhex (authtag, authtaglen, "Authtag ...:");
+ rc = gcry_cipher_checktag (dfparm.hd, authtag, authtaglen);
+ xfree (authtag);
+ if (rc)
+ log_error ("data is not authentic: %s\n", gpg_strerror (rc));
+ goto leave;
+ }
+ }
}
while (stopreason != KSBA_SR_READY);
diff --git a/sm/encrypt.c b/sm/encrypt.c
index f03097c..37cfe92 100644
--- a/sm/encrypt.c
+++ b/sm/encrypt.c
@@ -203,6 +203,7 @@ encrypt_dek (const DEK dek, ksba_cert_t cert, unsigned char **encval)
rc = encode_session_key (dek, &s_data);
if (rc)
{
+ gcry_sexp_release (s_pkey);
log_error ("encode_session_key failed: %s\n", gpg_strerror (rc));
return rc;
}
@@ -531,7 +532,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp)
}
}
- if (compliant)
+ if (compliant && gnupg_gcrypt_is_compliant (CO_DE_VS))
gpgsm_status (ctrl, STATUS_ENCRYPTION_COMPLIANCE_MODE,
gnupg_status_compliance_flag (CO_DE_VS));
@@ -564,7 +565,8 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, estream_t out_fp)
goto leave;
}
audit_log (ctrl->audit, AUDIT_ENCRYPTION_DONE);
- log_info ("encrypted data created\n");
+ if (!opt.quiet)
+ log_info ("encrypted data created\n");
leave:
ksba_cms_release (cms);
diff --git a/sm/export.c b/sm/export.c
index 7bea9cc..3da06d7 100644
--- a/sm/export.c
+++ b/sm/export.c
@@ -707,8 +707,8 @@ export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen,
{
err = gpgsm_agent_ask_passphrase
(ctrl,
- i18n_utf8 ("Please enter the passphrase to protect the "
- "new PKCS#12 object."),
+ i18n_utf8 (N_("Please enter the passphrase to protect the "
+ "new PKCS#12 object.")),
1, &passphrase);
if (err)
goto leave;
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 55a92c6..5c1f0bb 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -45,6 +45,7 @@
#include "../common/asshelp.h"
#include "../common/init.h"
#include "../common/compliance.h"
+#include "minip12.h"
#ifndef O_BINARY
@@ -336,8 +337,10 @@ static ARGPARSE_OPTS opts[] = {
/* N_("use the default key as default recipient")), */
/* ARGPARSE_s_n (oNoDefRecipient, "no-default-recipient", "@"), */
- ARGPARSE_s_s (oKeyServer, "keyserver",
+ ARGPARSE_s_s (oKeyServer, "ldapserver",
N_("|SPEC|use this keyserver to lookup keys")),
+ ARGPARSE_s_s (oKeyServer, "keyserver", "@"),
+
ARGPARSE_conffile (oOptions, "options", N_("|FILE|read options from FILE")),
ARGPARSE_s_s (oDebug, "debug", "@"),
@@ -731,6 +734,10 @@ set_debug (void)
if (opt.debug)
parse_debug_flag (NULL, &opt.debug, debug_flags);
+
+ /* minip12.c may be used outside of GnuPG, thus we don't have the
+ * opt structure over there. */
+ p12_set_verbosity (opt.verbose);
}
@@ -791,99 +798,6 @@ parse_validation_model (const char *model)
}
-/* Release the list of SERVERS. As usual it is okay to call this
- function with SERVERS passed as NULL. */
-void
-keyserver_list_free (struct keyserver_spec *servers)
-{
- while (servers)
- {
- struct keyserver_spec *tmp = servers->next;
- xfree (servers->host);
- xfree (servers->user);
- if (servers->pass)
- memset (servers->pass, 0, strlen (servers->pass));
- xfree (servers->pass);
- xfree (servers->base);
- xfree (servers);
- servers = tmp;
- }
-}
-
-/* See also dirmngr ldapserver_parse_one(). */
-struct keyserver_spec *
-parse_keyserver_line (char *line,
- const char *filename, unsigned int lineno)
-{
- char *p;
- char *endp;
- struct keyserver_spec *server;
- int fieldno;
- int fail = 0;
-
- /* Parse the colon separated fields. */
- server = xcalloc (1, sizeof *server);
- for (fieldno = 1, p = line; p; p = endp, fieldno++ )
- {
- endp = strchr (p, ':');
- if (endp)
- *endp++ = '\0';
- trim_spaces (p);
- switch (fieldno)
- {
- case 1:
- if (*p)
- server->host = xstrdup (p);
- else
- {
- log_error (_("%s:%u: no hostname given\n"),
- filename, lineno);
- fail = 1;
- }
- break;
-
- case 2:
- if (*p)
- server->port = atoi (p);
- break;
-
- case 3:
- if (*p)
- server->user = xstrdup (p);
- break;
-
- case 4:
- if (*p && !server->user)
- {
- log_error (_("%s:%u: password given without user\n"),
- filename, lineno);
- fail = 1;
- }
- else if (*p)
- server->pass = xstrdup (p);
- break;
-
- case 5:
- if (*p)
- server->base = xstrdup (p);
- break;
-
- default:
- /* (We silently ignore extra fields.) */
- break;
- }
- }
-
- if (fail)
- {
- log_info (_("%s:%u: skipping this line\n"), filename, lineno);
- keyserver_list_free (server);
- server = NULL;
- }
-
- return server;
-}
-
int
main ( int argc, char **argv)
@@ -1441,21 +1355,7 @@ main ( int argc, char **argv)
case oValidationModel: parse_validation_model (pargs.r.ret_str); break;
case oKeyServer:
- {
- struct keyserver_spec *keyserver;
- keyserver = parse_keyserver_line (pargs.r.ret_str,
- configname, pargs.lineno);
- if (! keyserver)
- log_error (_("could not parse keyserver\n"));
- else
- {
- /* FIXME: Keep last next pointer. */
- struct keyserver_spec **next_p = &opt.keyserver;
- while (*next_p)
- next_p = &(*next_p)->next;
- *next_p = keyserver;
- }
- }
+ append_to_strlist (&opt.keyserver, pargs.r.ret_str);
break;
case oIgnoreCertExtension:
@@ -1927,16 +1827,22 @@ main ( int argc, char **argv)
case aDecrypt:
{
estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
+ gpg_error_t err;
set_binary (stdin);
if (!argc)
- gpgsm_decrypt (&ctrl, 0, fp); /* from stdin */
+ err = gpgsm_decrypt (&ctrl, 0, fp); /* from stdin */
else if (argc == 1)
- gpgsm_decrypt (&ctrl, open_read (*argv), fp); /* from file */
+ err = gpgsm_decrypt (&ctrl, open_read (*argv), fp); /* from file */
else
wrong_args ("--decrypt [filename]");
- es_fclose (fp);
+#if GPGRT_VERSION_NUMBER >= 0x012700 /* 1.39 */
+ if (err)
+ gpgrt_fcancel (fp);
+ else
+#endif
+ es_fclose (fp);
}
break;
@@ -2137,7 +2043,7 @@ main ( int argc, char **argv)
}
/* cleanup */
- keyserver_list_free (opt.keyserver);
+ free_strlist (opt.keyserver);
opt.keyserver = NULL;
gpgsm_release_certlist (recplist);
gpgsm_release_certlist (signerlist);
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index d128344..9d9a303 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -39,17 +39,6 @@
#define MAX_DIGEST_LEN 64
-struct keyserver_spec
-{
- struct keyserver_spec *next;
-
- char *host;
- int port;
- char *user;
- char *pass;
- char *base;
-};
-
/* A large struct named "opt" to keep global flags. */
EXTERN_UNLESS_MAIN_MODULE
@@ -141,7 +130,7 @@ struct
the integrity of the software at
runtime. */
- struct keyserver_spec *keyserver;
+ strlist_t keyserver;
/* A list of certificate extension OIDs which are ignored so that
one can claim that a critical extension has been handled. One
diff --git a/sm/import.c b/sm/import.c
index ca69382..d7c898a 100644
--- a/sm/import.c
+++ b/sm/import.c
@@ -771,7 +771,7 @@ parse_p12 (ctrl_t ctrl, ksba_reader_t reader, struct stats_s *stats)
err = gpgsm_agent_ask_passphrase
(ctrl,
- i18n_utf8 ("Please enter the passphrase to unprotect the PKCS#12 object."),
+ i18n_utf8 (N_("Please enter the passphrase to unprotect the PKCS#12 object.")),
0, &passphrase);
if (err)
goto leave;
@@ -836,7 +836,8 @@ parse_p12 (ctrl_t ctrl, ksba_reader_t reader, struct stats_s *stats)
log_error ("can't calculate keygrip\n");
goto leave;
}
- log_printhex (grip, 20, "keygrip=");
+ if (DBG_X509)
+ log_printhex (grip, 20, "keygrip=");
/* Convert to canonical encoding using a function which pads it to a
multiple of 64 bits. We need this padding for AESWRAP. */
diff --git a/sm/keydb.c b/sm/keydb.c
index 8c0537a..564d449 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -58,7 +58,6 @@ static int any_registered;
struct keydb_handle {
- int locked;
int found;
int saved_found;
int current;
@@ -147,7 +146,7 @@ maybe_create_keybox (char *filename, int force, int *r_created)
}
*last_slash_in_filename = save_slash;
- /* To avoid races with other instances of gpg trying to create or
+ /* To avoid races with other instances of gpg/gpgsm trying to create or
update the keybox (it is removed during an update for a short
time), we do the next stuff in a locked state. */
lockhd = dotlock_create (filename, 0);
@@ -175,7 +174,7 @@ maybe_create_keybox (char *filename, int force, int *r_created)
}
/* Now the real test while we are locked. */
- if (!access(filename, F_OK))
+ if (!gnupg_access(filename, F_OK))
{
rc = 0; /* Okay, we may access the file now. */
goto leave;
@@ -375,6 +374,23 @@ keydb_add_resource (ctrl_t ctrl, const char *url, int force, int *auto_created)
}
+/* This is a helper requyired under Windows to close all files so that
+ * a rename will work. */
+void
+keydb_close_all_files (void)
+{
+#ifdef HAVE_W32_SYSTEM
+ int i;
+
+ log_assert (used_resources <= MAX_KEYDB_RESOURCES);
+ for (i=0; i < used_resources; i++)
+ if (all_resources[i].type == KEYDB_RESOURCE_TYPE_KEYBOX)
+ keybox_close_all_files (all_resources[i].token);
+#endif
+}
+
+
+
KEYDB_HANDLE
keydb_new (void)
{
@@ -505,22 +521,22 @@ keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
}
+
/* If the keyring has not yet been locked, lock it now. This
- operation is required before any update operation; it is optional
- for an insert operation. The lock is released with
- keydb_released. */
+ operation is required before any update operation; On Windows it is
+ always required to disallow other processes to open the file which
+ in turn would inhibit our copy+update+rename method. The lock is
+ released with keydb_released. */
gpg_error_t
keydb_lock (KEYDB_HANDLE hd)
{
if (!hd)
return gpg_error (GPG_ERR_INV_HANDLE);
- if (hd->locked)
- return 0; /* Already locked. */
return lock_all (hd);
}
-
+/* Same as keydb_lock but no check for an invalid HD. */
static int
lock_all (KEYDB_HANDLE hd)
{
@@ -560,8 +576,6 @@ lock_all (KEYDB_HANDLE hd)
}
}
}
- else
- hd->locked = 1;
/* make_dotlock () does not yet guarantee that errno is set, thus
we can't rely on the error reason and will simply use
@@ -569,14 +583,12 @@ lock_all (KEYDB_HANDLE hd)
return rc? gpg_error (GPG_ERR_EACCES) : 0;
}
+
static void
unlock_all (KEYDB_HANDLE hd)
{
int i;
- if (!hd->locked)
- return;
-
for (i=hd->used-1; i >= 0; i--)
{
switch (hd->active[i].type)
@@ -589,7 +601,6 @@ unlock_all (KEYDB_HANDLE hd)
break;
}
}
- hd->locked = 0;
}
@@ -719,7 +730,7 @@ keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
if ( hd->found < 0 || hd->found >= hd->used)
return gpg_error (GPG_ERR_NOTHING_FOUND);
- if (!hd->locked)
+ if (!dotlock_is_locked (hd->active[hd->found].lockhandle))
return gpg_error (GPG_ERR_NOT_LOCKED);
switch (hd->active[hd->found].type)
@@ -758,7 +769,7 @@ keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
else
return gpg_error (GPG_ERR_GENERAL);
- if (!hd->locked)
+ if (!dotlock_is_locked (hd->active[idx].lockhandle))
return gpg_error (GPG_ERR_NOT_LOCKED);
gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
@@ -778,44 +789,6 @@ keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
}
-
-/* Update the current keyblock with KB. */
-int
-keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
-{
- int rc = 0;
- unsigned char digest[20];
-
- if (!hd)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- if (opt.dry_run)
- return 0;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
-
- switch (hd->active[hd->found].type)
- {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL); /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
/*
* The current keyblock or cert will be deleted.
*/
@@ -833,7 +806,7 @@ keydb_delete (KEYDB_HANDLE hd, int unlock)
if( opt.dry_run )
return 0;
- if (!hd->locked)
+ if (!dotlock_is_locked (hd->active[hd->found].lockhandle))
return gpg_error (GPG_ERR_NOT_LOCKED);
switch (hd->active[hd->found].type)
@@ -952,7 +925,7 @@ int
keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
KEYDB_SEARCH_DESC *desc, size_t ndesc)
{
- int rc = -1;
+ int rc;
unsigned long skipped;
if (!hd)
@@ -965,6 +938,11 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
return gpg_error (GPG_ERR_NOT_FOUND);
}
+ rc = lock_all (hd);
+ if (rc)
+ return rc;
+ rc = -1;
+
while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
{
switch (hd->active[hd->current].type)
@@ -1118,6 +1096,7 @@ keydb_store_cert (ctrl_t ctrl, ksba_cert_t cert, int ephemeral, int *existed)
records. */
keydb_set_ephemeral (kh, 1);
+ keydb_close_all_files ();
rc = lock_all (kh);
if (rc)
return rc;
@@ -1203,7 +1182,8 @@ keydb_set_cert_flags (ctrl_t ctrl, ksba_cert_t cert, int ephemeral,
if (ephemeral)
keydb_set_ephemeral (kh, 1);
- err = keydb_lock (kh);
+ keydb_close_all_files ();
+ err = lock_all (kh);
if (err)
{
log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
@@ -1301,7 +1281,8 @@ keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names)
}
}
- err = keydb_lock (hd);
+ keydb_close_all_files ();
+ err = lock_all (hd);
if (err)
{
log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
@@ -1333,7 +1314,7 @@ keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names)
}
}
if (rc && rc != -1)
- log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
+ log_error ("%s failed: %s\n", __func__, gpg_strerror (rc));
leave:
xfree (desc);
diff --git a/sm/keydb.h b/sm/keydb.h
index 6234625..226cac2 100644
--- a/sm/keydb.h
+++ b/sm/keydb.h
@@ -33,6 +33,8 @@ typedef struct keydb_handle *KEYDB_HANDLE;
/*-- keydb.c --*/
gpg_error_t keydb_add_resource (ctrl_t ctrl, const char *url,
int force, int *auto_created);
+void keydb_close_all_files (void);
+
KEYDB_HANDLE keydb_new (void);
void keydb_release (KEYDB_HANDLE hd);
int keydb_set_ephemeral (KEYDB_HANDLE hd, int yes);
@@ -47,7 +49,6 @@ void keydb_push_found_state (KEYDB_HANDLE hd);
void keydb_pop_found_state (KEYDB_HANDLE hd);
int keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert);
int keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
-int keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
int keydb_delete (KEYDB_HANDLE hd, int unlock);
diff --git a/sm/minip12.c b/sm/minip12.c
index 7087e44..9096f0b 100644
--- a/sm/minip12.c
+++ b/sm/minip12.c
@@ -176,6 +176,16 @@ struct tag_info
};
+static int opt_verbose;
+
+
+void
+p12_set_verbosity (int verbose)
+{
+ opt_verbose = verbose;
+}
+
+
/* Parse the buffer at the address BUFFER which is of SIZE and return
the tag and the length part from the TLV triplet. Update BUFFER
and SIZE on success. Checks that the encoded length does not
@@ -869,8 +879,9 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
else
goto bailout;
- log_info ("%lu bytes of %s encrypted text\n",ti.length,
- is_pbes2?"AES128":is_3des?"3DES":"RC2");
+ if (opt_verbose)
+ log_info ("%lu bytes of %s encrypted text\n",ti.length,
+ is_pbes2?"AES128":is_3des?"3DES":"RC2");
plain = gcry_malloc_secure (ti.length);
if (!plain)
@@ -967,7 +978,8 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
{
int len;
- log_info ("processing simple keyBag\n");
+ if (opt_verbose)
+ log_info ("processing simple keyBag\n");
/* Fixme: This code is duplicated from parse_bag_data. */
if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
@@ -1050,7 +1062,8 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
}
else
{
- log_info ("processing certBag\n");
+ if (opt_verbose)
+ log_info ("processing certBag\n");
if (parse_tag (&p, &n, &ti))
goto bailout;
if (ti.class || ti.tag != TAG_SEQUENCE)
@@ -1376,8 +1389,9 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset,
if (ti.class || ti.tag != TAG_OCTET_STRING || !ti.length )
goto bailout;
- log_info ("%lu bytes of %s encrypted text\n",
- ti.length, is_pbes2? "AES128":"3DES");
+ if (opt_verbose)
+ log_info ("%lu bytes of %s encrypted text\n",
+ ti.length, is_pbes2? "AES128":"3DES");
plain = gcry_malloc_secure (ti.length);
if (!plain)
diff --git a/sm/minip12.h b/sm/minip12.h
index 39a8193..343b733 100644
--- a/sm/minip12.h
+++ b/sm/minip12.h
@@ -22,6 +22,8 @@
#include <gcrypt.h>
+void p12_set_verbosity (int verbose);
+
gcry_mpi_t *p12_parse (const unsigned char *buffer, size_t length,
const char *pw,
void (*certcb)(void*, const unsigned char*, size_t),
diff --git a/sm/server.c b/sm/server.c
index 77ec07f..5341d31 100644
--- a/sm/server.c
+++ b/sm/server.c
@@ -724,8 +724,13 @@ cmd_export (assuan_context_t ctx, char *line)
if (opt_secret)
{
- if (!list || !*list->d)
+ if (!list)
return set_error (GPG_ERR_NO_DATA, "No key given");
+ if (!*list->d)
+ {
+ free_strlist (list);
+ return set_error (GPG_ERR_NO_DATA, "No key given");
+ }
if (list->next)
return set_error (GPG_ERR_TOO_MANY, "Only one key allowed");
}
@@ -948,17 +953,27 @@ do_listkeys (assuan_context_t ctx, char *line, int mode)
int outfd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
if ( outfd == -1 )
- return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
+ {
+ free_strlist (list);
+ return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
+ }
fp = es_fdopen_nc (outfd, "w");
if (!fp)
- return set_error (gpg_err_code_from_syserror (), "es_fdopen() failed");
+ {
+ free_strlist (list);
+ return set_error (gpg_err_code_from_syserror (),
+ "es_fdopen() failed");
+ }
}
else
{
fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
if (!fp)
- return set_error (GPG_ERR_ASS_GENERAL,
- "error setting up a data stream");
+ {
+ free_strlist (list);
+ return set_error (GPG_ERR_ASS_GENERAL,
+ "error setting up a data stream");
+ }
}
ctrl->with_colons = 1;
diff --git a/sm/verify.c b/sm/verify.c
index 0fa365f..3c5279e 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -512,6 +512,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
/* Check compliance with CO_DE_VS. */
if (gnupg_pk_is_compliant (CO_DE_VS, pkalgo, pkalgoflags,
NULL, nbits, NULL)
+ && gnupg_gcrypt_is_compliant (CO_DE_VS)
&& gnupg_digest_is_compliant (CO_DE_VS, sigval_hash_algo))
gpgsm_status (ctrl, STATUS_VERIFICATION_COMPLIANCE_MODE,
gnupg_status_compliance_flag (CO_DE_VS));