diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | common/ChangeLog | 9 | ||||
-rw-r--r-- | common/Makefile.am | 4 | ||||
-rw-r--r-- | common/sexp-parse.h | 2 | ||||
-rw-r--r-- | common/sexputil.c | 52 | ||||
-rw-r--r-- | common/t-sexputil.c | 82 | ||||
-rw-r--r-- | common/util.h | 1 | ||||
-rw-r--r-- | doc/ChangeLog | 11 | ||||
-rw-r--r-- | doc/debugging.texi | 5 | ||||
-rw-r--r-- | doc/examples/trustlist.txt | 11 | ||||
-rw-r--r-- | doc/gpg.texi | 12 | ||||
-rw-r--r-- | doc/gpgsm.texi | 13 | ||||
-rw-r--r-- | doc/qualified.txt | 29 | ||||
-rw-r--r-- | doc/specify-user-id.texi | 2 | ||||
-rw-r--r-- | sm/ChangeLog | 7 | ||||
-rw-r--r-- | sm/gpgsm.c | 13 | ||||
-rw-r--r-- | sm/gpgsm.h | 3 | ||||
-rw-r--r-- | sm/sign.c | 4 | ||||
-rw-r--r-- | sm/verify.c | 38 |
19 files changed, 276 insertions, 25 deletions
@@ -23,6 +23,9 @@ Noteworthy changes in version 2.0.8 * Creating DSA2 keys is now possible. + * New option --extra-digest-algo for gpgsm to allow verification of + broken signatures. + Noteworthy changes in version 2.0.7 (2007-09-10) ------------------------------------------------ diff --git a/common/ChangeLog b/common/ChangeLog index b6b12f95b..b42bf9f4f 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,9 @@ +2007-12-13 Werner Koch <wk@g10code.com> + + * sexputil.c (hash_algo_from_sigval): New. + * t-sexputil.c: New. + * Makefile.am (module_tests): Add it. + 2007-12-11 Werner Koch <wk@g10code.com> * asshelp.c (send_pinentry_environment): Allow using of old @@ -1126,7 +1132,8 @@ (atoi_1,atoi_2,atoi_4,xtoi_1,xtoi_2): New. - Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004, 2005, 2006, + 2007 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/common/Makefile.am b/common/Makefile.am index 11404af02..e9c532521 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -107,7 +107,7 @@ status-codes.h: Makefile mkstrtable.awk exstatus.awk status.h # # Module tests # -module_tests = t-convert t-gettime t-sysutils +module_tests = t-convert t-gettime t-sysutils t-sexputil module_maint_tests = t-helpfile t_common_ldadd = libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a \ @@ -117,5 +117,5 @@ t_convert_LDADD = $(t_common_ldadd) t_gettime_LDADD = $(t_common_ldadd) t_sysutils_LDADD = $(t_common_ldadd) t_helpfile_LDADD = $(t_common_ldadd) - +t_sexputil_LDADD = $(t_common_ldadd) diff --git a/common/sexp-parse.h b/common/sexp-parse.h index d2675fbdb..b3213a6fe 100644 --- a/common/sexp-parse.h +++ b/common/sexp-parse.h @@ -44,7 +44,7 @@ snext (unsigned char const **buf) lists and may be passed as a positive number to skip over the remainder of an S-Expression if the current position is somewhere in an S-Expression. The function may return an error code if it - encounters an impossible conditions */ + encounters an impossible condition. */ static inline gpg_error_t sskip (unsigned char const **buf, int *depth) { diff --git a/common/sexputil.c b/common/sexputil.c index c7f718660..4907a9355 100644 --- a/common/sexputil.c +++ b/common/sexputil.c @@ -1,5 +1,5 @@ /* sexputil.c - Utility functions for S-expressions. - * Copyright (C) 2005 Free Software Foundation, Inc. + * Copyright (C) 2005, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -40,8 +40,8 @@ KEY is expected to be an canonical encoded S-expression with a public or private key. KEYLEN is the length of that buffer. - GRIP must be at least 20 bytes long On success 0 is return, on - error an aerror code. */ + GRIP must be at least 20 bytes long. On success 0 is returned, on + error an error code. */ gpg_error_t keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, unsigned char *grip) @@ -143,3 +143,49 @@ make_simple_sexp_from_hexstr (const char *line, size_t *nscanned) return buf; } + + +/* Return the hash algorithm from a KSBA sig-val. SIGVAL is a + canonical encoded S-expression. Return 0 if the hash algorithm is + not encoded in SIG-VAL or it is not supported by libgcrypt. */ +int +hash_algo_from_sigval (const unsigned char *sigval) +{ + const unsigned char *s = sigval; + size_t n; + int depth; + char buffer[50]; + + if (!s || *s != '(') + return 0; /* Invalid S-expression. */ + s++; + n = snext (&s); + if (!n) + return 0; /* Invalid S-expression. */ + if (!smatch (&s, n, "sig-val")) + return 0; /* Not a sig-val. */ + if (*s != '(') + return 0; /* Invalid S-expression. */ + s++; + /* Skip over the algo+parameter list. */ + depth = 1; + if (sskip (&s, &depth) || depth) + return 0; /* Invalid S-expression. */ + if (*s != '(') + return 0; /* No futher list. */ + /* Check whether this is (hash ALGO). */ + s++; + n = snext (&s); + if (!n) + return 0; /* Invalid S-expression. */ + if (!smatch (&s, n, "hash")) + return 0; /* Not a "hash" keyword. */ + n = snext (&s); + if (!n || n+1 >= sizeof (buffer)) + return 0; /* Algorithm string is missing or too long. */ + memcpy (buffer, s, n); + buffer[n] = 0; + + return gcry_md_map_name (buffer); +} + diff --git a/common/t-sexputil.c b/common/t-sexputil.c new file mode 100644 index 000000000..097dc9878 --- /dev/null +++ b/common/t-sexputil.c @@ -0,0 +1,82 @@ +/* t-sexputil.c - Module test for sexputil.c + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG 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 <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "util.h" + +#define pass() do { ; } while(0) +#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\ + __FILE__,__LINE__, (a)); \ + exit (1); \ + } while(0) + + +static void +test_hash_algo_from_sigval (void) +{ + int algo; + /* A real world example. */ + unsigned char example1_rsa_sha1[] = + ("\x28\x37\x3A\x73\x69\x67\x2D\x76\x61\x6C\x28\x33\x3A\x72\x73\x61" + "\x28\x31\x3A\x73\x31\x32\x38\x3A\x17\xD2\xE9\x5F\xB4\x24\xD4\x1E" + "\x8C\xEE\x94\xDA\x41\x42\x1F\x26\x5E\xF4\x6D\xEC\x5B\xBD\x5B\x89" + "\x7A\x69\x11\x43\xE9\xD2\x23\x21\x25\x64\xA6\xB0\x56\xEF\xB4\xE9" + "\x06\xB2\x44\xF6\x80\x1E\xFF\x41\x23\xEB\xC9\xFA\xFD\x09\xBF\x9C" + "\x8E\xCF\x7F\xC3\x7F\x3A\x40\x48\x89\xDC\xBA\xB7\xDB\x9E\xF1\xBA" + "\x7C\x08\xEA\x74\x1D\x49\xE7\x65\xEF\x67\x79\xBC\x23\xD9\x49\xCD" + "\x05\x99\xD3\xD8\xB7\x7B\xC7\x0E\xF2\xB3\x01\x48\x0F\xC8\xEB\x05" + "\x7B\xFB\x61\xCC\x41\x04\x74\x6D\x33\x84\xB1\xE6\x6A\xD8\x0F\xBC" + "\x27\xAC\x43\x45\xFA\x04\xD1\x22\x29\x29\x28\x34\x3A\x68\x61\x73" + "\x68\x34\x3A\x73\x68\x61\x31\x29\x29"); + /* The same but without the hash algo. */ + unsigned char example1_rsa[] = + ("\x28\x37\x3A\x73\x69\x67\x2D\x76\x61\x6C\x28\x33\x3A\x72\x73\x61" + "\x28\x31\x3A\x73\x31\x32\x38\x3A\x17\xD2\xE9\x5F\xB4\x24\xD4\x1E" + "\x8C\xEE\x94\xDA\x41\x42\x1F\x26\x5E\xF4\x6D\xEC\x5B\xBD\x5B\x89" + "\x7A\x69\x11\x43\xE9\xD2\x23\x21\x25\x64\xA6\xB0\x56\xEF\xB4\xE9" + "\x06\xB2\x44\xF6\x80\x1E\xFF\x41\x23\xEB\xC9\xFA\xFD\x09\xBF\x9C" + "\x8E\xCF\x7F\xC3\x7F\x3A\x40\x48\x89\xDC\xBA\xB7\xDB\x9E\xF1\xBA" + "\x7C\x08\xEA\x74\x1D\x49\xE7\x65\xEF\x67\x79\xBC\x23\xD9\x49\xCD" + "\x05\x99\xD3\xD8\xB7\x7B\xC7\x0E\xF2\xB3\x01\x48\x0F\xC8\xEB\x05" + "\x7B\xFB\x61\xCC\x41\x04\x74\x6D\x33\x84\xB1\xE6\x6A\xD8\x0F\xBC" + "\x27\xAC\x43\x45\xFA\x04\xD1\x22\x29\x29\x29"); + + algo = hash_algo_from_sigval (example1_rsa_sha1); + if (algo != GCRY_MD_SHA1) + fail (0); + algo = hash_algo_from_sigval (example1_rsa); + if (algo) + fail (0); +} + + + + +int +main (int argc, char **argv) +{ + + test_hash_algo_from_sigval (); + + return 0; +} + diff --git a/common/util.h b/common/util.h index e9d0ffbec..53a56a336 100644 --- a/common/util.h +++ b/common/util.h @@ -164,6 +164,7 @@ gpg_error_t keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, int cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b); unsigned char *make_simple_sexp_from_hexstr (const char *line, size_t *nscanned); +int hash_algo_from_sigval (const unsigned char *sigval); /*-- convert.c --*/ int hex2bin (const char *string, void *buffer, size_t length); diff --git a/doc/ChangeLog b/doc/ChangeLog index 63415c4da..b01d3b179 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,14 @@ +2007-12-13 Werner Koch <wk@g10code.com> + + * qualified.txt: Add 2 root certs from S-Trust for 2008-2012. + * examples/trustlist.txt: Ditto. + + * gpgsm.texi (Esoteric Options): Document --extra-digest-algo. + +2007-12-12 Werner Koch <wk@g10code.com> + + * gpg.texi: Typo fixes. From Christer Andersson. + 2007-12-04 Werner Koch <wk@g10code.com> * help.txt: New online help file. diff --git a/doc/debugging.texi b/doc/debugging.texi index fb27b2710..242d601cb 100644 --- a/doc/debugging.texi +++ b/doc/debugging.texi @@ -182,7 +182,12 @@ such a certificate. You may use the @code{relax} flag in fingerprint and this flag may only be added manually to @file{trustlist.txt}. +@item Error message: ``digest algorithm N has not been enabled'' +The signature is broken. You may try the option +@option{--extra-digest-algo SHA256} to workaround the problem. The +number N is the internal algorighm indentifier; for example 8 refers to +SHA-256. @end itemize diff --git a/doc/examples/trustlist.txt b/doc/examples/trustlist.txt index 1fcae4106..fa80ed4fc 100644 --- a/doc/examples/trustlist.txt +++ b/doc/examples/trustlist.txt @@ -38,6 +38,17 @@ DB:45:3D:1B:B0:1A:F3:23:10:6B:DE:D0:09:61:57:AA:F4:25:E0:5B S # Issuer: /CN=11R-CA 1:PN/O=Bundesnetzagentur/C=DE A0:8B:DF:3B:AA:EE:3F:9D:64:6C:47:81:23:21:D4:A6:18:81:67:1D S +# S/N: 00B3963E0E6C2D65125853E970665402E5 +# Issuer: /CN=S-TRUST Qualified Root CA 2008-001:PN +# /O=Deutscher Sparkassen Verlag GmbH/L=Stuttgart/C=DE +C9:2F:E6:50:DB:32:59:E0:CE:65:55:F3:8C:76:E0:B8:A8:FE:A3:CA S + +# S/N: 00C4216083F35C54F67B09A80C3C55FE7D +# Issuer: /CN=S-TRUST Qualified Root CA 2008-002:PN +# /O=Deutscher Sparkassen Verlag GmbH/L=Stuttgart/C=DE +D5:C7:50:F2:FE:4E:EE:D7:C7:B1:E4:13:7B:FB:54:84:3A:7D:97:9B S + + #Serial number: 00 # Issuer: /CN=CA Cert Signing Authority/OU=http:\x2f\x2fwww. # cacert.org/O=Root CA/EMail=support@cacert.org diff --git a/doc/gpg.texi b/doc/gpg.texi index f7b7df856..cc048b1db 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -113,7 +113,7 @@ Developer information: @node GPG Commands @section Commands -Commands are not distinguished from options execpt for the fact that +Commands are not distinguished from options except for the fact that only one command is allowed. @command{@gpgname} may be run with no commands, in which case it will @@ -876,7 +876,7 @@ encountered, you can explicitly stop parsing by using the special option @node GPG Configuration Options @subsection How to change the configuration -These options are used to change the configuraton and are usually found +These options are used to change the configuration and are usually found in the option file. @table @gnupgtabopt @@ -2456,13 +2456,13 @@ listed. @option{--list-config} is only usable with @item --gpgconf-list @opindex gpgconf-list -This command is simliar to @option{--list-config} but in general only +This command is similar to @option{--list-config} but in general only internally used by the @command{gpgconf} tool. @item --gpgconf-test @opindex gpgconf-test This is more or less dummy action. However it parses the configuration -file and returns with failure if the configuraion file would prevent +file and returns with failure if the configuration file would prevent @command{gpg} from startup. Thus it may be used to run a syntax check on the configuration file. @@ -2560,7 +2560,7 @@ For existing users the a small helper script is provided to create these files (@pxref{addgnupghome}). @end ifclear -For internal purposes @command{@gpgname} creates and maintaines a few other +For internal purposes @command{@gpgname} creates and maintains a few other files; They all live in in the current home directory (@pxref{option --homedir}). Only the @command{@gpgname} may modify these files. @@ -2686,7 +2686,7 @@ user for the filename. @include specify-user-id.texi @end ifset -@mansect return vaue +@mansect return value @chapheading RETURN VALUE The program returns 0 if everything was fine, 1 if at least diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index e5ae1688c..12f882e09 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -569,6 +569,19 @@ encryption. For convenience the strings @code{3DES}, @code{AES} and @table @gnupgtabopt +@item --extra-digest-algo @var{name} +@opindex extra-digest-algo +Sometimes signatures are broken in that they announce a different digest +algorithm than actually used. @command{gpgsm} uses a one-pass data +processing model and thus needs to rely on the announcde digest +algorithms to properly hash the data. As a workaround this option may +be used to tell gpg to also hash the data using the algorithm +@var{name}; this slows processing down a little bit but allows to verify +such broken signatures. If @command{gpgsm} prints an error like +``digest algo 8 has not been enabled'' you may want to try this option, +with @samp{SHA256} for @var{name}. + + @item --faked-system-time @var{epoch} @opindex faked-system-time This option is only useful for testing; it sets the system time back or diff --git a/doc/qualified.txt b/doc/qualified.txt index f6a54d66e..ddd77972b 100644 --- a/doc/qualified.txt +++ b/doc/qualified.txt @@ -180,6 +180,35 @@ E0:BF:1B:91:91:6B:88:E4:F1:15:92:22:CE:37:23:96:B1:4A:2E:5C de 7A:3C:1B:60:2E:BD:A4:A1:E0:EB:AD:7A:BA:4F:D1:43:69:A9:39:FC de +# ID: 0xA8FEA3CA +# S/N: 00B3963E0E6C2D65125853E970665402E5 +# Issuer: /CN=S-TRUST Qualified Root CA 2008-001:PN +# /O=Deutscher Sparkassen Verlag GmbH/L=Stuttgart/C=DE +# Subject: /CN=S-TRUST Qualified Root CA 2008-001:PN +# /O=Deutscher Sparkassen Verlag GmbH/L=Stuttgart/C=DE +# validity: 2008-01-01 00:00:00 through 2012-12-30 23:59:59 +# key type: 2048 bit RSA +# key usage: certSign crlSign +# chain length: 1 +#[checked: 2007-12-13 via received ZIP file with qualified signature from +# /CN=Dr. Matthias Stehle/O=Deutscher Sparkassenverlag +# /C=DE/SerialNumber=DSV0000000008/SN=Stehle/GN=Matthias Georg] +C9:2F:E6:50:DB:32:59:E0:CE:65:55:F3:8C:76:E0:B8:A8:FE:A3:CA + +# ID: 0x3A7D979B +# S/N: 00C4216083F35C54F67B09A80C3C55FE7D +# Issuer: /CN=S-TRUST Qualified Root CA 2008-002:PN +# /O=Deutscher Sparkassen Verlag GmbH/L=Stuttgart/C=DE +# Subject: /CN=S-TRUST Qualified Root CA 2008-002:PN +# /O=Deutscher Sparkassen Verlag GmbH/L=Stuttgart/C=DE +# validity: 2008-01-01 00:00:00 through 2012-12-30 23:59:59 +# key type: 2048 bit RSA +# key usage: certSign crlSign +# chain length: 1 +#[checked: 2007-12-13 via received ZIP file with qualified signature from +# /CN=Dr. Matthias Stehle/O=Deutscher Sparkassenverlag +# /C=DE/SerialNumber=DSV0000000008/SN=Stehle/GN=Matthias Georg"] +D5:C7:50:F2:FE:4E:EE:D7:C7:B1:E4:13:7B:FB:54:84:3A:7D:97:9B #******************************************* diff --git a/doc/specify-user-id.texi b/doc/specify-user-id.texi index 0929a10f8..7d23ed86f 100644 --- a/doc/specify-user-id.texi +++ b/doc/specify-user-id.texi @@ -121,7 +121,7 @@ This should return the Root cert of the issuer. See note above. @item By exact match on serial number and issuer's DN. -This is indicated by a hash mark, followed by the hexadecmal +This is indicated by a hash mark, followed by the hexadecimal representation of the serial number, then followed by a slash and the RFC-2253 encoded DN of the issuer. See note above. diff --git a/sm/ChangeLog b/sm/ChangeLog index 49ed50669..032f02897 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2007-12-13 Werner Koch <wk@g10code.com> + + * gpgsm.c (main): Add option --extra-digest-algo. + * gpgsm.h (struct): Add EXTRA_DIGEST_ALGO. + * verify.c (gpgsm_verify): Use it. Use the hash algorithm from + the signature value. + 2007-12-11 Werner Koch <wk@g10code.com> * certchain.c (do_validate_chain): Log AUDIT_ROOT_TRUSTED. diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 93474b37a..71f8e2cc1 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -174,6 +174,7 @@ enum cmd_and_opt_values { oOpenPGP, oCipherAlgo, oDigestAlgo, + oExtraDigestAlgo, oCompressAlgo, oCommandFD, oNoVerbose, @@ -388,6 +389,7 @@ static ARGPARSE_OPTS opts[] = { { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")}, { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")}, + { oExtraDigestAlgo, "extra-digest-algo", 2 , "@" }, #if 0 { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")}, #endif @@ -842,6 +844,7 @@ main ( int argc, char **argv) int use_random_seed = 1; int with_fpr = 0; char *def_digest_string = NULL; + char *extra_digest_algo = NULL; enum cmd_and_opt_values cmd = 0; struct server_control_s ctrl; certlist_t recplist = NULL; @@ -1298,6 +1301,10 @@ main ( int argc, char **argv) } break; + case oExtraDigestAlgo: + extra_digest_algo = pargs.r.ret_str; + break; + case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; case oNoRandomSeedFile: use_random_seed = 0; break; @@ -1441,6 +1448,12 @@ main ( int argc, char **argv) if (our_md_test_algo(opt.def_digest_algo) ) log_error (_("selected digest algorithm is invalid\n")); } + if (extra_digest_algo) + { + opt.extra_digest_algo = gcry_md_map_name (extra_digest_algo); + if (our_md_test_algo (opt.extra_digest_algo) ) + log_error (_("selected digest algorithm is invalid\n")); + } } if (log_get_errorcount(0)) diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 5232ce427..8b03995e8 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -92,6 +92,9 @@ struct char *local_user; /* NULL or argument to -u */ + int extra_digest_algo; /* A digest algorithm also used for + verification of signatures. */ + int always_trust; /* Trust the given keys even if there is no valid certification chain */ int skip_verify; /* do not check signatures on data */ @@ -491,7 +491,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, unsigned char *digest; size_t digest_len; /* Fixme do this for all signers and get the algo to use from - the signer's certificate - does not make mich sense, but we + the signer's certificate - does not make much sense, but we should do this consistent as we have already done it above. */ algo = GCRY_MD_SHA1; hash_data (data_fd, data_md); @@ -530,7 +530,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist, } /* We need to write at least a minimal list of our capabilities to - try to convince some MUAs to use 3DEs and not the crippled + try to convince some MUAs to use 3DES and not the crippled RC2. Our list is: aes128-CBC diff --git a/sm/verify.c b/sm/verify.c index 2a455a5ce..1071d9086 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -203,10 +203,20 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp) } else { + if (DBG_X509) + log_debug ("enabling hash algorithm %d (%s)\n", + algo, algoid? algoid:""); gcry_md_enable (data_md, algo); audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo); } } + if (opt.extra_digest_algo) + { + if (DBG_X509) + log_debug ("enabling extra hash algorithm %d\n", + opt.extra_digest_algo); + gcry_md_enable (data_md, opt.extra_digest_algo); + } if (is_detached) { if (data_fd == -1) @@ -271,6 +281,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp) char *msgdigest = NULL; size_t msgdigestlen; char *ctattr; + int sigval_hash_algo; int info_pkalgo; unsigned int verifyflags; @@ -331,7 +342,8 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp) &algo, &is_enabled) || !is_enabled) { - log_error ("digest algo %d has not been enabled\n", algo); + log_error ("digest algo %d (%s) has not been enabled\n", + algo, algoid?algoid:""); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "unsupported"); goto next_signer; } @@ -389,8 +401,16 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp) audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } + sigval_hash_algo = hash_algo_from_sigval (sigval); if (DBG_X509) - log_debug ("signer %d - signature available", signer); + { + log_debug ("signer %d - signature available (sigval hash=%d)", + signer, sigval_hash_algo); +/* log_printhex ("sigval ", sigval, */ +/* gcry_sexp_canon_len (sigval, 0, NULL, NULL)); */ + } + if (!sigval_hash_algo) + sigval_hash_algo = algo; /* Fallback used e.g. with old libksba. */ /* Find the certificate of the signer */ keydb_search_reset (kh); @@ -438,8 +458,8 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp) gcry_md_hd_t md; unsigned char *s; - /* check that the message digest in the signed attributes - matches the one we calculated on the data */ + /* Check that the message digest in the signed attributes + matches the one we calculated on the data. */ s = gcry_md_read (data_md, algo); if ( !s || !msgdigestlen || gcry_md_get_algo_dlen (algo) != msgdigestlen @@ -456,7 +476,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp) goto next_signer; } - rc = gcry_md_open (&md, algo, 0); + rc = gcry_md_open (&md, sigval_hash_algo, 0); if (rc) { log_error ("md_open failed: %s\n", gpg_strerror (rc)); @@ -476,14 +496,14 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp) audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error"); goto next_signer; } - rc = gpgsm_check_cms_signature (cert, sigval, md, algo, - &info_pkalgo); + rc = gpgsm_check_cms_signature (cert, sigval, md, + sigval_hash_algo, &info_pkalgo); gcry_md_close (md); } else { - rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo, - &info_pkalgo); + rc = gpgsm_check_cms_signature (cert, sigval, data_md, + algo, &info_pkalgo); } if (rc) |