aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2023-03-08 09:57:25 +0000
committerWerner Koch <[email protected]>2023-09-07 14:38:35 +0000
commit6bdf11f6715086bb7de4dc3b6d2ea0a307f4653e (patch)
tree9cf0de46192afe885481ba7e4541ac8f776ddb73
parentdoc: Add missing NEWS entry for next release (diff)
downloadgnupg-6bdf11f6715086bb7de4dc3b6d2ea0a307f4653e.tar.gz
gnupg-6bdf11f6715086bb7de4dc3b6d2ea0a307f4653e.zip
gpgsm: Strip trailing zeroes from detached signatures.
* common/ksba-io-support.c: Include tlv.h (struct reader_cb_parm_s): Add new fields. (starts_with_sequence): New. (simple_reader_cb): Handle stripping. * common/ksba-io-support.h (GNUPG_KSBA_IO_STRIP): New. (gnupg_ksba_create_reader): Handle the new flag. * sm/verify.c (gpgsm_verify): Use the new flag for detached signatures. -- Note that this works only if --assume-binary is given. The use case for the feature is PDF signature checking where the PDF specs require that the detached signature is padded with zeroes. (cherry picked from commit 2a13f7f9dc75265ece649e30fecd3dc694b1240e)
-rw-r--r--common/ksba-io-support.c107
-rw-r--r--common/ksba-io-support.h1
-rw-r--r--doc/gpgsm.texi6
-rw-r--r--sm/verify.c10
4 files changed, 119 insertions, 5 deletions
diff --git a/common/ksba-io-support.c b/common/ksba-io-support.c
index a23608164..352485ffa 100644
--- a/common/ksba-io-support.c
+++ b/common/ksba-io-support.c
@@ -41,6 +41,7 @@
#include "util.h"
#include "i18n.h"
+#include "tlv.h"
#include "ksba-io-support.h"
@@ -66,6 +67,12 @@ struct reader_cb_parm_s
int autodetect; /* Try to detect the input encoding. */
int assume_pem; /* Assume input encoding is PEM. */
int assume_base64; /* Assume input is base64 encoded. */
+ int strip_zeroes; /* Expect a SEQUENCE followed by zero padding. */
+ /* 1 = check state; 2 = reading; 3 = checking */
+ /* for zeroes. */
+ int use_maxread; /* If true read not more than MAXREAD. */
+ unsigned int maxread; /* # of bytes left to read. */
+ off_t nzeroes; /* Number of padding zeroes red. */
int identified;
int is_pem;
@@ -401,6 +408,55 @@ base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
}
+/* Read up to 10 bytes to test whether the data consist of a sequence;
+ * if that is true, set the limited flag and record the length of the
+ * entire sequence in PARM. Unget everything then. Return true if we
+ * have a sequence with a fixed length. */
+static int
+starts_with_sequence (struct reader_cb_parm_s *parm)
+{
+ gpg_error_t err;
+ unsigned char peekbuf[10];
+ int npeeked, c;
+ int found = 0;
+ const unsigned char *p;
+ size_t n, objlen, hdrlen;
+ int class, tag, constructed, ndef;
+
+ for (npeeked=0; npeeked < sizeof peekbuf; npeeked++)
+ {
+ c = es_getc (parm->fp);
+ if (c == EOF)
+ goto leave;
+ peekbuf[npeeked] = c;
+ }
+ /* Enough to check for a sequence. */
+
+ p = peekbuf;
+ n = npeeked;
+ err = parse_ber_header (&p, &n, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (err)
+ {
+ log_debug ("%s: error parsing data: %s\n", __func__, gpg_strerror (err));
+ goto leave;
+ }
+
+ if (class == CLASS_UNIVERSAL && constructed && tag == TAG_SEQUENCE && !ndef)
+ {
+ /* We need to add 1 due to the way we implement the limit. */
+ parm->maxread = objlen + hdrlen + 1;
+ if (!(parm->maxread < objlen + hdrlen) && parm->maxread)
+ parm->use_maxread = 1;
+ found = 1;
+ }
+
+ leave:
+ while (npeeked)
+ es_ungetc (peekbuf[--npeeked], parm->fp);
+ return found;
+}
+
static int
simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
@@ -413,9 +469,55 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
if (!buffer)
return -1; /* not supported */
+ restart:
+ if (parm->strip_zeroes)
+ {
+ if (parm->strip_zeroes == 1)
+ {
+ if (starts_with_sequence (parm))
+ parm->strip_zeroes = 2; /* Found fixed length sequence. */
+ else
+ parm->strip_zeroes = 0; /* Disable zero padding check. */
+ }
+ else if (parm->strip_zeroes == 3)
+ {
+ /* Limit reached - check that only zeroes follow. */
+ while (!(c = es_getc (parm->fp)))
+ parm->nzeroes++;
+ if (c == EOF)
+ { /* only zeroes found. Reset zero padding engine and
+ * return EOF. */
+ parm->strip_zeroes = 0;
+ parm->eof_seen = 1;
+ return -1;
+ }
+ /* Not only zeroes. Reset engine and continue. */
+ parm->strip_zeroes = 0;
+ }
+ }
+
for (n=0; n < count; n++)
{
- c = es_getc (parm->fp);
+ if (parm->use_maxread && !--parm->maxread)
+ {
+ parm->use_maxread = 0;
+ if (parm->strip_zeroes)
+ {
+ parm->strip_zeroes = 3;
+ parm->nzeroes = 0;
+ if (n)
+ goto leave; /* Return what we already got. */
+ goto restart; /* Immediately check for trailing zeroes. */
+ }
+ }
+
+ if (parm->nzeroes)
+ {
+ parm->nzeroes--;
+ c = 0;
+ }
+ else
+ c = es_getc (parm->fp);
if (c == EOF)
{
parm->eof_seen = 1;
@@ -428,6 +530,7 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
*(byte *)buffer++ = c;
}
+ leave:
*nread = n;
return 0;
}
@@ -626,6 +729,7 @@ base64_finish_write (struct writer_cb_parm_s *parm)
* GNUPG_KSBA_IO_MULTIPEM - The reader expects that the caller uses
* ksba_reader_clear after EOF until no more
* objects were found.
+ * GNUPG_KSBA_IO_STRIP - Strip zero padding from some CMS objects.
*
* Note that the PEM flag has a higher priority than the BASE64 flag
* which in turn has a gight priority than the AUTODETECT flag.
@@ -643,6 +747,7 @@ gnupg_ksba_create_reader (gnupg_ksba_io_t *ctx,
if (!*ctx)
return out_of_core ();
(*ctx)->u.rparm.allow_multi_pem = !!(flags & GNUPG_KSBA_IO_MULTIPEM);
+ (*ctx)->u.rparm.strip_zeroes = !!(flags & GNUPG_KSBA_IO_STRIP);
rc = ksba_reader_new (&r);
if (rc)
diff --git a/common/ksba-io-support.h b/common/ksba-io-support.h
index f309e6647..1dbc303c8 100644
--- a/common/ksba-io-support.h
+++ b/common/ksba-io-support.h
@@ -37,6 +37,7 @@
#define GNUPG_KSBA_IO_BASE64 2 /* Plain Base64 format. */
#define GNUPG_KSBA_IO_AUTODETECT 4 /* Try to autodetect the format. */
#define GNUPG_KSBA_IO_MULTIPEM 8 /* Allow more than one PEM chunk. */
+#define GNUPG_KSBA_IO_STRIP 16 /* Strip off zero padding. */
/* Context object. */
diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi
index c5cfd254c..03fe1c9e6 100644
--- a/doc/gpgsm.texi
+++ b/doc/gpgsm.texi
@@ -480,8 +480,10 @@ This usually means that Dirmngr is employed to search for the
certificate. Note that this option makes a "web bug" like behavior
possible. LDAP server operators can see which keys you request, so by
sending you a message signed by a brand new key (which you naturally
-will not have on your local keybox), the operator can tell both your IP
-address and the time when you verified the signature.
+will not have on your local keybox), the operator can tell both your
+IP address and the time when you verified the signature. Note that if
+CRL checking is not disabled issuer certificates are retrieved in any
+case using the caIssuers authorityInfoAccess method.
@anchor{gpgsm-option --validation-model}
diff --git a/sm/verify.c b/sm/verify.c
index 6840ed16b..b092b90da 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -106,12 +106,17 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
int signer;
const char *algoid;
int algo;
- int is_detached;
+ int is_detached, maybe_detached;
estream_t in_fp = NULL;
char *p;
audit_set_type (ctrl->audit, AUDIT_TYPE_VERIFY);
+ /* Although we detect detached signatures during the parsing phase,
+ * we need to know it earlier and thus accept the caller's idea of
+ * what to verify. */
+ maybe_detached = (data_fd != -1);
+
kh = keydb_new ();
if (!kh)
{
@@ -132,7 +137,8 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
rc = gnupg_ksba_create_reader
(&b64reader, ((ctrl->is_pem? GNUPG_KSBA_IO_PEM : 0)
| (ctrl->is_base64? GNUPG_KSBA_IO_BASE64 : 0)
- | (ctrl->autodetect_encoding? GNUPG_KSBA_IO_AUTODETECT : 0)),
+ | (ctrl->autodetect_encoding? GNUPG_KSBA_IO_AUTODETECT : 0)
+ | (maybe_detached? GNUPG_KSBA_IO_STRIP : 0)),
in_fp, &reader);
if (rc)
{