mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
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.
This commit is contained in:
parent
4e391d95e0
commit
2a13f7f9dc
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
#include "tlv.h"
|
||||||
#include "ksba-io-support.h"
|
#include "ksba-io-support.h"
|
||||||
|
|
||||||
|
|
||||||
@ -65,6 +66,12 @@ struct reader_cb_parm_s
|
|||||||
int autodetect; /* Try to detect the input encoding. */
|
int autodetect; /* Try to detect the input encoding. */
|
||||||
int assume_pem; /* Assume input encoding is PEM. */
|
int assume_pem; /* Assume input encoding is PEM. */
|
||||||
int assume_base64; /* Assume input is base64 encoded. */
|
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 identified;
|
||||||
int is_pem;
|
int is_pem;
|
||||||
@ -390,6 +397,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
|
static int
|
||||||
simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
|
simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
|
||||||
@ -402,8 +458,54 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
|
|||||||
if (!buffer)
|
if (!buffer)
|
||||||
return -1; /* not supported */
|
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++)
|
for (n=0; n < count; n++)
|
||||||
{
|
{
|
||||||
|
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);
|
c = es_getc (parm->fp);
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
{
|
{
|
||||||
@ -417,6 +519,7 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
|
|||||||
*(byte *)buffer++ = c;
|
*(byte *)buffer++ = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
*nread = n;
|
*nread = n;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -575,6 +678,7 @@ base64_finish_write (struct writer_cb_parm_s *parm)
|
|||||||
* GNUPG_KSBA_IO_MULTIPEM - The reader expects that the caller uses
|
* GNUPG_KSBA_IO_MULTIPEM - The reader expects that the caller uses
|
||||||
* ksba_reader_clear after EOF until no more
|
* ksba_reader_clear after EOF until no more
|
||||||
* objects were found.
|
* 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
|
* Note that the PEM flag has a higher priority than the BASE64 flag
|
||||||
* which in turn has a gight priority than the AUTODETECT flag.
|
* which in turn has a gight priority than the AUTODETECT flag.
|
||||||
@ -592,6 +696,7 @@ gnupg_ksba_create_reader (gnupg_ksba_io_t *ctx,
|
|||||||
if (!*ctx)
|
if (!*ctx)
|
||||||
return out_of_core ();
|
return out_of_core ();
|
||||||
(*ctx)->u.rparm.allow_multi_pem = !!(flags & GNUPG_KSBA_IO_MULTIPEM);
|
(*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);
|
rc = ksba_reader_new (&r);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#define GNUPG_KSBA_IO_BASE64 2 /* Plain Base64 format. */
|
#define GNUPG_KSBA_IO_BASE64 2 /* Plain Base64 format. */
|
||||||
#define GNUPG_KSBA_IO_AUTODETECT 4 /* Try to autodetect the 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_MULTIPEM 8 /* Allow more than one PEM chunk. */
|
||||||
|
#define GNUPG_KSBA_IO_STRIP 16 /* Strip off zero padding. */
|
||||||
|
|
||||||
|
|
||||||
/* Context object. */
|
/* Context object. */
|
||||||
|
@ -156,8 +156,7 @@ gpg_error_t
|
|||||||
parse_ber_header (unsigned char const **buffer, size_t *size,
|
parse_ber_header (unsigned char const **buffer, size_t *size,
|
||||||
int *r_class, int *r_tag,
|
int *r_class, int *r_tag,
|
||||||
int *r_constructed, int *r_ndef,
|
int *r_constructed, int *r_ndef,
|
||||||
size_t *r_length, size_t *r_nhdr)
|
size_t *r_length, size_t *r_nhdr){
|
||||||
{
|
|
||||||
int c;
|
int c;
|
||||||
unsigned long tag;
|
unsigned long tag;
|
||||||
const unsigned char *buf = *buffer;
|
const unsigned char *buf = *buffer;
|
||||||
|
@ -492,8 +492,10 @@ This usually means that Dirmngr is employed to search for the
|
|||||||
certificate. Note that this option makes a "web bug" like behavior
|
certificate. Note that this option makes a "web bug" like behavior
|
||||||
possible. LDAP server operators can see which keys you request, so by
|
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
|
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
|
will not have on your local keybox), the operator can tell both your
|
||||||
address and the time when you verified the signature.
|
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}
|
@anchor{gpgsm-option --validation-model}
|
||||||
|
10
sm/verify.c
10
sm/verify.c
@ -105,12 +105,17 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
|
|||||||
int signer;
|
int signer;
|
||||||
const char *algoid;
|
const char *algoid;
|
||||||
int algo;
|
int algo;
|
||||||
int is_detached;
|
int is_detached, maybe_detached;
|
||||||
estream_t in_fp = NULL;
|
estream_t in_fp = NULL;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
audit_set_type (ctrl->audit, AUDIT_TYPE_VERIFY);
|
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 idea of
|
||||||
|
* what to verify. */
|
||||||
|
maybe_detached = (data_fd != -1);
|
||||||
|
|
||||||
kh = keydb_new (ctrl);
|
kh = keydb_new (ctrl);
|
||||||
if (!kh)
|
if (!kh)
|
||||||
{
|
{
|
||||||
@ -131,7 +136,8 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
|
|||||||
rc = gnupg_ksba_create_reader
|
rc = gnupg_ksba_create_reader
|
||||||
(&b64reader, ((ctrl->is_pem? GNUPG_KSBA_IO_PEM : 0)
|
(&b64reader, ((ctrl->is_pem? GNUPG_KSBA_IO_PEM : 0)
|
||||||
| (ctrl->is_base64? GNUPG_KSBA_IO_BASE64 : 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);
|
in_fp, &reader);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user