diff --git a/src/der-builder.c b/src/der-builder.c
index b345e35..30df7e4 100644
--- a/src/der-builder.c
+++ b/src/der-builder.c
@@ -1,627 +1,647 @@
/* der-builder.c - Straightforward DER object builder
* Copyright (C) 2020 g10 Code GmbH
*
* This file is part of KSBA.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This file 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 Lesser General Public License
* along with this program; if not, see .
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
/* This is a new way in KSBA to build DER objects without the need and
* overhead of using an ASN.1 module. It further avoids a lot of error
* checking because the error checking is delayed to the last call.
*
* For an example on how to use it see cms.c
*/
#include
#include
#include
#include
#include
#include "util.h"
#include "asn1-constants.h"
#include "convert.h"
#include "ber-help.h"
#include "der-builder.h"
struct item_s
{
+ unsigned int tag;
short int class;
- short int tag;
- unsigned int hdrlen:4; /* Computed size of tag+length field. */
+ unsigned int hdrlen:12; /* Computed size of tag+length field. */
unsigned int is_constructed:1; /* This is a constructed element. */
unsigned int verbatim:1; /* Copy the value verbatim. */
unsigned int is_stop:1; /* This is a STOP item. */
const void *value;
size_t valuelen;
char *buffer; /* Malloced space or NULL. */
};
/* Our DER context object; it may eventually be extended to also
* feature a parser. */
struct ksba_der_s
{
gpg_error_t error; /* Last error. */
size_t nallocateditems; /* Number of allocated items. */
size_t nitems; /* Number of used items. */
struct item_s *items; /* Array of items. */
int laststop; /* Used as return value of compute_length. */
unsigned int finished:1;/* The object has been constructed. */
};
/* Release a DER object. */
void
_ksba_der_release (ksba_der_t d)
{
int idx;
if (!d)
return;
for (idx=0; idx < d->nitems; idx++)
xfree (d->items[idx].buffer);
xfree (d->items);
xfree (d);
}
/* Allocate a new DER builder instance. Returns NULL on error.
* NITEMS can be used to tell the number of DER items needed so to
* reduce the number of automatic reallocations. */
ksba_der_t
_ksba_der_builder_new (unsigned int nitems)
{
ksba_der_t d;
d = xtrycalloc (1, sizeof *d);
if (!d)
return NULL;
if (nitems)
{
d->nallocateditems = nitems;
d->items = xtrycalloc (d->nallocateditems, sizeof *d->items);
if (!d->items)
{
xfree (d);
return NULL;
}
}
return d;
}
/* Reset a DER build context so that a new sequence can be build. */
void
_ksba_der_builder_reset (ksba_der_t d)
{
int idx;
if (!d)
return; /* Oops. */
for (idx=0; idx < d->nitems; idx++)
{
if (d->items[idx].buffer)
{
xfree (d->items[idx].buffer);
d->items[idx].buffer = NULL;
}
d->items[idx].hdrlen = 0;
d->items[idx].is_constructed = 0;
d->items[idx].verbatim = 0;
d->items[idx].is_stop = 0;
d->items[idx].value = NULL;
}
d->nitems = 0;
d->finished = 0;
d->error = 0;
}
/* Make sure the array of items is large enough for one new item.
* Records any error in D and returns true in that case. True is also
* returned if D is in finished state. */
static int
ensure_space (ksba_der_t d)
{
struct item_s *newitems;
if (!d || d->error || d->finished)
return 1;
if (d->nitems == d->nallocateditems)
{
d->nallocateditems += 32;
newitems = _ksba_reallocarray (d->items, d->nitems,
d->nallocateditems, sizeof *newitems);
if (!newitems)
d->error = gpg_error_from_syserror ();
else
d->items = newitems;
}
return !!d->error;
}
/* Add a new primitive element to the builder instance D. The element
* is described by CLASS, TAG, VALUE, and VALUELEN. CLASS and TAG
* must describe a primitive element and (VALUE,VALUELEN) specify its
* value. The value is a pointer and its object must not be changed
* as long as the instance D exists. For a TYPE_NULL tag no value is
* expected. Errors are not returned but recorded for later
* retrieval. */
void
_ksba_der_add_ptr (ksba_der_t d, int class, int tag,
void *value, size_t valuelen)
{
if (ensure_space (d))
return;
d->items[d->nitems].class = class;
d->items[d->nitems].tag = tag;
d->items[d->nitems].value = value;
d->items[d->nitems].valuelen = valuelen;
d->nitems++;
}
/* This is a low level function which assumes that D has been
* validated, VALUE is not NULL and enough space for a new item is
* available. It takes ownership of VALUE. VERBATIM is usually
* passed as false */
static void
add_val_core (ksba_der_t d, int class, int tag, void *value, size_t valuelen,
int verbatim)
{
d->items[d->nitems].buffer = value;
d->items[d->nitems].class = class;
d->items[d->nitems].tag = tag;
d->items[d->nitems].value = value;
d->items[d->nitems].valuelen = valuelen;
d->items[d->nitems].verbatim = !!verbatim;
d->nitems++;
}
/* This is the same as ksba_der_add_ptr but it takes a copy of the
* value and thus the caller does not need to care about keeping the
* value. */
void
_ksba_der_add_val (ksba_der_t d, int class, int tag,
const void *value, size_t valuelen)
{
void *p;
if (ensure_space (d))
return;
if (!value || !valuelen)
{
d->error = gpg_error (GPG_ERR_INV_VALUE);
return;
}
p = xtrymalloc (valuelen);
if (!p)
{
d->error = gpg_error_from_syserror ();
return;
}
memcpy (p, value, valuelen);
add_val_core (d, class, tag, p, valuelen, 0);
}
/* Add an OBJECT ID element to D. The OID is given in decimal dotted
* format as OIDSTR. */
void
_ksba_der_add_oid (ksba_der_t d, const char *oidstr)
{
gpg_error_t err;
unsigned char *buf;
size_t len;
if (ensure_space (d))
return;
err = ksba_oid_from_str (oidstr, &buf, &len);
if (err)
d->error = err;
else
add_val_core (d, 0, TYPE_OBJECT_ID, buf, len, 0);
}
/* Add a BIT STRING to D. Using a separate function allows to easily
* pass the number of unused bits. */
void
_ksba_der_add_bts (ksba_der_t d, const void *value, size_t valuelen,
unsigned int unusedbits)
{
unsigned char *p;
if (ensure_space (d))
return;
if (!value || !valuelen || unusedbits > 7)
{
d->error = gpg_error (GPG_ERR_INV_VALUE);
return;
}
p = xtrymalloc (1+valuelen);
if (!p)
{
d->error = gpg_error_from_syserror ();
return;
}
p[0] = unusedbits;
memcpy (p+1, value, valuelen);
add_val_core (d, 0, TYPE_BIT_STRING, p, 1+valuelen, 0);
}
/* Add (VALUE, VALUELEN) as an INTEGER to D. If FORCE_POSITIVE iset
* set a 0 or positive number is stored regardless of what is in
* (VALUE, VALUELEN). */
void
_ksba_der_add_int (ksba_der_t d, const void *value, size_t valuelen,
int force_positive)
{
unsigned char *p;
int need_extra;
if (ensure_space (d))
return;
if (!value || !valuelen)
need_extra = 1; /* Assume the integer value 0 was meant. */
else
need_extra = (force_positive && (*(const unsigned char*)value & 0x80));
p = xtrymalloc (need_extra+valuelen);
if (!p)
{
d->error = gpg_error_from_syserror ();
return;
}
if (need_extra)
p[0] = 0;
if (valuelen)
memcpy (p+need_extra, value, valuelen);
add_val_core (d, 0, TYPE_INTEGER, p, need_extra+valuelen, 0);
}
/* This function allows to add a pre-constructed DER object to the
* builder. It should be a valid DER object but its values is not
* further checked and copied verbatim to the final DER object
* constructed for the handle D. */
void
_ksba_der_add_der (ksba_der_t d, const void *der, size_t derlen)
{
void *p;
if (ensure_space (d))
return;
if (!der || !derlen)
{
d->error = gpg_error (GPG_ERR_INV_VALUE);
return;
}
p = xtrymalloc (derlen);
if (!p)
{
d->error = gpg_error_from_syserror ();
return;
}
memcpy (p, der, derlen);
add_val_core (d, 0, 0, p, derlen, 1);
}
/* Add a new constructed object to the builder instance D. The object
* is described by CLASS and TAG which must describe a constructed
* object. The elements of the constructed objects are added with
* more call using the add functions. To close a constructed element
* a call to tlv_builer_add_end is required. Errors are not returned
* but recorded for later retrieval. */
void
_ksba_der_add_tag (ksba_der_t d, int class, int tag)
{
if (ensure_space (d))
return;
d->items[d->nitems].class = class;
d->items[d->nitems].tag = tag;
d->items[d->nitems].is_constructed = 1;
d->nitems++;
}
/* A call to this function closes a constructed element. This must be
* called even for an empty constructed element. */
void
_ksba_der_add_end (ksba_der_t d)
{
if (ensure_space (d))
return;
d->items[d->nitems].is_stop = 1;
d->nitems++;
}
/* Return the length of the TL header of a to be constructed TLV.
* LENGTH gives the length of the value, if it is 0 indefinite length
- * is assumed. LENGTH is ignored for the NULL tag. TAG must be less
- * than 0x1f. On error 0 is returned. Note that this function is
- * similar to _ksba_ber_count_tl but we want our own copy here. Note
- * that the returned length is always less than 16 and can thus be
- * storred in a few bits. */
+ * is assumed. LENGTH is ignored for the NULL tag. On error 0 is
+ * returned. Note that this function is similar to _ksba_ber_count_tl
+ * but we want our own copy here. */
static unsigned int
count_tl (int class, int tag, size_t length)
{
unsigned int hdrlen = 0;
- int i;
+ int i, t;
if (tag < 0x1f)
hdrlen++;
else
- return 0;
+ {
+ hdrlen++;
+
+ for (i = 0, t = tag; t > 0; i++)
+ t >>= 7;
+ hdrlen += i;
+ }
if (!tag && !class)
hdrlen++; /* end tag */
else if (tag == TYPE_NULL && !class)
hdrlen++; /* NULL tag */
else if (!length)
hdrlen++; /* indefinite length */
else if (length < 128)
hdrlen++;
else
{
i = (length <= 0xff ? 1:
length <= 0xffff ? 2:
length <= 0xffffff ? 3: 4);
hdrlen++;
if (i > 3)
hdrlen++;
if (i > 2)
hdrlen++;
if (i > 1)
hdrlen++;
hdrlen++;
}
return hdrlen;
}
/* Write TAG of CLASS to BUFFER. CONSTRUCTED is a flag telling
* whether the value is constructed. LENGTH gives the length of the
* value, if it is 0 undefinite length is assumed. LENGTH is ignored
* for the NULL tag. TAG must be less that 0x1f. The caller must
* make sure that the written TL field does not overflow the
* buffer. */
static void
write_tl (unsigned char *buffer, int class, int tag,
int constructed, size_t length)
{
- int i;
+ int i, savei, t;
if (tag < 0x1f)
{
*buffer = (class << 6) | tag;
if (constructed)
*buffer |= 0x20;
buffer++;
}
else
{
- assert (!"oops");
+ *buffer = (class << 6) | 0x1f;
+ if (constructed)
+ *buffer |= 0x20;
+ buffer++;
+
+ for (i = 0, t = tag; t > 0; i++)
+ t >>= 7;
+ savei = i;
+ t = tag;
+ while (i-- > 0)
+ {
+ buffer[i] = t & 0x7f;
+ if (i != savei - 1)
+ buffer[i] |= 0x80;
+ t >>= 7;
+ }
+ buffer += savei;
}
if (!tag && !class)
*buffer++ = 0; /* end tag */
else if (tag == TYPE_NULL && !class)
*buffer++ = 0; /* NULL tag */
else if (!length)
*buffer++ = 0x80; /* indefinite length */
else if (length < 128)
*buffer++ = length;
else
{
/* If we know the sizeof a size_t we could support larger
* objects - however this is pretty ridiculous */
i = (length <= 0xff ? 1:
length <= 0xffff ? 2:
length <= 0xffffff ? 3: 4);
*buffer++ = (0x80 | i);
if (i > 3)
*buffer++ = length >> 24;
if (i > 2)
*buffer++ = length >> 16;
if (i > 1)
*buffer++ = length >> 8;
*buffer++ = length;
}
}
/* Compute and set the length of all constructed elements in the item
* array of D starting at IDX up to the corresponding stop item. On
* error d->error is set. */
static size_t
compute_lengths (ksba_der_t d, int idx)
{
size_t total = 0;
if (d->error)
return 0;
for (; idx < d->nitems; idx++)
{
if (d->items[idx].is_stop)
{
d->laststop = idx;
break;
}
if (d->items[idx].verbatim)
{
total += d->items[idx].valuelen;
continue;
}
if (d->items[idx].is_constructed)
{
d->items[idx].valuelen = compute_lengths (d, idx+1);
if (d->error)
return 0;
/* Note: The last processed IDX is stored at d->LASTSTOP. */
}
d->items[idx].hdrlen = count_tl (d->items[idx].class,
d->items[idx].tag,
d->items[idx].valuelen);
if (!d->items[idx].hdrlen)
{
if (d->error)
d->error = gpg_error (GPG_ERR_ENCODING_PROBLEM);
return 0; /* Error. */
}
total += d->items[idx].hdrlen + d->items[idx].valuelen;
if (d->items[idx].is_constructed)
idx = d->laststop;
}
return total;
}
/* Return the constructed DER object at D. On success the object is
* stored at R_OBJ and its length at R_OBJLEN. The caller needs to
* release that memory. On error NULL is stored at R_OBJ and an error
* code is returned. Further the number of successful calls prior to
* the error are stored at R_OBJLEN. Note than an error may stem from
* any of the previous call made to this object or from constructing
* the DER object. If this function is called with NULL for R_OBJ
* only the current error state is returned and no further processing
* is done. This can be used to figure which of the add calls induced
* the error.
*/
gpg_error_t
_ksba_der_builder_get (ksba_der_t d, unsigned char **r_obj, size_t *r_objlen)
{
gpg_error_t err;
int idx;
unsigned char *buffer = NULL;
unsigned char *p;
size_t bufsize, buflen;
*r_obj = NULL;
*r_objlen = 0;
if (!d)
return gpg_error (GPG_ERR_INV_ARG);
if (d->error)
{
err = d->error;
if (r_objlen)
*r_objlen = d->nitems;
goto leave;
}
if (!r_obj)
return 0;
if (!d->finished)
{
if (d->nitems == 1)
; /* Single item does not need an end tag. */
else if (!d->nitems || !d->items[d->nitems-1].is_stop)
{
err = gpg_error (GPG_ERR_NO_OBJ);
goto leave;
}
compute_lengths (d, 0);
err = d->error;
if (err)
goto leave;
d->finished = 1;
}
/* If the first element is a primitive element we rightly assume no
* other elements follow. It is the user's duty to build a valid
* ASN.1 object. */
bufsize = d->items[0].hdrlen + d->items[0].valuelen;
/* for (idx=0; idx < d->nitems; idx++) */
/* gpgrt_log_debug ("DERB[%2d]: c=%d t=%2d %s p=%p h=%u l=%zu\n", */
/* idx, */
/* d->items[idx].class, */
/* d->items[idx].tag, */
/* d->items[idx].verbatim? "verbatim": */
/* d->items[idx].is_stop? "stop": */
/* d->items[idx].is_constructed? "cons":"prim", */
/* d->items[idx].value, */
/* d->items[idx].hdrlen, */
/* d->items[idx].valuelen); */
buffer = xtrymalloc (bufsize);
if (!buffer)
{
err = gpg_error_from_syserror ();
goto leave;
}
buflen = 0;
p = buffer;
for (idx=0; idx < d->nitems; idx++)
{
if (d->items[idx].is_stop)
continue;
if (!d->items[idx].verbatim)
{
if (buflen + d->items[idx].hdrlen > bufsize)
{
err = gpg_error (GPG_ERR_BUG);
goto leave;
}
write_tl (p, d->items[idx].class, d->items[idx].tag,
d->items[idx].is_constructed, d->items[idx].valuelen);
p += d->items[idx].hdrlen;
buflen += d->items[idx].hdrlen;
}
if (d->items[idx].value)
{
if (buflen + d->items[idx].valuelen > bufsize)
{
err = gpg_error (GPG_ERR_BUG);
goto leave;
}
memcpy (p, d->items[idx].value, d->items[idx].valuelen);
p += d->items[idx].valuelen;
buflen += d->items[idx].valuelen;
}
}
assert (buflen == bufsize);
*r_obj = buffer;
*r_objlen = buflen;
buffer = NULL;
leave:
xfree (buffer);
return err;
}
diff --git a/src/ksba.h.in b/src/ksba.h.in
index f9c91bb..a9f08b8 100644
--- a/src/ksba.h.in
+++ b/src/ksba.h.in
@@ -1,593 +1,636 @@
/* ksba.h - X.509 library used by GnuPG
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2010, 2011
* 2012, 2013, 2104, 2015, 2019 g10 Code GmbH
*
* This file is part of KSBA.
*
* KSBA is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* or both in parallel, as here.
*
* KSBA 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 copies of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, see .
*/
#ifndef KSBA_H
#define KSBA_H 1
#include
#include
#ifdef __cplusplus
extern "C" {
#if 0
}
#endif
#endif
/* The version of this header should match the one of the library. Do
* not use this symbol in your application; use assuan_check_version
* instead. */
#define KSBA_VERSION "@VERSION@"
/* The version number of this header. It may be used to handle minor
* API incompatibilities. */
#define KSBA_VERSION_NUMBER @VERSION_NUMBER@
/* Check for compiler features. */
#ifdef __GNUC__
#define _KSBA_GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#if _KSBA_GCC_VERSION > 30100
#define _KSBA_DEPRECATED __attribute__ ((__deprecated__))
#endif
#endif /*__GNUC__*/
#ifndef _KSBA_DEPRECATED
#define _KSBA_DEPRECATED
#endif
+#define KSBA_CLASS_UNIVERSAL 0
+#define KSBA_CLASS_APPLICATION 1
+#define KSBA_CLASS_CONTEXT 2
+#define KSBA_CLASS_PRIVATE 3
+
+#define KSBA_TYPE_BOOLEAN 1
+#define KSBA_TYPE_INTEGER 2
+#define KSBA_TYPE_BIT_STRING 3
+#define KSBA_TYPE_OCTET_STRING 4
+#define KSBA_TYPE_NULL 5
+#define KSBA_TYPE_OBJECT_ID 6
+#define KSBA_TYPE_OBJECT_DESCRIPTOR 7
+#define KSBA_TYPE_EXTERNAL 8
+#define KSBA_TYPE_REAL 9
+#define KSBA_TYPE_ENUMERATED 10
+#define KSBA_TYPE_EMBEDDED_PDV 11
+#define KSBA_TYPE_UTF8_STRING 12
+#define KSBA_TYPE_RELATIVE_OID 13
+#define KSBA_TYPE_TIME 14
+#define KSBA_TYPE_SEQUENCE 16
+#define KSBA_TYPE_SET 17
+#define KSBA_TYPE_NUMERIC_STRING 18
+#define KSBA_TYPE_PRINTABLE_STRING 19
+#define KSBA_TYPE_TELETEX_STRING 20
+#define KSBA_TYPE_VIDEOTEX_STRING 21
+#define KSBA_TYPE_IA5_STRING 22
+#define KSBA_TYPE_UTC_TIME 23
+#define KSBA_TYPE_GENERALIZED_TIME 24
+#define KSBA_TYPE_GRAPHIC_STRING 25
+#define KSBA_TYPE_VISIBLE_STRING 26
+#define KSBA_TYPE_GENERAL_STRING 27
+#define KSBA_TYPE_UNIVERSAL_STRING 28
+#define KSBA_TYPE_CHARACTER_STRING 29
+#define KSBA_TYPE_BMP_STRING 30
+#define KSBA_TYPE_DATE 31
+#define KSBA_TYPE_TIME_OF_DAY 32
+#define KSBA_TYPE_DATE_TIME 33
+#define KSBA_TYPE_DURATION 34
+#define KSBA_TYPE_OID_IRI 35
+#define KSBA_TYPE_RELATIVE_OID_IRI 36
+
+
+
typedef gpg_error_t KsbaError _KSBA_DEPRECATED;
typedef enum
{
KSBA_CT_NONE = 0,
KSBA_CT_DATA = 1,
KSBA_CT_SIGNED_DATA = 2,
KSBA_CT_ENVELOPED_DATA = 3,
KSBA_CT_DIGESTED_DATA = 4,
KSBA_CT_ENCRYPTED_DATA = 5,
KSBA_CT_AUTH_DATA = 6,
KSBA_CT_PKCS12 = 7,
KSBA_CT_SPC_IND_DATA_CTX = 8
}
ksba_content_type_t;
typedef ksba_content_type_t KsbaContentType _KSBA_DEPRECATED;
typedef enum
{
KSBA_SR_NONE = 0, /* Never seen by libksba user. */
KSBA_SR_RUNNING = 1, /* Never seen by libksba user. */
KSBA_SR_GOT_CONTENT = 2,
KSBA_SR_NEED_HASH = 3,
KSBA_SR_BEGIN_DATA = 4,
KSBA_SR_END_DATA = 5,
KSBA_SR_READY = 6,
KSBA_SR_NEED_SIG = 7,
KSBA_SR_DETACHED_DATA = 8,
KSBA_SR_BEGIN_ITEMS = 9,
KSBA_SR_GOT_ITEM = 10,
KSBA_SR_END_ITEMS = 11
}
ksba_stop_reason_t;
typedef ksba_stop_reason_t KsbaStopReason _KSBA_DEPRECATED;
typedef enum
{
KSBA_CRLREASON_UNSPECIFIED = 1,
KSBA_CRLREASON_KEY_COMPROMISE = 2,
KSBA_CRLREASON_CA_COMPROMISE = 4,
KSBA_CRLREASON_AFFILIATION_CHANGED = 8,
KSBA_CRLREASON_SUPERSEDED = 16,
KSBA_CRLREASON_CESSATION_OF_OPERATION = 32,
KSBA_CRLREASON_CERTIFICATE_HOLD = 64,
KSBA_CRLREASON_REMOVE_FROM_CRL = 256,
KSBA_CRLREASON_PRIVILEGE_WITHDRAWN = 512,
KSBA_CRLREASON_AA_COMPROMISE = 1024,
KSBA_CRLREASON_OTHER = 32768
}
ksba_crl_reason_t;
typedef ksba_crl_reason_t KsbaCRLReason _KSBA_DEPRECATED;
typedef enum
{
KSBA_OCSP_RSPSTATUS_SUCCESS = 0,
KSBA_OCSP_RSPSTATUS_MALFORMED = 1,
KSBA_OCSP_RSPSTATUS_INTERNAL = 2,
KSBA_OCSP_RSPSTATUS_TRYLATER = 3,
KSBA_OCSP_RSPSTATUS_SIGREQUIRED = 5,
KSBA_OCSP_RSPSTATUS_UNAUTHORIZED = 6,
KSBA_OCSP_RSPSTATUS_REPLAYED = 253,
KSBA_OCSP_RSPSTATUS_OTHER = 254,
KSBA_OCSP_RSPSTATUS_NONE = 255
}
ksba_ocsp_response_status_t;
typedef enum
{
KSBA_STATUS_NONE = 0,
KSBA_STATUS_UNKNOWN = 1,
KSBA_STATUS_GOOD = 2,
KSBA_STATUS_REVOKED = 4
}
ksba_status_t;
typedef enum
{
KSBA_KEYUSAGE_DIGITAL_SIGNATURE = 1,
KSBA_KEYUSAGE_NON_REPUDIATION = 2,
KSBA_KEYUSAGE_KEY_ENCIPHERMENT = 4,
KSBA_KEYUSAGE_DATA_ENCIPHERMENT = 8,
KSBA_KEYUSAGE_KEY_AGREEMENT = 16,
KSBA_KEYUSAGE_KEY_CERT_SIGN = 32,
KSBA_KEYUSAGE_CRL_SIGN = 64,
KSBA_KEYUSAGE_ENCIPHER_ONLY = 128,
KSBA_KEYUSAGE_DECIPHER_ONLY = 256
}
ksba_key_usage_t;
typedef ksba_key_usage_t KsbaKeyUsage _KSBA_DEPRECATED;
/* ISO format, e.g. "19610711T172059", assumed to be UTC. */
typedef char ksba_isotime_t[16];
/* X.509 certificates are represented by this object.
ksba_cert_new() creates such an object */
struct ksba_cert_s;
typedef struct ksba_cert_s *ksba_cert_t;
typedef struct ksba_cert_s *KsbaCert _KSBA_DEPRECATED;
/* CMS objects are controlled by this object.
ksba_cms_new() creates it */
struct ksba_cms_s;
typedef struct ksba_cms_s *ksba_cms_t;
typedef struct ksba_cms_s *KsbaCMS _KSBA_DEPRECATED;
/* CRL objects are controlled by this object.
ksba_crl_new() creates it */
struct ksba_crl_s;
typedef struct ksba_crl_s *ksba_crl_t;
typedef struct ksba_crl_s *KsbaCRL _KSBA_DEPRECATED;
/* OCSP objects are controlled by this object.
ksba_ocsp_new() creates it. */
struct ksba_ocsp_s;
typedef struct ksba_ocsp_s *ksba_ocsp_t;
/* PKCS-10 creation is controlled by this object.
ksba_certreq_new() creates it */
struct ksba_certreq_s;
typedef struct ksba_certreq_s *ksba_certreq_t;
typedef struct ksba_certreq_s *KsbaCertreq _KSBA_DEPRECATED;
/* This is a reader object for various purposes
see ksba_reader_new et al. */
struct ksba_reader_s;
typedef struct ksba_reader_s *ksba_reader_t;
typedef struct ksba_reader_s *KsbaReader _KSBA_DEPRECATED;
/* This is a writer object for various purposes
see ksba_writer_new et al. */
struct ksba_writer_s;
typedef struct ksba_writer_s *ksba_writer_t;
typedef struct ksba_writer_s *KsbaWriter _KSBA_DEPRECATED;
/* This is an object to store an ASN.1 parse tree as
create by ksba_asn_parse_file() */
struct ksba_asn_tree_s;
typedef struct ksba_asn_tree_s *ksba_asn_tree_t;
typedef struct ksba_asn_tree_s *KsbaAsnTree _KSBA_DEPRECATED;
/* This is an object to reference a General Name. Such an object is
returned by several functions. */
struct ksba_name_s;
typedef struct ksba_name_s *ksba_name_t;
typedef struct ksba_name_s *KsbaName _KSBA_DEPRECATED;
/* KsbaSexp is just an unsigned char * which should be used for
documentation purpose. The S-expressions returned by libksba are
always in canonical representation with an extra 0 byte at the end,
so that one can print the values in the debugger and at least see
the first bytes */
typedef unsigned char *ksba_sexp_t;
typedef unsigned char *KsbaSexp _KSBA_DEPRECATED;
typedef const unsigned char *ksba_const_sexp_t;
typedef const unsigned char *KsbaConstSexp _KSBA_DEPRECATED;
/* This is a generic object used by various functions. */
struct ksba_der_s;
typedef struct ksba_der_s *ksba_der_t;
/*-- cert.c --*/
gpg_error_t ksba_cert_new (ksba_cert_t *acert);
void ksba_cert_ref (ksba_cert_t cert);
void ksba_cert_release (ksba_cert_t cert);
gpg_error_t ksba_cert_set_user_data (ksba_cert_t cert, const char *key,
const void *data, size_t datalen);
gpg_error_t ksba_cert_get_user_data (ksba_cert_t cert, const char *key,
void *buffer, size_t bufferlen,
size_t *datalen);
gpg_error_t ksba_cert_read_der (ksba_cert_t cert, ksba_reader_t reader);
gpg_error_t ksba_cert_init_from_mem (ksba_cert_t cert,
const void *buffer, size_t length);
const unsigned char *ksba_cert_get_image (ksba_cert_t cert, size_t *r_length);
gpg_error_t ksba_cert_hash (ksba_cert_t cert,
int what,
void (*hasher)(void *,
const void *,
size_t length),
void *hasher_arg);
const char *ksba_cert_get_digest_algo (ksba_cert_t cert);
ksba_sexp_t ksba_cert_get_serial (ksba_cert_t cert);
char *ksba_cert_get_issuer (ksba_cert_t cert, int idx);
gpg_error_t ksba_cert_get_validity (ksba_cert_t cert, int what,
ksba_isotime_t r_time);
char *ksba_cert_get_subject (ksba_cert_t cert, int idx);
ksba_sexp_t ksba_cert_get_public_key (ksba_cert_t cert);
ksba_sexp_t ksba_cert_get_sig_val (ksba_cert_t cert);
gpg_error_t ksba_cert_get_extension (ksba_cert_t cert, int idx,
char const **r_oid, int *r_crit,
size_t *r_deroff, size_t *r_derlen);
gpg_error_t ksba_cert_is_ca (ksba_cert_t cert, int *r_ca, int *r_pathlen);
gpg_error_t ksba_cert_get_key_usage (ksba_cert_t cert, unsigned int *r_flags);
gpg_error_t ksba_cert_get_cert_policies (ksba_cert_t cert, char **r_policies);
gpg_error_t ksba_cert_get_ext_key_usages (ksba_cert_t cert, char **result);
gpg_error_t ksba_cert_get_crl_dist_point (ksba_cert_t cert, int idx,
ksba_name_t *r_distpoint,
ksba_name_t *r_issuer,
ksba_crl_reason_t *r_reason);
gpg_error_t ksba_cert_get_auth_key_id (ksba_cert_t cert,
ksba_sexp_t *r_keyid,
ksba_name_t *r_name,
ksba_sexp_t *r_serial);
gpg_error_t ksba_cert_get_subj_key_id (ksba_cert_t cert,
int *r_crit,
ksba_sexp_t *r_keyid);
gpg_error_t ksba_cert_get_authority_info_access (ksba_cert_t cert, int idx,
char **r_method,
ksba_name_t *r_location);
gpg_error_t ksba_cert_get_subject_info_access (ksba_cert_t cert, int idx,
char **r_method,
ksba_name_t *r_location);
/*-- cms.c --*/
ksba_content_type_t ksba_cms_identify (ksba_reader_t reader);
gpg_error_t ksba_cms_new (ksba_cms_t *r_cms);
void ksba_cms_release (ksba_cms_t cms);
gpg_error_t ksba_cms_set_reader_writer (ksba_cms_t cms,
ksba_reader_t r, ksba_writer_t w);
gpg_error_t ksba_cms_parse (ksba_cms_t cms, ksba_stop_reason_t *r_stopreason);
gpg_error_t ksba_cms_build (ksba_cms_t cms, ksba_stop_reason_t *r_stopreason);
ksba_content_type_t ksba_cms_get_content_type (ksba_cms_t cms, int what);
const char *ksba_cms_get_content_oid (ksba_cms_t cms, int what);
gpg_error_t ksba_cms_get_content_enc_iv (ksba_cms_t cms, void *iv,
size_t maxivlen, size_t *ivlen);
const char *ksba_cms_get_digest_algo_list (ksba_cms_t cms, int idx);
gpg_error_t ksba_cms_get_issuer_serial (ksba_cms_t cms, int idx,
char **r_issuer,
ksba_sexp_t *r_serial);
const char *ksba_cms_get_digest_algo (ksba_cms_t cms, int idx);
ksba_cert_t ksba_cms_get_cert (ksba_cms_t cms, int idx);
gpg_error_t ksba_cms_get_message_digest (ksba_cms_t cms, int idx,
char **r_digest, size_t *r_digest_len);
gpg_error_t ksba_cms_get_signing_time (ksba_cms_t cms, int idx,
ksba_isotime_t r_sigtime);
gpg_error_t ksba_cms_get_sigattr_oids (ksba_cms_t cms, int idx,
const char *reqoid, char **r_value);
ksba_sexp_t ksba_cms_get_sig_val (ksba_cms_t cms, int idx);
ksba_sexp_t ksba_cms_get_enc_val (ksba_cms_t cms, int idx);
void ksba_cms_set_hash_function (ksba_cms_t cms,
void (*hash_fnc)(void *, const void *, size_t),
void *hash_fnc_arg);
gpg_error_t ksba_cms_hash_signed_attrs (ksba_cms_t cms, int idx);
gpg_error_t ksba_cms_set_content_type (ksba_cms_t cms, int what,
ksba_content_type_t type);
gpg_error_t ksba_cms_add_digest_algo (ksba_cms_t cms, const char *oid);
gpg_error_t ksba_cms_add_signer (ksba_cms_t cms, ksba_cert_t cert);
gpg_error_t ksba_cms_add_cert (ksba_cms_t cms, ksba_cert_t cert);
gpg_error_t ksba_cms_add_smime_capability (ksba_cms_t cms, const char *oid,
const unsigned char *der,
size_t derlen);
gpg_error_t ksba_cms_set_message_digest (ksba_cms_t cms, int idx,
const unsigned char *digest,
size_t digest_len);
gpg_error_t ksba_cms_set_signing_time (ksba_cms_t cms, int idx,
const ksba_isotime_t sigtime);
gpg_error_t ksba_cms_set_sig_val (ksba_cms_t cms,
int idx, ksba_const_sexp_t sigval);
gpg_error_t ksba_cms_set_content_enc_algo (ksba_cms_t cms,
const char *oid,
const void *iv,
size_t ivlen);
gpg_error_t ksba_cms_add_recipient (ksba_cms_t cms, ksba_cert_t cert);
gpg_error_t ksba_cms_set_enc_val (ksba_cms_t cms,
int idx, ksba_const_sexp_t encval);
/*-- crl.c --*/
gpg_error_t ksba_crl_new (ksba_crl_t *r_crl);
void ksba_crl_release (ksba_crl_t crl);
gpg_error_t ksba_crl_set_reader (ksba_crl_t crl, ksba_reader_t r);
void ksba_crl_set_hash_function (ksba_crl_t crl,
void (*hash_fnc)(void *,
const void *, size_t),
void *hash_fnc_arg);
const char *ksba_crl_get_digest_algo (ksba_crl_t crl);
gpg_error_t ksba_crl_get_issuer (ksba_crl_t crl, char **r_issuer);
gpg_error_t ksba_crl_get_extension (ksba_crl_t crl, int idx,
char const **oid, int *critical,
unsigned char const **der, size_t *derlen);
gpg_error_t ksba_crl_get_auth_key_id (ksba_crl_t crl,
ksba_sexp_t *r_keyid,
ksba_name_t *r_name,
ksba_sexp_t *r_serial);
gpg_error_t ksba_crl_get_crl_number (ksba_crl_t crl, ksba_sexp_t *number);
gpg_error_t ksba_crl_get_update_times (ksba_crl_t crl,
ksba_isotime_t this_update,
ksba_isotime_t next_update);
gpg_error_t ksba_crl_get_item (ksba_crl_t crl,
ksba_sexp_t *r_serial,
ksba_isotime_t r_revocation_date,
ksba_crl_reason_t *r_reason);
ksba_sexp_t ksba_crl_get_sig_val (ksba_crl_t crl);
gpg_error_t ksba_crl_parse (ksba_crl_t crl, ksba_stop_reason_t *r_stopreason);
/*-- ocsp.c --*/
gpg_error_t ksba_ocsp_new (ksba_ocsp_t *r_oscp);
void ksba_ocsp_release (ksba_ocsp_t ocsp);
gpg_error_t ksba_ocsp_set_digest_algo (ksba_ocsp_t ocsp, const char *oid);
gpg_error_t ksba_ocsp_set_requestor (ksba_ocsp_t ocsp, ksba_cert_t cert);
gpg_error_t ksba_ocsp_add_target (ksba_ocsp_t ocsp,
ksba_cert_t cert, ksba_cert_t issuer_cert);
size_t ksba_ocsp_set_nonce (ksba_ocsp_t ocsp,
unsigned char *nonce, size_t noncelen);
gpg_error_t ksba_ocsp_prepare_request (ksba_ocsp_t ocsp);
gpg_error_t ksba_ocsp_hash_request (ksba_ocsp_t ocsp,
void (*hasher)(void *, const void *,
size_t length),
void *hasher_arg);
gpg_error_t ksba_ocsp_set_sig_val (ksba_ocsp_t ocsp,
ksba_const_sexp_t sigval);
gpg_error_t ksba_ocsp_add_cert (ksba_ocsp_t ocsp, ksba_cert_t cert);
gpg_error_t ksba_ocsp_build_request (ksba_ocsp_t ocsp,
unsigned char **r_buffer,
size_t *r_buflen);
gpg_error_t ksba_ocsp_parse_response (ksba_ocsp_t ocsp,
const unsigned char *msg, size_t msglen,
ksba_ocsp_response_status_t *resp_status);
const char *ksba_ocsp_get_digest_algo (ksba_ocsp_t ocsp);
gpg_error_t ksba_ocsp_hash_response (ksba_ocsp_t ocsp,
const unsigned char *msg, size_t msglen,
void (*hasher)(void *, const void *,
size_t length),
void *hasher_arg);
ksba_sexp_t ksba_ocsp_get_sig_val (ksba_ocsp_t ocsp,
ksba_isotime_t produced_at);
gpg_error_t ksba_ocsp_get_responder_id (ksba_ocsp_t ocsp,
char **r_name,
ksba_sexp_t *r_keyid);
ksba_cert_t ksba_ocsp_get_cert (ksba_ocsp_t ocsp, int idx);
gpg_error_t ksba_ocsp_get_status (ksba_ocsp_t ocsp, ksba_cert_t cert,
ksba_status_t *r_status,
ksba_isotime_t r_this_update,
ksba_isotime_t r_next_update,
ksba_isotime_t r_revocation_time,
ksba_crl_reason_t *r_reason);
gpg_error_t ksba_ocsp_get_extension (ksba_ocsp_t ocsp, ksba_cert_t cert,
int idx,
char const **r_oid, int *r_crit,
unsigned char const **r_der,
size_t *r_derlen);
/*-- certreq.c --*/
gpg_error_t ksba_certreq_new (ksba_certreq_t *r_cr);
void ksba_certreq_release (ksba_certreq_t cr);
gpg_error_t ksba_certreq_set_writer (ksba_certreq_t cr, ksba_writer_t w);
void ksba_certreq_set_hash_function (
ksba_certreq_t cr,
void (*hash_fnc)(void *, const void *, size_t),
void *hash_fnc_arg);
gpg_error_t ksba_certreq_add_subject (ksba_certreq_t cr, const char *name);
gpg_error_t ksba_certreq_set_public_key (ksba_certreq_t cr,
ksba_const_sexp_t key);
gpg_error_t ksba_certreq_add_extension (ksba_certreq_t cr,
const char *oid, int is_crit,
const void *der,
size_t derlen);
gpg_error_t ksba_certreq_set_sig_val (ksba_certreq_t cr,
ksba_const_sexp_t sigval);
gpg_error_t ksba_certreq_build (ksba_certreq_t cr,
ksba_stop_reason_t *r_stopreason);
/* The functions below are used to switch to X.509 certificate creation. */
gpg_error_t ksba_certreq_set_serial (ksba_certreq_t cr, ksba_const_sexp_t sn);
gpg_error_t ksba_certreq_set_issuer (ksba_certreq_t cr, const char *name);
gpg_error_t ksba_certreq_set_validity (ksba_certreq_t cr, int what,
const ksba_isotime_t timebuf);
gpg_error_t ksba_certreq_set_siginfo (ksba_certreq_t cr,
ksba_const_sexp_t siginfo);
/*-- reader.c --*/
gpg_error_t ksba_reader_new (ksba_reader_t *r_r);
void ksba_reader_release (ksba_reader_t r);
gpg_error_t ksba_reader_set_release_notify (ksba_reader_t r,
void (*notify)(void*,ksba_reader_t),
void *notify_value);
gpg_error_t ksba_reader_clear (ksba_reader_t r,
unsigned char **buffer, size_t *buflen);
gpg_error_t ksba_reader_error (ksba_reader_t r);
gpg_error_t ksba_reader_set_mem (ksba_reader_t r,
const void *buffer, size_t length);
gpg_error_t ksba_reader_set_fd (ksba_reader_t r, int fd);
gpg_error_t ksba_reader_set_file (ksba_reader_t r, FILE *fp);
gpg_error_t ksba_reader_set_cb (ksba_reader_t r,
int (*cb)(void*,char *,size_t,size_t*),
void *cb_value );
gpg_error_t ksba_reader_read (ksba_reader_t r,
char *buffer, size_t length, size_t *nread);
gpg_error_t ksba_reader_unread (ksba_reader_t r, const void *buffer, size_t count);
unsigned long ksba_reader_tell (ksba_reader_t r);
/*-- writer.c --*/
gpg_error_t ksba_writer_new (ksba_writer_t *r_w);
void ksba_writer_release (ksba_writer_t w);
gpg_error_t ksba_writer_set_release_notify (ksba_writer_t w,
void (*notify)(void*,ksba_writer_t),
void *notify_value);
int ksba_writer_error (ksba_writer_t w);
unsigned long ksba_writer_tell (ksba_writer_t w);
gpg_error_t ksba_writer_set_fd (ksba_writer_t w, int fd);
gpg_error_t ksba_writer_set_file (ksba_writer_t w, FILE *fp);
gpg_error_t ksba_writer_set_cb (ksba_writer_t w,
int (*cb)(void*,const void *,size_t),
void *cb_value);
gpg_error_t ksba_writer_set_mem (ksba_writer_t w, size_t initial_size);
const void *ksba_writer_get_mem (ksba_writer_t w, size_t *nbytes);
void * ksba_writer_snatch_mem (ksba_writer_t w, size_t *nbytes);
gpg_error_t ksba_writer_set_filter (ksba_writer_t w,
gpg_error_t (*filter)(void*,
const void *,size_t, size_t *,
void *, size_t, size_t *),
void *filter_arg);
gpg_error_t ksba_writer_write (ksba_writer_t w, const void *buffer, size_t length);
gpg_error_t ksba_writer_write_octet_string (ksba_writer_t w,
const void *buffer, size_t length,
int flush);
/*-- asn1-parse.y --*/
int ksba_asn_parse_file (const char *filename, ksba_asn_tree_t *result,
int debug);
void ksba_asn_tree_release (ksba_asn_tree_t tree);
/*-- asn1-func.c --*/
void ksba_asn_tree_dump (ksba_asn_tree_t tree, const char *name, FILE *fp);
gpg_error_t ksba_asn_create_tree (const char *mod_name, ksba_asn_tree_t *result);
/*-- oid.c --*/
char *ksba_oid_to_str (const char *buffer, size_t length);
gpg_error_t ksba_oid_from_str (const char *string,
unsigned char **rbuf, size_t *rlength);
/*-- dn.c --*/
gpg_error_t ksba_dn_der2str (const void *der, size_t derlen, char **r_string);
gpg_error_t ksba_dn_str2der (const char *string,
unsigned char **rder, size_t *rderlen);
gpg_error_t ksba_dn_teststr (const char *string, int seq,
size_t *rerroff, size_t *rerrlen);
/*-- name.c --*/
gpg_error_t ksba_name_new (ksba_name_t *r_name);
void ksba_name_ref (ksba_name_t name);
void ksba_name_release (ksba_name_t name);
const char *ksba_name_enum (ksba_name_t name, int idx);
char *ksba_name_get_uri (ksba_name_t name, int idx);
/*-- der-builder.c --*/
void ksba_der_release (ksba_der_t d);
ksba_der_t ksba_der_builder_new (unsigned int nitems);
void ksba_der_builder_reset (ksba_der_t d);
void ksba_der_add_ptr (ksba_der_t d, int cls, int tag,
void *value, size_t valuelen);
void ksba_der_add_val (ksba_der_t d, int cls, int tag,
const void *value, size_t valuelen);
void ksba_der_add_int (ksba_der_t d, const void *value, size_t valuelen,
int force_positive);
void ksba_der_add_oid (ksba_der_t d, const char *oidstr);
void ksba_der_add_bts (ksba_der_t d, const void *value, size_t valuelen,
unsigned int unusedbits);
void ksba_der_add_der (ksba_der_t d, const void *der, size_t derlen);
void ksba_der_add_tag (ksba_der_t d, int cls, int tag);
void ksba_der_add_end (ksba_der_t d);
gpg_error_t ksba_der_builder_get (ksba_der_t d,
unsigned char **r_obj, size_t *r_objlen);
/*-- util.c --*/
void ksba_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
void *(*new_realloc_func)(void *p, size_t n),
void (*new_free_func)(void*) );
void ksba_set_hash_buffer_function ( gpg_error_t (*fnc)
(void *arg, const char *oid,
const void *buffer, size_t length,
size_t resultsize,
unsigned char *result,
size_t *resultlen),
void *fnc_arg);
void *ksba_malloc (size_t n );
void *ksba_calloc (size_t n, size_t m );
void *ksba_realloc (void *p, size_t n);
char *ksba_strdup (const char *p);
void ksba_free ( void *a );
/*--version.c --*/
const char *ksba_check_version (const char *req_version);
#ifdef __cplusplus
}
#endif
#endif /*KSBA_H*/
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ef72198..0e7186f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,75 +1,76 @@
# Makefile.am - for the KSBA regression tests
# Copyright (C) 2001, 2003 g10 Code GmbH
#
# This file is part of KSBA.
#
# KSBA 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.
#
# KSBA 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 .
## Process this file with automake to produce Makefile.in
TESTS_ENVIRONMENT =
test_certs = samples/cert_dfn_pca01.der samples/cert_dfn_pca15.der \
samples/cert_g10code_test1.der samples/crl_testpki_testpca.der \
samples/authority.crt samples/betsy.crt samples/bull.crt \
samples/ov-ocsp-server.crt samples/ov-userrev.crt \
samples/ov-root-ca-cert.crt samples/ov-serverrev.crt \
samples/ov-user.crt samples/ov-server.crt \
samples/ov2-root-ca-cert.crt samples/ov2-ocsp-server.crt \
samples/ov2-user.crt samples/ov2-userrev.crt \
samples/secp256r1-sha384_cert.crt \
samples/secp256r1-sha512_cert.crt \
samples/secp384r1-sha512_cert.crt \
samples/openssl-secp256r1ca.cert.crt \
samples/ed25519-rfc8410.crt \
samples/ed25519-ossl-1.crt \
samples/ed448-ossl-1.crt
test_crls = samples/ov-test-crl.crl
test_keys = samples/ov-server.p12 samples/ov-userrev.p12 \
samples/ov-serverrev.p12 samples/ov-user.p12
EXTRA_DIST = $(test_certs) samples/README mkoidtbl.awk \
samples/detached-sig.cms \
samples/rsa-sample1.p7m samples/rsa-sample1.p7m.asn \
samples/ecdh-sample1.p7m samples/ecdh-sample1.p7m.asn
BUILT_SOURCES = oidtranstbl.h
CLEANFILES = oidtranstbl.h
-TESTS = cert-basic t-crl-parser t-dnparser t-oid t-reader t-cms-parser
+TESTS = cert-basic t-crl-parser t-dnparser t-oid t-reader t-cms-parser \
+ t-der-builder
AM_CFLAGS = $(GPG_ERROR_CFLAGS) $(COVERAGE_CFLAGS)
AM_LDFLAGS = -no-install $(COVERAGE_LDFLAGS)
noinst_HEADERS = t-common.h
noinst_PROGRAMS = $(TESTS) t-ocsp
LDADD = ../src/libksba.la $(GPG_ERROR_LIBS) @LDADD_FOR_TESTS_KLUDGE@
t_ocsp_SOURCES = t-ocsp.c sha1.c
# Build the OID table: Note that the binary includes data from an
# another program and we may not be allowed to distribute this. This
# ain't no problem as the programs using this generated data are not
# installed and thus not distributed.
oidtranstbl.h: Makefile mkoidtbl.awk
set -e; f="/dev/null"; \
for i in /etc/dumpasn1 /usr/local/bin /usr/local/share /usr/bin \
/usr/share ; do \
if test -f $$i/dumpasn1.cfg; then f=$$i/dumpasn1.cfg; break; fi; \
done; tr -d '\r' <$$f | $(AWK) -f $(srcdir)/mkoidtbl.awk >$@
LOG_COMPILER = $(VALGRIND)
diff --git a/tests/t-der-builder.c b/tests/t-der-builder.c
new file mode 100644
index 0000000..e06ff53
--- /dev/null
+++ b/tests/t-der-builder.c
@@ -0,0 +1,153 @@
+/* t-der-builder.c - Tests for the DER builder functions
+ * Copyright (C) 2020 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 .
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../src/ksba.h"
+
+#define PGM "t-der-builder"
+
+#include "t-common.h"
+
+
+static int verbose;
+
+
+
+static void
+test_der_encoding (void)
+{
+ gpg_error_t err;
+ ksba_der_t d;
+ unsigned char *der;
+ size_t derlen;
+
+ d = ksba_der_builder_new (0);
+ if (!d)
+ fail ("error creating new DER builder");
+
+ ksba_der_add_ptr (d, KSBA_CLASS_UNIVERSAL, KSBA_TYPE_NULL, NULL, 0);
+ err = ksba_der_builder_get (d, &der, &derlen);
+ fail_if_err (err);
+ if (derlen != 2 || memcmp (der, "\x05\x00", 2))
+ fail ("bad encoding");
+ xfree (der);
+
+ ksba_der_builder_reset (d);
+ ksba_der_add_ptr (d, KSBA_CLASS_UNIVERSAL, KSBA_TYPE_OCTET_STRING, "123", 3);
+ err = ksba_der_builder_get (d, &der, &derlen);
+ fail_if_err (err);
+ if (derlen != 5 || memcmp (der, "\x04\x03""123", 5))
+ fail ("bad encoding");
+ xfree (der);
+
+ ksba_der_builder_reset (d);
+ ksba_der_add_ptr (d, KSBA_CLASS_UNIVERSAL, 65537, "a", 1);
+ err = ksba_der_builder_get (d, &der, &derlen);
+ fail_if_err (err);
+ if (derlen != 6 || memcmp (der, "\x1f\x84\x80\x01\x01\x61", 6))
+ fail ("bad encoding");
+ xfree (der);
+
+ ksba_der_builder_reset (d);
+ ksba_der_add_tag (d, KSBA_CLASS_APPLICATION, 257);
+ err = ksba_der_builder_get (d, &der, &derlen);
+ fail_if_err (err);
+ if (derlen != 4 || memcmp (der, "\x7f\x82\x01\x80", 4))
+ fail ("bad encoding");
+ xfree (der);
+
+ ksba_der_release (d);
+}
+
+
+static void
+test_der_builder (void)
+{
+ gpg_error_t err;
+ ksba_der_t d;
+ unsigned char *der;
+ size_t derlen;
+
+ d = ksba_der_builder_new (0);
+ if (!d)
+ fail ("error creating new DER builder");
+
+ ksba_der_add_tag (d, KSBA_CLASS_UNIVERSAL, KSBA_TYPE_SEQUENCE);
+ ksba_der_add_oid (d, "1.2.3.4");
+ ksba_der_add_tag (d, KSBA_CLASS_UNIVERSAL, KSBA_TYPE_SET);
+ ksba_der_add_tag (d, KSBA_CLASS_CONTEXT, 0);
+ ksba_der_add_int (d, "\x01", 1, 0);
+ ksba_der_add_end (d);
+ ksba_der_add_tag (d, KSBA_CLASS_CONTEXT, 42);
+ ksba_der_add_int (d, "\x7f", 1, 0); /* 127 */
+ ksba_der_add_int (d, "\x7f", 1, 1); /* Also 127 */
+ ksba_der_add_int (d, "\x82", 1, 0); /* Note: this is a negative number. */
+ ksba_der_add_int (d, "\x83", 1, 1); /* Forces positive encoding. */
+ ksba_der_add_end (d);
+ ksba_der_add_end (d);
+
+ err = ksba_der_builder_get (d, &der, &derlen);
+ fail_if_err (err);
+ /* gpgrt_log_printhex (der, derlen, "DER:"); */
+ if (derlen != 30
+ || memcmp (der, ("\x30\x1c\x06\x03\x2a\x03\x04\x31\x15\xa0\x03\x02"
+ "\x01\x01\xbf\x2a\x0d\x02\x01\x7f\x02\x01\x7f\x02"
+ "\x01\x82\x02\x02\x00\x83"), 30))
+ fail ("bad encoding");
+ xfree (der);
+
+ ksba_der_release (d);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ if (argc)
+ {
+ argc--; argv++;
+ }
+
+ if (argc && !strcmp (*argv, "--verbose"))
+ {
+ verbose = 1;
+ argc--; argv++;
+ }
+
+
+ if (!argc)
+ {
+ test_der_encoding ();
+ test_der_builder ();
+ }
+ else
+ {
+ fputs ("usage: "PGM"\n", stderr);
+ return 1;
+ }
+
+ return 0;
+}