mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Allow verification of some broken S-TRUST generated signatures.
This commit is contained in:
parent
aeb5a65f7c
commit
9d66580cff
3
NEWS
3
NEWS
@ -23,6 +23,9 @@ Noteworthy changes in version 2.0.8
|
|||||||
|
|
||||||
* Creating DSA2 keys is now possible.
|
* 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)
|
Noteworthy changes in version 2.0.7 (2007-09-10)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
@ -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>
|
2007-12-11 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* asshelp.c (send_pinentry_environment): Allow using of old
|
* asshelp.c (send_pinentry_environment): Allow using of old
|
||||||
@ -1126,7 +1132,8 @@
|
|||||||
(atoi_1,atoi_2,atoi_4,xtoi_1,xtoi_2): New.
|
(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
|
This file is free software; as a special exception the author gives
|
||||||
unlimited permission to copy and/or distribute it, with or without
|
unlimited permission to copy and/or distribute it, with or without
|
||||||
|
@ -107,7 +107,7 @@ status-codes.h: Makefile mkstrtable.awk exstatus.awk status.h
|
|||||||
#
|
#
|
||||||
# Module tests
|
# 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
|
module_maint_tests = t-helpfile
|
||||||
|
|
||||||
t_common_ldadd = libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a \
|
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_gettime_LDADD = $(t_common_ldadd)
|
||||||
t_sysutils_LDADD = $(t_common_ldadd)
|
t_sysutils_LDADD = $(t_common_ldadd)
|
||||||
t_helpfile_LDADD = $(t_common_ldadd)
|
t_helpfile_LDADD = $(t_common_ldadd)
|
||||||
|
t_sexputil_LDADD = $(t_common_ldadd)
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ snext (unsigned char const **buf)
|
|||||||
lists and may be passed as a positive number to skip over the
|
lists and may be passed as a positive number to skip over the
|
||||||
remainder of an S-Expression if the current position is somewhere
|
remainder of an S-Expression if the current position is somewhere
|
||||||
in an S-Expression. The function may return an error code if it
|
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
|
static inline gpg_error_t
|
||||||
sskip (unsigned char const **buf, int *depth)
|
sskip (unsigned char const **buf, int *depth)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* sexputil.c - Utility functions for S-expressions.
|
/* 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.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -40,8 +40,8 @@
|
|||||||
KEY is expected to be an canonical encoded S-expression with a
|
KEY is expected to be an canonical encoded S-expression with a
|
||||||
public or private key. KEYLEN is the length of that buffer.
|
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
|
GRIP must be at least 20 bytes long. On success 0 is returned, on
|
||||||
error an aerror code. */
|
error an error code. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
|
keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
|
||||||
unsigned char *grip)
|
unsigned char *grip)
|
||||||
@ -143,3 +143,49 @@ make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
|
|||||||
|
|
||||||
return buf;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
82
common/t-sexputil.c
Normal file
82
common/t-sexputil.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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);
|
int cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b);
|
||||||
unsigned char *make_simple_sexp_from_hexstr (const char *line,
|
unsigned char *make_simple_sexp_from_hexstr (const char *line,
|
||||||
size_t *nscanned);
|
size_t *nscanned);
|
||||||
|
int hash_algo_from_sigval (const unsigned char *sigval);
|
||||||
|
|
||||||
/*-- convert.c --*/
|
/*-- convert.c --*/
|
||||||
int hex2bin (const char *string, void *buffer, size_t length);
|
int hex2bin (const char *string, void *buffer, size_t length);
|
||||||
|
@ -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>
|
2007-12-04 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* help.txt: New online help file.
|
* help.txt: New online help file.
|
||||||
|
@ -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
|
fingerprint and this flag may only be added manually to
|
||||||
@file{trustlist.txt}.
|
@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
|
@end itemize
|
||||||
|
|
||||||
|
@ -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
|
# 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
|
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
|
#Serial number: 00
|
||||||
# Issuer: /CN=CA Cert Signing Authority/OU=http:\x2f\x2fwww.
|
# Issuer: /CN=CA Cert Signing Authority/OU=http:\x2f\x2fwww.
|
||||||
# cacert.org/O=Root CA/EMail=support@cacert.org
|
# cacert.org/O=Root CA/EMail=support@cacert.org
|
||||||
|
12
doc/gpg.texi
12
doc/gpg.texi
@ -113,7 +113,7 @@ Developer information:
|
|||||||
@node GPG Commands
|
@node GPG Commands
|
||||||
@section 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.
|
only one command is allowed.
|
||||||
|
|
||||||
@command{@gpgname} may be run with no commands, in which case it will
|
@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
|
@node GPG Configuration Options
|
||||||
@subsection How to change the configuration
|
@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.
|
in the option file.
|
||||||
|
|
||||||
@table @gnupgtabopt
|
@table @gnupgtabopt
|
||||||
@ -2456,13 +2456,13 @@ listed. @option{--list-config} is only usable with
|
|||||||
|
|
||||||
@item --gpgconf-list
|
@item --gpgconf-list
|
||||||
@opindex 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.
|
internally used by the @command{gpgconf} tool.
|
||||||
|
|
||||||
@item --gpgconf-test
|
@item --gpgconf-test
|
||||||
@opindex gpgconf-test
|
@opindex gpgconf-test
|
||||||
This is more or less dummy action. However it parses the configuration
|
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
|
@command{gpg} from startup. Thus it may be used to run a syntax check
|
||||||
on the configuration file.
|
on the configuration file.
|
||||||
|
|
||||||
@ -2560,7 +2560,7 @@ For existing users the a small
|
|||||||
helper script is provided to create these files (@pxref{addgnupghome}).
|
helper script is provided to create these files (@pxref{addgnupghome}).
|
||||||
@end ifclear
|
@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
|
files; They all live in in the current home directory (@pxref{option
|
||||||
--homedir}). Only the @command{@gpgname} may modify these files.
|
--homedir}). Only the @command{@gpgname} may modify these files.
|
||||||
|
|
||||||
@ -2686,7 +2686,7 @@ user for the filename.
|
|||||||
@include specify-user-id.texi
|
@include specify-user-id.texi
|
||||||
@end ifset
|
@end ifset
|
||||||
|
|
||||||
@mansect return vaue
|
@mansect return value
|
||||||
@chapheading RETURN VALUE
|
@chapheading RETURN VALUE
|
||||||
|
|
||||||
The program returns 0 if everything was fine, 1 if at least
|
The program returns 0 if everything was fine, 1 if at least
|
||||||
|
@ -569,6 +569,19 @@ encryption. For convenience the strings @code{3DES}, @code{AES} and
|
|||||||
|
|
||||||
@table @gnupgtabopt
|
@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}
|
@item --faked-system-time @var{epoch}
|
||||||
@opindex faked-system-time
|
@opindex faked-system-time
|
||||||
This option is only useful for testing; it sets the system time back or
|
This option is only useful for testing; it sets the system time back or
|
||||||
|
@ -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
|
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
|
||||||
|
|
||||||
|
|
||||||
#*******************************************
|
#*******************************************
|
||||||
|
@ -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.
|
@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
|
representation of the serial number, then followed by a slash and the
|
||||||
RFC-2253 encoded DN of the issuer. See note above.
|
RFC-2253 encoded DN of the issuer. See note above.
|
||||||
|
|
||||||
|
@ -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>
|
2007-12-11 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* certchain.c (do_validate_chain): Log AUDIT_ROOT_TRUSTED.
|
* certchain.c (do_validate_chain): Log AUDIT_ROOT_TRUSTED.
|
||||||
|
13
sm/gpgsm.c
13
sm/gpgsm.c
@ -174,6 +174,7 @@ enum cmd_and_opt_values {
|
|||||||
oOpenPGP,
|
oOpenPGP,
|
||||||
oCipherAlgo,
|
oCipherAlgo,
|
||||||
oDigestAlgo,
|
oDigestAlgo,
|
||||||
|
oExtraDigestAlgo,
|
||||||
oCompressAlgo,
|
oCompressAlgo,
|
||||||
oCommandFD,
|
oCommandFD,
|
||||||
oNoVerbose,
|
oNoVerbose,
|
||||||
@ -388,6 +389,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
{ oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
|
{ oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
|
||||||
{ oDigestAlgo, "digest-algo", 2 ,
|
{ oDigestAlgo, "digest-algo", 2 ,
|
||||||
N_("|NAME|use message digest algorithm NAME")},
|
N_("|NAME|use message digest algorithm NAME")},
|
||||||
|
{ oExtraDigestAlgo, "extra-digest-algo", 2 , "@" },
|
||||||
#if 0
|
#if 0
|
||||||
{ oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
|
{ oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
|
||||||
#endif
|
#endif
|
||||||
@ -842,6 +844,7 @@ main ( int argc, char **argv)
|
|||||||
int use_random_seed = 1;
|
int use_random_seed = 1;
|
||||||
int with_fpr = 0;
|
int with_fpr = 0;
|
||||||
char *def_digest_string = NULL;
|
char *def_digest_string = NULL;
|
||||||
|
char *extra_digest_algo = NULL;
|
||||||
enum cmd_and_opt_values cmd = 0;
|
enum cmd_and_opt_values cmd = 0;
|
||||||
struct server_control_s ctrl;
|
struct server_control_s ctrl;
|
||||||
certlist_t recplist = NULL;
|
certlist_t recplist = NULL;
|
||||||
@ -1298,6 +1301,10 @@ main ( int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case oExtraDigestAlgo:
|
||||||
|
extra_digest_algo = pargs.r.ret_str;
|
||||||
|
break;
|
||||||
|
|
||||||
case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
|
case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
|
||||||
case oNoRandomSeedFile: use_random_seed = 0; 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) )
|
if (our_md_test_algo(opt.def_digest_algo) )
|
||||||
log_error (_("selected digest algorithm is invalid\n"));
|
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))
|
if (log_get_errorcount(0))
|
||||||
|
@ -92,6 +92,9 @@ struct
|
|||||||
|
|
||||||
char *local_user; /* NULL or argument to -u */
|
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
|
int always_trust; /* Trust the given keys even if there is no
|
||||||
valid certification chain */
|
valid certification chain */
|
||||||
int skip_verify; /* do not check signatures on data */
|
int skip_verify; /* do not check signatures on data */
|
||||||
|
@ -491,7 +491,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
|
|||||||
unsigned char *digest;
|
unsigned char *digest;
|
||||||
size_t digest_len;
|
size_t digest_len;
|
||||||
/* Fixme do this for all signers and get the algo to use from
|
/* 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. */
|
should do this consistent as we have already done it above. */
|
||||||
algo = GCRY_MD_SHA1;
|
algo = GCRY_MD_SHA1;
|
||||||
hash_data (data_fd, data_md);
|
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
|
/* 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:
|
RC2. Our list is:
|
||||||
|
|
||||||
aes128-CBC
|
aes128-CBC
|
||||||
|
38
sm/verify.c
38
sm/verify.c
@ -203,10 +203,20 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (DBG_X509)
|
||||||
|
log_debug ("enabling hash algorithm %d (%s)\n",
|
||||||
|
algo, algoid? algoid:"");
|
||||||
gcry_md_enable (data_md, algo);
|
gcry_md_enable (data_md, algo);
|
||||||
audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, 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 (is_detached)
|
||||||
{
|
{
|
||||||
if (data_fd == -1)
|
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;
|
char *msgdigest = NULL;
|
||||||
size_t msgdigestlen;
|
size_t msgdigestlen;
|
||||||
char *ctattr;
|
char *ctattr;
|
||||||
|
int sigval_hash_algo;
|
||||||
int info_pkalgo;
|
int info_pkalgo;
|
||||||
unsigned int verifyflags;
|
unsigned int verifyflags;
|
||||||
|
|
||||||
@ -331,7 +342,8 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
|
|||||||
&algo, &is_enabled)
|
&algo, &is_enabled)
|
||||||
|| !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");
|
audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "unsupported");
|
||||||
goto next_signer;
|
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");
|
audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
|
||||||
goto next_signer;
|
goto next_signer;
|
||||||
}
|
}
|
||||||
|
sigval_hash_algo = hash_algo_from_sigval (sigval);
|
||||||
if (DBG_X509)
|
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 */
|
/* Find the certificate of the signer */
|
||||||
keydb_search_reset (kh);
|
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;
|
gcry_md_hd_t md;
|
||||||
unsigned char *s;
|
unsigned char *s;
|
||||||
|
|
||||||
/* check that the message digest in the signed attributes
|
/* Check that the message digest in the signed attributes
|
||||||
matches the one we calculated on the data */
|
matches the one we calculated on the data. */
|
||||||
s = gcry_md_read (data_md, algo);
|
s = gcry_md_read (data_md, algo);
|
||||||
if ( !s || !msgdigestlen
|
if ( !s || !msgdigestlen
|
||||||
|| gcry_md_get_algo_dlen (algo) != 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;
|
goto next_signer;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = gcry_md_open (&md, algo, 0);
|
rc = gcry_md_open (&md, sigval_hash_algo, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error ("md_open failed: %s\n", gpg_strerror (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");
|
audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
|
||||||
goto next_signer;
|
goto next_signer;
|
||||||
}
|
}
|
||||||
rc = gpgsm_check_cms_signature (cert, sigval, md, algo,
|
rc = gpgsm_check_cms_signature (cert, sigval, md,
|
||||||
&info_pkalgo);
|
sigval_hash_algo, &info_pkalgo);
|
||||||
gcry_md_close (md);
|
gcry_md_close (md);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo,
|
rc = gpgsm_check_cms_signature (cert, sigval, data_md,
|
||||||
&info_pkalgo);
|
algo, &info_pkalgo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user