aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/audit.c1
-rw-r--r--common/ksba-io-support.c107
-rw-r--r--common/ksba-io-support.h1
-rw-r--r--common/openpgp-oid.c26
-rw-r--r--common/recsel.c3
-rw-r--r--common/sexputil.c5
-rw-r--r--common/status.c3
-rw-r--r--common/tlv.c3
8 files changed, 137 insertions, 12 deletions
diff --git a/common/audit.c b/common/audit.c
index 803523c94..ae0d45216 100644
--- a/common/audit.c
+++ b/common/audit.c
@@ -1109,6 +1109,7 @@ proc_type_verify (audit_ctx_t ctx)
case GPG_ERR_CERT_REVOKED: ok = "bad"; break;
case GPG_ERR_NOT_ENABLED: ok = "disabled"; break;
case GPG_ERR_NO_CRL_KNOWN:
+ case GPG_ERR_INV_CRL_OBJ:
ok = _("no CRL found for certificate");
break;
case GPG_ERR_CRL_TOO_OLD:
diff --git a/common/ksba-io-support.c b/common/ksba-io-support.c
index 2832a4f3d..a279b67ad 100644
--- a/common/ksba-io-support.c
+++ b/common/ksba-io-support.c
@@ -40,6 +40,7 @@
#include "util.h"
#include "i18n.h"
+#include "tlv.h"
#include "ksba-io-support.h"
@@ -65,6 +66,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;
@@ -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
simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
@@ -402,9 +458,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;
@@ -417,6 +519,7 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
*(byte *)buffer++ = c;
}
+ leave:
*nread = n;
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
* 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.
@@ -592,6 +696,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 e33e0ed74..02e541b16 100644
--- a/common/ksba-io-support.h
+++ b/common/ksba-io-support.h
@@ -36,6 +36,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/common/openpgp-oid.c b/common/openpgp-oid.c
index f0460b068..510e09f4a 100644
--- a/common/openpgp-oid.c
+++ b/common/openpgp-oid.c
@@ -48,6 +48,8 @@ static struct {
{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519", PUBKEY_ALGO_ECDH },
{ "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519", PUBKEY_ALGO_EDDSA },
+ { "Curve25519", "1.3.101.110", 255, "cv25519", PUBKEY_ALGO_ECDH },
+ { "Ed25519", "1.3.101.112", 255, "ed25519", PUBKEY_ALGO_EDDSA },
{ "X448", "1.3.101.111", 448, "cv448", PUBKEY_ALGO_ECDH },
{ "Ed448", "1.3.101.113", 456, "ed448", PUBKEY_ALGO_EDDSA },
@@ -65,13 +67,17 @@ static struct {
};
-/* The OID for Curve Ed25519 in OpenPGP format. */
+/* The OID for Curve Ed25519 in OpenPGP format. The shorter v5
+ * variant may only be used with v5 keys. */
static const char oid_ed25519[] =
{ 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 };
+static const char oid_ed25519_v5[] = { 0x03, 0x2b, 0x65, 0x70 };
-/* The OID for Curve25519 in OpenPGP format. */
+/* The OID for Curve25519 in OpenPGP format. The shorter v5
+ * variant may only be used with v5 keys. */
static const char oid_cv25519[] =
{ 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 };
+static const char oid_cv25519_v5[] = { 0x03, 0x2b, 0x65, 0x6e };
/* The OID for X448 in OpenPGP format. */
/*
@@ -321,8 +327,12 @@ openpgp_oid_to_str (gcry_mpi_t a)
int
openpgp_oidbuf_is_ed25519 (const void *buf, size_t len)
{
- return (buf && len == DIM (oid_ed25519)
- && !memcmp (buf, oid_ed25519, DIM (oid_ed25519)));
+ if (!buf)
+ return 0;
+ return ((len == DIM (oid_ed25519)
+ && !memcmp (buf, oid_ed25519, DIM (oid_ed25519)))
+ || (len == DIM (oid_ed25519_v5)
+ && !memcmp (buf, oid_ed25519_v5, DIM (oid_ed25519_v5))));
}
@@ -345,8 +355,12 @@ openpgp_oid_is_ed25519 (gcry_mpi_t a)
int
openpgp_oidbuf_is_cv25519 (const void *buf, size_t len)
{
- return (buf && len == DIM (oid_cv25519)
- && !memcmp (buf, oid_cv25519, DIM (oid_cv25519)));
+ if (!buf)
+ return 0;
+ return ((len == DIM (oid_cv25519)
+ && !memcmp (buf, oid_cv25519, DIM (oid_cv25519)))
+ || (len == DIM (oid_cv25519_v5)
+ && !memcmp (buf, oid_cv25519_v5, DIM (oid_cv25519_v5))));
}
diff --git a/common/recsel.c b/common/recsel.c
index 60da4d3c9..ea0858c84 100644
--- a/common/recsel.c
+++ b/common/recsel.c
@@ -174,6 +174,7 @@ find_next_lc (char *string)
* -c The string match in this part is done case-sensitive.
* -t Do not trim leading and trailing spaces from VALUE.
* Note that a space after <op> is here required.
+ * -r RFU: String match uses a regular expression
*
* For example four calls to recsel_parse_expr() with these values for
* EXPR
@@ -192,7 +193,7 @@ find_next_lc (char *string)
*
* The caller must pass the address of a selector variable to this
* function and initialize the value of the function to NULL before
- * the first call. recset_release needs to be called to free the
+ * the first call. recsel_release needs to be called to free the
* selector.
*/
gpg_error_t
diff --git a/common/sexputil.c b/common/sexputil.c
index b7ddea8fc..29fe508b6 100644
--- a/common/sexputil.c
+++ b/common/sexputil.c
@@ -536,7 +536,8 @@ get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
return err;
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
return err;
- if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
+ if (!tok || !((toklen == 10 && !memcmp ("public-key", tok, toklen))
+ || (toklen == 11 && !memcmp ("private-key", tok, toklen))))
return gpg_error (GPG_ERR_BAD_PUBKEY);
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
return err;
@@ -1075,6 +1076,8 @@ pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid)
l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
if (!l1)
+ l1 = gcry_sexp_find_token (s_pkey, "private-key", 0);
+ if (!l1)
return xtrystrdup ("E_no_key");
{
gcry_sexp_t l_tmp = gcry_sexp_cadr (l1);
diff --git a/common/status.c b/common/status.c
index b752c12c6..b7dc1de39 100644
--- a/common/status.c
+++ b/common/status.c
@@ -158,7 +158,8 @@ get_inv_recpsgnr_code (gpg_error_t err)
case GPG_ERR_WRONG_KEY_USAGE: errstr = "3"; break;
case GPG_ERR_CERT_REVOKED: errstr = "4"; break;
case GPG_ERR_CERT_EXPIRED: errstr = "5"; break;
- case GPG_ERR_NO_CRL_KNOWN: errstr = "6"; break;
+ case GPG_ERR_NO_CRL_KNOWN:
+ case GPG_ERR_INV_CRL_OBJ: errstr = "6"; break;
case GPG_ERR_CRL_TOO_OLD: errstr = "7"; break;
case GPG_ERR_NO_POLICY_MATCH: errstr = "8"; break;
diff --git a/common/tlv.c b/common/tlv.c
index 9618d04cb..4cc1dc7cf 100644
--- a/common/tlv.c
+++ b/common/tlv.c
@@ -156,8 +156,7 @@ gpg_error_t
parse_ber_header (unsigned char const **buffer, size_t *size,
int *r_class, int *r_tag,
int *r_constructed, int *r_ndef,
- size_t *r_length, size_t *r_nhdr)
-{
+ size_t *r_length, size_t *r_nhdr){
int c;
unsigned long tag;
const unsigned char *buf = *buffer;