diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2009-04-20 20:53:38 +0000 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2009-04-20 20:53:38 +0000 |
commit | 08b2d288a1281d672533428fb1d8170dff9e5e08 (patch) | |
tree | 040f1eaa97f5f3c243b67b59a47d7e8742779e42 | |
parent | 09f706ec3e69e1899ba3efb9eaf248f35d5c6aaa (diff) | |
download | strongswan-08b2d288a1281d672533428fb1d8170dff9e5e08.tar.bz2 strongswan-08b2d288a1281d672533428fb1d8170dff9e5e08.tar.xz |
scepclient and pluto use asn1 from libstrongswan
38 files changed, 1517 insertions, 2564 deletions
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index 13c87105e..037f81956 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -105,7 +105,8 @@ AM_CFLAGS = -rdynamic \ -DIPSEC_PIDDIR=\"${piddir}\" \ -DIPSEC_PLUGINDIR=\"${plugindir}\" \ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ - -DRESOLV_CONF=\"${resolv_conf}\" + -DRESOLV_CONF=\"${resolv_conf}\" \ + -Wformat=0 charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lpthread -lm -ldl EXTRA_DIST = config/proposal_keywords.txt diff --git a/src/charon/plugins/nm/Makefile.am b/src/charon/plugins/nm/Makefile.am index 9c8c64fe1..ffd38e8b7 100644 --- a/src/charon/plugins/nm/Makefile.am +++ b/src/charon/plugins/nm/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${nm_CFLAGS} -AM_CFLAGS = -rdynamic +AM_CFLAGS = -rdynamic -Wformat=0 plugin_LTLIBRARIES = libstrongswan-nm.la libstrongswan_nm_la_SOURCES = \ diff --git a/src/charon/plugins/sql/Makefile.am b/src/charon/plugins/sql/Makefile.am index ea39ce0d5..1e9694456 100644 --- a/src/charon/plugins/sql/Makefile.am +++ b/src/charon/plugins/sql/Makefile.am @@ -4,7 +4,8 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon AM_CFLAGS = -rdynamic \ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ -DIPSEC_PLUGINDIR=\"${plugindir}\" \ - -DPLUGINS=\""${libstrongswan_plugins}\"" + -DPLUGINS=\""${libstrongswan_plugins}\"" \ + -Wformat=0 plugin_LTLIBRARIES = libstrongswan-sql.la libstrongswan_sql_la_SOURCES = sql_plugin.h sql_plugin.c \ diff --git a/src/charon/plugins/stroke/Makefile.am b/src/charon/plugins/stroke/Makefile.am index 7a341102b..a8ab074da 100644 --- a/src/charon/plugins/stroke/Makefile.am +++ b/src/charon/plugins/stroke/Makefile.am @@ -1,7 +1,10 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke -AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_PIDDIR=\"${piddir}\" +AM_CFLAGS = \ +-rdynamic -Wformat=0 \ +-DIPSEC_CONFDIR=\"${confdir}\" \ +-DIPSEC_PIDDIR=\"${piddir}\" plugin_LTLIBRARIES = libstrongswan-stroke.la diff --git a/src/charon/plugins/updown/Makefile.am b/src/charon/plugins/updown/Makefile.am index de60d9fbf..21bb733da 100644 --- a/src/charon/plugins/updown/Makefile.am +++ b/src/charon/plugins/updown/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -AM_CFLAGS = -rdynamic +AM_CFLAGS = -rdynamic -Wformat=0 plugin_LTLIBRARIES = libstrongswan-updown.la libstrongswan_updown_la_SOURCES = \ diff --git a/src/dumm/Makefile.am b/src/dumm/Makefile.am index 029290fb6..730767642 100644 --- a/src/dumm/Makefile.am +++ b/src/dumm/Makefile.am @@ -16,4 +16,6 @@ irdumm_LDADD = libdumm.la -lruby1.8 INCLUDES = -I$(top_srcdir)/src/libstrongswan ${gtk_CFLAGS} \ -I/usr/lib/ruby/1.8/i486-linux/ -AM_CFLAGS = -D_FILE_OFFSET_BITS=64 +AM_CFLAGS = \ +-D_FILE_OFFSET_BITS=64 \ +-Wformat=0 diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index f18549e55..c8c94acb9 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -63,6 +63,8 @@ enum.c enum.h \ printf_hook.c printf_hook.h \ settings.c settings.h \ utils.c utils.h \ +asn1/asn1.c asn1/asn1.h \ +asn1/asn1_parser.c asn1/asn1_parser.h \ asn1/oid.c asn1/oid.h \ utils/enumerator.c utils/enumerator.h \ utils/lexparser.c utils/lexparser.h \ @@ -70,8 +72,10 @@ utils/linked_list.c utils/linked_list.h \ utils/optionsfrom.c utils/optionsfrom.h INCLUDES = -I$(top_srcdir)/src/libstrongswan -AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \ - -DIPSEC_PLUGINDIR=\"${plugindir}\" +AM_CFLAGS = \ +-DIPSEC_DIR=\"${ipsecdir}\" \ +-DIPSEC_PLUGINDIR=\"${plugindir}\" \ +-Wformat=0 if USE_LEAK_DETECTIVE AM_CFLAGS += -DLEAK_DETECTIVE diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c index fa614ef56..de8c5ea4c 100644 --- a/src/libstrongswan/asn1/asn1.c +++ b/src/libstrongswan/asn1/asn1.c @@ -21,7 +21,7 @@ #include <string.h> #include <time.h> -#include <library.h> +#include <utils.h> #include <debug.h> #include "oid.h" diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h index cc0010ad1..e29ffa84e 100644 --- a/src/libstrongswan/asn1/asn1.h +++ b/src/libstrongswan/asn1/asn1.h @@ -27,7 +27,8 @@ #include <stdarg.h> -#include <library.h> +#include <utils.h> +#include <chunk.h> /** * Definition of some primitive ASN1 types diff --git a/src/libstrongswan/asn1/asn1_parser.c b/src/libstrongswan/asn1/asn1_parser.c index 68c5e7307..e6ca599b6 100644 --- a/src/libstrongswan/asn1/asn1_parser.c +++ b/src/libstrongswan/asn1/asn1_parser.c @@ -21,7 +21,7 @@ #include <string.h> #include <time.h> -#include <library.h> +#include <utils.h> #include <debug.h> #include "asn1.h" diff --git a/src/libstrongswan/asn1/asn1_parser.h b/src/libstrongswan/asn1/asn1_parser.h index f0e21125c..6ac74ad67 100644 --- a/src/libstrongswan/asn1/asn1_parser.h +++ b/src/libstrongswan/asn1/asn1_parser.h @@ -27,7 +27,9 @@ #include <stdarg.h> -#include <library.h> +#include <utils.h> +#include <chunk.h> +#include <asn1/asn1.h> /** * Definition of ASN.1 flags diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c index 24ac5e8e7..d165300c1 100644 --- a/src/libstrongswan/chunk.c +++ b/src/libstrongswan/chunk.c @@ -225,13 +225,13 @@ bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force { if (fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd) == chunk.len) { - DBG1(" written to %s file '%s' (%d bytes)", + DBG1(" written %s file '%s' (%d bytes)", label, path, chunk.len); good = TRUE; } else { - DBG1(" writing to %s file '%s' failed: %s", + DBG1(" writing %s file '%s' failed: %s", label, path, strerror(errno)); } fclose(fd); diff --git a/src/libstrongswan/plugins/x509/Makefile.am b/src/libstrongswan/plugins/x509/Makefile.am index 3f9f85c36..a4f3990f8 100644 --- a/src/libstrongswan/plugins/x509/Makefile.am +++ b/src/libstrongswan/plugins/x509/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -AM_CFLAGS = -rdynamic +AM_CFLAGS = -rdynamic -Wformat=0 plugin_LTLIBRARIES = libstrongswan-x509.la diff --git a/src/openac/Makefile.am b/src/openac/Makefile.am index 005486779..cc9b72e16 100644 --- a/src/openac/Makefile.am +++ b/src/openac/Makefile.am @@ -7,6 +7,7 @@ AM_CFLAGS = \ -DIPSEC_CONFDIR=\"${confdir}\" \ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ -DIPSEC_PLUGINDIR=\"${plugindir}\" \ - -DPLUGINS=\""${libstrongswan_plugins}\"" + -DPLUGINS=\""${libstrongswan_plugins}\"" \ + -Wformat=0 openac_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lgmp diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am index d6db237b5..78862baa2 100644 --- a/src/pluto/Makefile.am +++ b/src/pluto/Makefile.am @@ -7,7 +7,6 @@ ipsec_PROGRAMS = pluto _pluto_adns pluto_SOURCES = \ ac.c ac.h \ alg_info.c alg_info.h \ -asn1.c asn1.h \ ca.c ca.h \ certs.c certs.h \ connections.c connections.h \ @@ -87,7 +86,8 @@ AM_CFLAGS = \ -DSHARED_SECRETS_FILE=\"${confdir}/ipsec.secrets\" \ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ -DKERNEL26_SUPPORT -DKERNEL26_HAS_KAME_DUPLICATES \ --DPLUTO -DKLIPS -DDEBUG +-DPLUTO -DKLIPS -DDEBUG \ +-Wformat=0 pluto_LDADD = \ $(LIBSTRONGSWANDIR)/libstrongswan-lite.la \ diff --git a/src/pluto/ac.c b/src/pluto/ac.c index d661557db..302cc67db 100644 --- a/src/pluto/ac.c +++ b/src/pluto/ac.c @@ -25,10 +25,11 @@ #include <freeswan.h> -#include "constants.h" -#include "defs.h" -#include "asn1.h" +#include <utils.h> +#include <asn1/asn1.h> +#include <asn1/asn1_parser.h> #include <asn1/oid.h> + #include "ac.h" #include "x509.h" #include "crl.h" @@ -38,120 +39,125 @@ #include "whack.h" #include "fetch.h" -/* chained list of X.509 attribute certificates */ - +/** + * Chained list of X.509 attribute certificates + */ static x509acert_t *x509acerts = NULL; -/* chained list of ietfAttributes */ - +/** + * Chained list of ietfAttributes + */ static ietfAttrList_t *ietfAttributes = NULL; -/* ASN.1 definition of ietfAttrSyntax */ - +/** + * ASN.1 definition of ietfAttrSyntax + */ static const asn1Object_t ietfAttrSyntaxObjects[] = { - { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_BODY }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */ - { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT | - ASN1_BODY }, /* 4 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ - { 2, "oid", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 6 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ - { 2, "string", ASN1_UTF8STRING, ASN1_OPT | - ASN1_BODY }, /* 8 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ - { 1, "end loop", ASN1_EOC, ASN1_END } /* 10 */ + { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_BODY }, /* 1 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ + { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */ + { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT | + ASN1_BODY }, /* 4 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ + { 2, "oid", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 6 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ + { 2, "string", ASN1_UTF8STRING, ASN1_OPT | + ASN1_BODY }, /* 8 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ + { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; #define IETF_ATTR_OCTETS 4 #define IETF_ATTR_OID 6 #define IETF_ATTR_STRING 8 -#define IETF_ATTR_ROOF 11 - -/* ASN.1 definition of roleSyntax */ +/** + * ASN.1 definition of roleSyntax + */ static const asn1Object_t roleSyntaxObjects[] = { - { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_OBJ }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ } /* 3 */ + { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_OBJ }, /* 1 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ + { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ }, /* 3 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; -#define ROLE_ROOF 4 - -/* ASN.1 definition of an X509 attribute certificate */ - +/** + * ASN.1 definition of an X509 attribute certificate + */ static const asn1Object_t acObjects[] = { - { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "version", ASN1_INTEGER, ASN1_DEF | - ASN1_BODY }, /* 2 */ - { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ - { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | - ASN1_BODY }, /* 7 */ - { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ - { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_OBJ }, /* 10 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ - { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ - { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13*/ - { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 14 */ - { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15*/ - { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ - { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ - { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | - ASN1_OBJ }, /* 19 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ - { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ - { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ - { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ - { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | - ASN1_BODY }, /* 25 */ - { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ - { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */ - { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ - { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ - { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 31 */ - { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */ - { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ - { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ - { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ - { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ - { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ - { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ - { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */ - { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */ - { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */ - { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */ - { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */ - { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */ - { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */ - { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */ - { 4, "critical", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 50 */ - { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */ - { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */ + { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ + { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ + { 2, "version", ASN1_INTEGER, ASN1_DEF | + ASN1_BODY }, /* 2 */ + { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ + { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ + { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ + { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ + { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | + ASN1_BODY }, /* 7 */ + { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ + { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | + ASN1_OBJ }, /* 10 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ + { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ + { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */ + { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 14 */ + { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15 */ + { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ + { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ + { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | + ASN1_OBJ }, /* 19 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ + { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ + { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ + { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ + { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ + { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | + ASN1_BODY }, /* 25 */ + { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ + { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */ + { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ + { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ + { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 31 */ + { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */ + { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */ + { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ + { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ + { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ + { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ + { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ + { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ + { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */ + { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */ + { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */ + { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */ + { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */ + { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */ + { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */ + { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */ + { 4, "critical", ASN1_BOOLEAN, ASN1_DEF | + ASN1_BODY }, /* 50 */ + { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */ + { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */ + { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 54 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; #define AC_OBJ_CERTIFICATE 0 @@ -173,7 +179,6 @@ static const asn1Object_t acObjects[] = #define AC_OBJ_EXTN_VALUE 51 #define AC_OBJ_ALGORITHM 53 #define AC_OBJ_SIGNATURE 54 -#define AC_OBJ_ROOF 55 const x509acert_t empty_ac = { NULL , /* *next */ @@ -208,11 +213,11 @@ const x509acert_t empty_ac = { }; -/* compare two ietfAttributes, returns zero if a equals b +/** + * compare two ietfAttributes, returns zero if a equals b * negative/positive if a is earlier/later in the alphabet than b */ -static int -cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b) +static int cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b) { int cmp_len, len, cmp_value; @@ -227,11 +232,10 @@ cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b) return (cmp_value == 0)? cmp_len : cmp_value; } -/* +/** * add an ietfAttribute to the chained list */ -static ietfAttr_t* -add_ietfAttr(ietfAttr_t *attr) +static ietfAttr_t* add_ietfAttr(ietfAttr_t *attr) { ietfAttrList_t **listp = &ietfAttributes; ietfAttrList_t *list = *listp; @@ -270,11 +274,10 @@ add_ietfAttr(ietfAttr_t *attr) } } -/* +/** * decodes a comma separated list of group attributes */ -void -decode_groups(char *groups, ietfAttrList_t **listp) +void decode_groups(char *groups, ietfAttrList_t **listp) { if (groups == NULL) return; @@ -316,15 +319,13 @@ decode_groups(char *groups, ietfAttrList_t **listp) } } -static bool -same_attribute(const ietfAttr_t *a, const ietfAttr_t *b) +static bool same_attribute(const ietfAttr_t *a, const ietfAttr_t *b) { return (a->kind == b->kind && a->value.len == b->value.len && memeq(a->value.ptr, b->value.ptr, b->value.len)); } -bool -group_membership(const ietfAttrList_t *peer_list +bool group_membership(const ietfAttrList_t *peer_list , const char *conn , const ietfAttrList_t *conn_list) { @@ -359,9 +360,7 @@ group_membership(const ietfAttrList_t *peer_list return FALSE; } - -void -unshare_ietfAttrList(ietfAttrList_t **listp) +void unshare_ietfAttrList(ietfAttrList_t **listp) { ietfAttrList_t *list = *listp; @@ -378,26 +377,22 @@ unshare_ietfAttrList(ietfAttrList_t **listp) } } -/* - * parses ietfAttrSyntax +/** + * Parses ietfAttrSyntax */ -static ietfAttrList_t* -parse_ietfAttrSyntax(chunk_t blob, int level0) +static ietfAttrList_t* parse_ietfAttrSyntax(chunk_t blob, int level0) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; ietfAttrList_t *list = NULL; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + parser = asn1_parser_create(ietfAttrSyntaxObjects, blob); + parser->set_top_level(parser, level0); - while (objectID < IETF_ATTR_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx)) - return NULL; - switch (objectID) { case IETF_ATTR_OCTETS: @@ -419,59 +414,52 @@ parse_ietfAttrSyntax(chunk_t blob, int level0) default: break; } - objectID++; } + parser->destroy(parser); return list; } -/* - * parses roleSyntax + +/** + * Parses roleSyntax */ -static void -parse_roleSyntax(chunk_t blob, int level0) +static void parse_roleSyntax(chunk_t blob, int level0) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + parser = asn1_parser_create(roleSyntaxObjects, blob); + parser->set_top_level(parser, level0); - while (objectID < ROLE_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx)) - return; - - switch (objectID) { - default: - break; + switch (objectID) + { + default: + break; } - objectID++; } + parser->destroy(parser); } -/* +/** * Parses an X.509 attribute certificate */ -bool -parse_ac(chunk_t blob, x509acert_t *ac) +bool parse_ac(chunk_t blob, x509acert_t *ac) { - asn1_ctx_t ctx; - bool critical; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; int type = OID_UNKNOWN; int extn_oid = OID_UNKNOWN; + bool success = FALSE; + bool critical; - asn1_init(&ctx, blob, 0, FALSE, DBG_RAW); - - while (objectID < AC_OBJ_ROOF) { - - if (!extract_object(acObjects, &objectID, &object, &level, &ctx)) - return FALSE; + parser = asn1_parser_create(acObjects, blob); - /* those objects which will parsed further need the next higher level */ - level++; + while (parser->iterate(parser, &objectID, &object)) + { + u_int level = parser->get_level(parser)+1; switch (objectID) { @@ -490,7 +478,7 @@ parse_ac(chunk_t blob, x509acert_t *ac) { plog("v%d attribute certificates are not supported" , ac->version); - return FALSE; + goto end; } break; case AC_OBJ_HOLDER_ISSUER: @@ -506,16 +494,16 @@ parse_ac(chunk_t blob, x509acert_t *ac) ac->issuerName = get_directoryName(object, level, FALSE); break; case AC_OBJ_SIG_ALG: - ac->sigAlg = parse_algorithmIdentifier(object, level, NULL); + ac->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL); break; case AC_OBJ_SERIAL_NUMBER: ac->serialNumber = object; break; case AC_OBJ_NOT_BEFORE: - ac->notBefore = asn1totime(&object, ASN1_GENERALIZEDTIME); + ac->notBefore = asn1_to_time(&object, ASN1_GENERALIZEDTIME); break; case AC_OBJ_NOT_AFTER: - ac->notAfter = asn1totime(&object, ASN1_GENERALIZEDTIME); + ac->notAfter = asn1_to_time(&object, ASN1_GENERALIZEDTIME); break; case AC_OBJ_ATTRIBUTE_TYPE: type = asn1_known_oid(object); @@ -582,7 +570,7 @@ parse_ac(chunk_t blob, x509acert_t *ac) } break; case AC_OBJ_ALGORITHM: - ac->algorithm = parse_algorithmIdentifier(object, level, NULL); + ac->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL); break; case AC_OBJ_SIGNATURE: ac->signature = object; @@ -591,17 +579,19 @@ parse_ac(chunk_t blob, x509acert_t *ac) default: break; } - objectID++; } + success = parser->success(parser); time(&ac->installed); - return TRUE; + +end: + parser->destroy(parser); + return success; } -/* - * release an ietfAttribute, free it if count reaches zero +/** + * Release an ietfAttribute, free it if count reaches zero */ -static void -release_ietfAttr(ietfAttr_t* attr) +static void release_ietfAttr(ietfAttr_t* attr) { if (--attr->count == 0) { @@ -621,11 +611,10 @@ release_ietfAttr(ietfAttr_t* attr) } } -/* - * free an ietfAttrList +/** + * Free an ietfAttrList */ -void -free_ietfAttrList(ietfAttrList_t* list) +void free_ietfAttrList(ietfAttrList_t* list) { while (list != NULL) { @@ -637,11 +626,10 @@ free_ietfAttrList(ietfAttrList_t* list) } } -/* - * free a X.509 attribute certificate +/** + * Free a X.509 attribute certificate */ -void -free_acert(x509acert_t *ac) +void free_acert(x509acert_t *ac) { if (ac != NULL) { @@ -652,32 +640,29 @@ free_acert(x509acert_t *ac) } } -/* - * free first X.509 attribute certificate in the chained list +/** + * Free first X.509 attribute certificate in the chained list */ -static void -free_first_acert(void) +static void free_first_acert(void) { x509acert_t *first = x509acerts; x509acerts = first->next; free_acert(first); } -/* +/** * Free all attribute certificates in the chained list */ -void -free_acerts(void) -{ +void free_acerts(void) +{ while (x509acerts != NULL) free_first_acert(); } -/* - * get a X.509 attribute certificate for a given holder +/** + * Get a X.509 attribute certificate for a given holder */ -x509acert_t* -get_x509acert(chunk_t issuer, chunk_t serial) +x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial) { x509acert_t *ac = x509acerts; x509acert_t *prev_ac = NULL; @@ -702,11 +687,10 @@ get_x509acert(chunk_t issuer, chunk_t serial) return NULL; } -/* - * add a X.509 attribute certificate to the chained list +/** + * Add a X.509 attribute certificate to the chained list */ -static void -add_acert(x509acert_t *ac) +static void add_acert(x509acert_t *ac) { x509acert_t *old_ac = get_x509acert(ac->holderIssuer, ac->holderSerial); @@ -736,11 +720,11 @@ add_acert(x509acert_t *ac) x509acerts = ac; } -/* verify the validity of an attribute certificate by +/** + * Verify the validity of an attribute certificate by * checking the notBefore and notAfter dates */ -static err_t -check_ac_validity(const x509acert_t *ac) +static err_t check_ac_validity(const x509acert_t *ac) { time_t current_time; @@ -759,11 +743,10 @@ check_ac_validity(const x509acert_t *ac) return NULL; } -/* +/** * verifies a X.509 attribute certificate */ -bool -verify_x509acert(x509acert_t *ac, bool strict) +bool verify_x509acert(x509acert_t *ac, bool strict) { u_char buf[BUF_LEN]; x509cert_t *aacert; @@ -815,11 +798,10 @@ verify_x509acert(x509acert_t *ac, bool strict) return verify_x509cert(aacert, strict, &valid_until); } -/* +/** * Loads X.509 attribute certificates */ -void -load_acerts(void) +void load_acerts(void) { u_char buf[BUF_LEN]; @@ -862,11 +844,10 @@ load_acerts(void) ignore_result(chdir(save_dir)); } -/* +/** * lists group attributes separated by commas on a single line */ -void -format_groups(const ietfAttrList_t *list, char *buf, int len) +void format_groups(const ietfAttrList_t *list, char *buf, int len) { bool first_group = TRUE; @@ -894,11 +875,10 @@ format_groups(const ietfAttrList_t *list, char *buf, int len) } } -/* +/** * list all X.509 attribute certificates in the chained list */ -void -list_acerts(bool utc) +void list_acerts(bool utc) { x509acert_t *ac = x509acerts; time_t now; @@ -967,11 +947,10 @@ list_acerts(bool utc) } } -/* +/** * list all group attributes in alphabetical order */ -void -list_groups(bool utc) +void list_groups(bool utc) { ietfAttrList_t *list = ietfAttributes; diff --git a/src/pluto/asn1.c b/src/pluto/asn1.c deleted file mode 100644 index b7605395e..000000000 --- a/src/pluto/asn1.c +++ /dev/null @@ -1,825 +0,0 @@ -/* Simple ASN.1 parser - * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur - * - * This program 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 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program 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. - * - * RCSID $Id$ - */ - -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include <freeswan.h> - -#include "constants.h" -#include "defs.h" -#include "mp_defs.h" -#include "asn1.h" -#include <asn1/oid.h> -#include "log.h" - -/* some common prefabricated ASN.1 constants */ - -static u_char ASN1_INTEGER_0_str[] = { 0x02, 0x00 }; -static u_char ASN1_INTEGER_1_str[] = { 0x02, 0x01, 0x01 }; -static u_char ASN1_INTEGER_2_str[] = { 0x02, 0x01, 0x02 }; - -const chunk_t ASN1_INTEGER_0 = chunk_from_buf(ASN1_INTEGER_0_str); -const chunk_t ASN1_INTEGER_1 = chunk_from_buf(ASN1_INTEGER_1_str); -const chunk_t ASN1_INTEGER_2 = chunk_from_buf(ASN1_INTEGER_2_str); - -/* some popular algorithmIdentifiers */ - -static u_char ASN1_md5_id_str[] = { - 0x30, 0x0C, - 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, - 0x05, 0x00 -}; - -static u_char ASN1_sha1_id_str[] = { - 0x30, 0x09, - 0x06, 0x05, 0x2B, 0x0E,0x03, 0x02, 0x1A, - 0x05, 0x00 -}; - -static u_char ASN1_md5WithRSA_id_str[] = { - 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, - 0x05, 0x00 -}; - -static u_char ASN1_sha1WithRSA_id_str[] = { - 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, - 0x05, 0x00 -}; - -static u_char ASN1_rsaEncryption_id_str[] = { - 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00 -}; - -const chunk_t ASN1_md5_id = chunk_from_buf(ASN1_md5_id_str); -const chunk_t ASN1_sha1_id = chunk_from_buf(ASN1_sha1_id_str); -const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str); -const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str); -const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_id_str); - -/* ASN.1 definition of an algorithmIdentifier */ - -static const asn1Object_t algorithmIdentifierObjects[] = { - { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */ - { 1, "parameters", ASN1_EOC, ASN1_OPT | - ASN1_RAW }, /* 2 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */ -}; - -#define ALGORITHM_ID_ALG 1 -#define ALGORITHM_ID_PARAMETERS 2 -#define ALGORITHM_ID_ROOF 4 - -/* - * return the ASN.1 encoded algorithm identifier - */ -chunk_t -asn1_algorithmIdentifier(int oid) -{ - switch (oid) - { - case OID_RSA_ENCRYPTION: - return ASN1_rsaEncryption_id; - case OID_MD5_WITH_RSA: - return ASN1_md5WithRSA_id; - case OID_SHA1_WITH_RSA: - return ASN1_sha1WithRSA_id; - case OID_MD5: - return ASN1_md5_id; - case OID_SHA1: - return ASN1_sha1_id; - default: - return chunk_empty; - } -} - -/* If the oid is listed in the oid_names table then the corresponding - * position in the oid_names table is returned otherwise -1 is returned - */ -int -asn1_known_oid(chunk_t object) -{ - int oid = 0; - - while (object.len) - { - if (oid_names[oid].octet == *object.ptr) - { - if (--object.len == 0 || oid_names[oid].down == 0) - { - return oid; /* found terminal symbol */ - } - else - { - object.ptr++; oid++; /* advance to next hex octet */ - } - } - else - { - if (oid_names[oid].next) - { - oid = oid_names[oid].next; - } - else - { - return OID_UNKNOWN; - } - } - } - return -1; -} - -/* - * Converts a known OID index to an ASN.1 OID - */ -chunk_t -asn1_build_known_oid(int n) -{ - chunk_t oid; - int i; - - if (n < 0 || n >= OID_MAX) - { - return chunk_empty; - } - - i = oid_names[n].level + 1; - oid.ptr = malloc(2 + i); - oid.len = i; - oid.ptr[0] = ASN1_OID; - oid.ptr[1] = i; - - do - { - if (oid_names[n].level >= i) - { - n--; - continue; - } - oid.ptr[--i + 2] = oid_names[n--].octet; - } - while (i > 0); - - return oid; -} - -/* - * Decodes the length in bytes of an ASN.1 object - */ -u_int -asn1_length(chunk_t *blob) -{ - u_char n; - size_t len; - - /* advance from tag field on to length field */ - blob->ptr++; - blob->len--; - - /* read first octet of length field */ - n = *blob->ptr++; - blob->len--; - - if ((n & 0x80) == 0) /* single length octet */ - return n; - - /* composite length, determine number of length octets */ - n &= 0x7f; - - if (n > blob->len) - { - DBG(DBG_PARSING, - DBG_log("number of length octets is larger than ASN.1 object") - ) - return ASN1_INVALID_LENGTH; - } - - if (n > sizeof(len)) - { - DBG(DBG_PARSING, - DBG_log("number of length octets is larger than limit of %d octets" - , (int)sizeof(len)) - ) - return ASN1_INVALID_LENGTH; - } - - len = 0; - - while (n-- > 0) - { - len = 256*len + *blob->ptr++; - blob->len--; - } - return len; -} - -/* - * codes ASN.1 lengths up to a size of 16'777'215 bytes - */ -void -code_asn1_length(size_t length, chunk_t *code) -{ - if (length < 128) - { - code->ptr[0] = length; - code->len = 1; - } - else if (length < 256) - { - code->ptr[0] = 0x81; - code->ptr[1] = (u_char) length; - code->len = 2; - } - else if (length < 65536) - { - code->ptr[0] = 0x82; - code->ptr[1] = length >> 8; - code->ptr[2] = length & 0x00ff; - code->len = 3; - } - else - { - code->ptr[0] = 0x83; - code->ptr[1] = length >> 16; - code->ptr[2] = (length >> 8) & 0x00ff; - code->ptr[3] = length & 0x0000ff; - code->len = 4; - } -} - -/* - * build an empty asn.1 object with tag and length fields already filled in - */ -u_char* -build_asn1_object(chunk_t *object, asn1_t type, size_t datalen) -{ - u_char length_buf[4]; - chunk_t length = { length_buf, 0 }; - u_char *pos; - - /* code the asn.1 length field */ - code_asn1_length(datalen, &length); - - /* allocate memory for the asn.1 TLV object */ - object->len = 1 + length.len + datalen; - object->ptr = malloc(object->len); - - /* set position pointer at the start of the object */ - pos = object->ptr; - - /* copy the asn.1 tag field and advance the pointer */ - *pos++ = type; - - /* copy the asn.1 length field and advance the pointer */ - chunkcpy(pos, length); - - return pos; -} - -/* - * build a simple ASN.1 object - */ -chunk_t -asn1_simple_object(asn1_t tag, chunk_t content) -{ - chunk_t object; - - u_char *pos = build_asn1_object(&object, tag, content.len); - chunkcpy(pos, content); - - return object; -} - -/* Build an ASN.1 object from a variable number of individual chunks. - * Depending on the mode, chunks either are moved ('m') or copied ('c'). - */ -chunk_t -asn1_wrap(asn1_t type, const char *mode, ...) -{ - chunk_t construct; - va_list chunks; - u_char *pos; - int i; - int count = strlen(mode); - - /* sum up lengths of individual chunks */ - va_start(chunks, mode); - construct.len = 0; - for (i = 0; i < count; i++) - { - chunk_t ch = va_arg(chunks, chunk_t); - construct.len += ch.len; - } - va_end(chunks); - - /* allocate needed memory for construct */ - pos = build_asn1_object(&construct, type, construct.len); - - /* copy or move the chunks */ - va_start(chunks, mode); - for (i = 0; i < count; i++) - { - chunk_t ch = va_arg(chunks, chunk_t); - - switch (*mode++) - { - case 'm': - mv_chunk(&pos, ch); - break; - case 'c': - default: - chunkcpy(pos, ch); - } - } - va_end(chunks); - - return construct; -} - -/* - * convert a MP integer into a DER coded ASN.1 object - */ -chunk_t -asn1_integer_from_mpz(const mpz_t value) -{ - size_t bits = mpz_sizeinbase(value, 2); /* size in bits */ - size_t size = 1 + bits / BITS_PER_BYTE; /* size in bytes */ - chunk_t n = mpz_to_n(value, size); - - return asn1_wrap(ASN1_INTEGER, "m", n); -} - -/* - * determines if a character string is of type ASN.1 printableString - */ -bool -is_printablestring(chunk_t str) -{ - const char printablestring_charset[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?"; - u_int i; - - for (i = 0; i < str.len; i++) - { - if (strchr(printablestring_charset, str.ptr[i]) == NULL) - return FALSE; - } - return TRUE; -} - -#define TIME_MAX 0x7fffffff - -/* - * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time - */ -time_t -asn1totime(const chunk_t *utctime, asn1_t type) -{ - struct tm t; - time_t tc, tz_offset; - u_char *eot = NULL; - - if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL) - { - tz_offset = 0; /* Zulu time with a zero time zone offset */ - } - else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL) - { - int tz_hour, tz_min; - - sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); - tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */ - } - else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL) - { - int tz_hour, tz_min; - - sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); - tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */ - } - else - { - return 0; /* error in time format */ - } - - /* parse ASN.1 time string */ - { - const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d": - "%4d%2d%2d%2d%2d"; - - sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday, - &t.tm_hour, &t.tm_min); - } - - /* is there a seconds field? */ - if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14)) - { - sscanf(eot-2, "%2d", &t.tm_sec); - } - else - { - t.tm_sec = 0; - } - - /* representation of year */ - if (t.tm_year >= 1900) - { - t.tm_year -= 1900; - } - else if (t.tm_year >= 100) - { - return 0; - } - else if (t.tm_year < 50) - { - t.tm_year += 100; - } - - /* representation of month 0..11*/ - t.tm_mon--; - - /* set daylight saving time to off */ - t.tm_isdst = 0; - - /* convert to time_t */ - tc = mktime(&t); - - /* if no conversion overflow occurred, compensate timezone */ - return (tc == -1) ? TIME_MAX : (tc - timezone - tz_offset); -} - -/* - * convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format - */ -chunk_t -timetoasn1(const time_t *time, asn1_t type) -{ - int offset; - const char *format; - char buf[BUF_LEN]; - chunk_t formatted_time; - struct tm *t = gmtime(time); - - if (type == ASN1_GENERALIZEDTIME) - { - format = "%04d%02d%02d%02d%02d%02dZ"; - offset = 1900; - } - else /* ASN1_UTCTIME */ - { - format = "%02d%02d%02d%02d%02d%02dZ"; - offset = (t->tm_year < 100)? 0 : -100; - } - sprintf(buf, format, t->tm_year + offset, t->tm_mon + 1, t->tm_mday - , t->tm_hour, t->tm_min, t->tm_sec); - formatted_time.ptr = buf; - formatted_time.len = strlen(buf); - return asn1_simple_object(type, formatted_time); -} - - -/* - * Initializes the internal context of the ASN.1 parser - */ -void -asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, - bool implicit, u_int cond) -{ - ctx->blobs[0] = blob; - ctx->level0 = level0; - ctx->implicit = implicit; - ctx->cond = cond; - memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr)); -} - -/* - * print the value of an ASN.1 simple object - */ -static void -debug_asn1_simple_object(chunk_t object, asn1_t type, u_int cond) -{ - int oid; - - switch (type) - { - case ASN1_OID: - oid = asn1_known_oid(object); - if (oid != OID_UNKNOWN) - { - DBG(DBG_PARSING, - DBG_log(" '%s'",oid_names[oid].name); - ) - return; - } - break; - case ASN1_UTF8STRING: - case ASN1_IA5STRING: - case ASN1_PRINTABLESTRING: - case ASN1_T61STRING: - case ASN1_VISIBLESTRING: - DBG(DBG_PARSING, - DBG_log(" '%.*s'", (int)object.len, object.ptr); - ) - return; - case ASN1_UTCTIME: - case ASN1_GENERALIZEDTIME: - DBG(DBG_PARSING, - time_t time = asn1totime(&object, type); - DBG_log(" '%T'", &time, TRUE); - ) - return; - default: - break; - } - DBG(cond, - DBG_dump_chunk("", object); - ) -} - -/* - * Parses and extracts the next ASN.1 object - */ -bool -extract_object(asn1Object_t const *objects, - u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx) -{ - asn1Object_t obj = objects[*objectID]; - chunk_t *blob; - chunk_t *blob1; - u_char *start_ptr; - - *object = chunk_empty; - - if (obj.flags & ASN1_END) /* end of loop or option found */ - { - if (ctx->loopAddr[obj.level] && ctx->blobs[obj.level+1].len > 0) - { - *objectID = ctx->loopAddr[obj.level]; /* another iteration */ - obj = objects[*objectID]; - } - else - { - ctx->loopAddr[obj.level] = 0; /* exit loop or option*/ - return TRUE; - } - } - - *level = ctx->level0 + obj.level; - blob = ctx->blobs + obj.level; - blob1 = blob + 1; - start_ptr = blob->ptr; - - /* handle ASN.1 defaults values */ - - if ((obj.flags & ASN1_DEF) - && (blob->len == 0 || *start_ptr != obj.type) ) - { - /* field is missing */ - DBG(DBG_PARSING, - DBG_log("L%d - %s:", *level, obj.name); - ) - if (obj.type & ASN1_CONSTRUCTED) - { - (*objectID)++ ; /* skip context-specific tag */ - } - return TRUE; - } - - /* handle ASN.1 options */ - - if ((obj.flags & ASN1_OPT) - && (blob->len == 0 || *start_ptr != obj.type)) - { - /* advance to end of missing option field */ - do - (*objectID)++; - while (!((objects[*objectID].flags & ASN1_END) - && (objects[*objectID].level == obj.level))); - return TRUE; - } - - /* an ASN.1 object must possess at least a tag and length field */ - - if (blob->len < 2) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: ASN.1 object smaller than 2 octets", - *level, obj.name); - ) - return FALSE; - } - - blob1->len = asn1_length(blob); - - if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: length of ASN.1 object invalid or too large", - *level, obj.name); - ) - return FALSE; - } - - blob1->ptr = blob->ptr; - blob->ptr += blob1->len; - blob->len -= blob1->len; - - /* return raw ASN.1 object without prior type checking */ - - if (obj.flags & ASN1_RAW) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s:", *level, obj.name); - ) - object->ptr = start_ptr; - object->len = (size_t)(blob->ptr - start_ptr); - return TRUE; - } - - if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0)) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", - *level, obj.name, obj.type, *start_ptr); - DBG_dump("", start_ptr, (u_int)(blob->ptr - start_ptr)); - ) - return FALSE; - } - - DBG(DBG_PARSING, - DBG_log("L%d - %s:", ctx->level0+obj.level, obj.name); - ) - - /* In case of "SEQUENCE OF" or "SET OF" start a loop */ - - if (obj.flags & ASN1_LOOP) - { - if (blob1->len > 0) - { - /* at least one item, start the loop */ - ctx->loopAddr[obj.level] = *objectID + 1; - } - else - { - /* no items, advance directly to end of loop */ - do - (*objectID)++; - while (!((objects[*objectID].flags & ASN1_END) - && (objects[*objectID].level == obj.level))); - return TRUE; - } - } - - if (obj.flags & ASN1_OBJ) - { - object->ptr = start_ptr; - object->len = (size_t)(blob->ptr - start_ptr); - DBG(ctx->cond, - DBG_dump_chunk("", *object); - ) - } - else if (obj.flags & ASN1_BODY) - { - *object = *blob1; - debug_asn1_simple_object(*object, obj.type, ctx->cond); - } - return TRUE; -} - -/* - * parse an ASN.1 simple type - */ -bool -parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level -, const char* name) -{ - size_t len; - - /* an ASN.1 object must possess at least a tag and length field */ - if (object->len < 2) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: ASN.1 object smaller than 2 octets", - level, name); - ) - return FALSE; - } - - if (*object->ptr != type) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", - level, name, type, *object->ptr); - ) - return FALSE; - } - - len = asn1_length(object); - - if (len == ASN1_INVALID_LENGTH || object->len < len) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: length of ASN.1 object invalid or too large", - level, name); - ) - return FALSE; - } - - DBG(DBG_PARSING, - DBG_log("L%d - %s:", level, name); - ) - debug_asn1_simple_object(*object, type, DBG_RAW); - return TRUE; -} - -/* - * extracts an algorithmIdentifier - */ -int -parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int alg = OID_UNKNOWN; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - - while (objectID < ALGORITHM_ID_ROOF) - { - if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx)) - return alg; - - switch (objectID) - { - case ALGORITHM_ID_ALG: - alg = asn1_known_oid(object); - break; - case ALGORITHM_ID_PARAMETERS: - if (parameters != NULL) - *parameters = object; - break; - default: - break; - } - objectID++; - } - return alg; - } - -/* - * tests if a blob contains a valid ASN.1 set or sequence - */ -bool -is_asn1(chunk_t blob) -{ - u_int len; - u_char tag = *blob.ptr; - - if (tag != ASN1_SEQUENCE && tag != ASN1_SET) - { - DBG(DBG_PARSING, - DBG_log(" file content is not binary ASN.1"); - ) - return FALSE; - } - - len = asn1_length(&blob); - - /* exact match */ - if (len == blob.len) - { - return TRUE; - } - - /* some websites append a surplus newline character to the blob */ - if (len + 1 == blob.len && *(blob.ptr + len) == '\n') - { - return TRUE; - } - - DBG(DBG_PARSING, - DBG_log(" file size does not match ASN.1 coded length"); - ) - return FALSE; -} diff --git a/src/pluto/asn1.h b/src/pluto/asn1.h deleted file mode 100644 index cbc923bac..000000000 --- a/src/pluto/asn1.h +++ /dev/null @@ -1,142 +0,0 @@ -/* Simple ASN.1 parser - * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur - * - * This program 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 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program 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. - * - * RCSID $Id$ - */ - -#ifndef _ASN1_H -#define _ASN1_H - -#include <stdarg.h> -#include <gmp.h> - -#include "defs.h" - -/* Defines some primitive ASN1 types */ - -typedef enum { - ASN1_EOC = 0x00, - ASN1_BOOLEAN = 0x01, - ASN1_INTEGER = 0x02, - ASN1_BIT_STRING = 0x03, - ASN1_OCTET_STRING = 0x04, - ASN1_NULL = 0x05, - ASN1_OID = 0x06, - ASN1_ENUMERATED = 0x0A, - ASN1_UTF8STRING = 0x0C, - ASN1_NUMERICSTRING = 0x12, - ASN1_PRINTABLESTRING = 0x13, - ASN1_T61STRING = 0x14, - ASN1_VIDEOTEXSTRING = 0x15, - ASN1_IA5STRING = 0x16, - ASN1_UTCTIME = 0x17, - ASN1_GENERALIZEDTIME = 0x18, - ASN1_GRAPHICSTRING = 0x19, - ASN1_VISIBLESTRING = 0x1A, - ASN1_GENERALSTRING = 0x1B, - ASN1_UNIVERSALSTRING = 0x1C, - ASN1_BMPSTRING = 0x1E, - - ASN1_CONSTRUCTED = 0x20, - - ASN1_SEQUENCE = 0x30, - - ASN1_SET = 0x31, - - ASN1_CONTEXT_S_0 = 0x80, - ASN1_CONTEXT_S_1 = 0x81, - ASN1_CONTEXT_S_2 = 0x82, - ASN1_CONTEXT_S_3 = 0x83, - ASN1_CONTEXT_S_4 = 0x84, - ASN1_CONTEXT_S_5 = 0x85, - ASN1_CONTEXT_S_6 = 0x86, - ASN1_CONTEXT_S_7 = 0x87, - ASN1_CONTEXT_S_8 = 0x88, - - ASN1_CONTEXT_C_0 = 0xA0, - ASN1_CONTEXT_C_1 = 0xA1, - ASN1_CONTEXT_C_2 = 0xA2, - ASN1_CONTEXT_C_3 = 0xA3, - ASN1_CONTEXT_C_4 = 0xA4, - ASN1_CONTEXT_C_5 = 0xA5 -} asn1_t; - -/* Definition of ASN1 flags */ - -#define ASN1_NONE 0x00 -#define ASN1_DEF 0x01 -#define ASN1_OPT 0x02 -#define ASN1_LOOP 0x04 -#define ASN1_END 0x08 -#define ASN1_OBJ 0x10 -#define ASN1_BODY 0x20 -#define ASN1_RAW 0x40 - -#define ASN1_INVALID_LENGTH 0xffffffff - -/* definition of an ASN.1 object */ - -typedef struct { - u_int level; - const u_char *name; - asn1_t type; - u_char flags; -} asn1Object_t; - -#define ASN1_MAX_LEVEL 10 - -typedef struct { - bool implicit; - u_int cond; - u_int level0; - u_int loopAddr[ASN1_MAX_LEVEL+1]; - chunk_t blobs[ASN1_MAX_LEVEL+2]; -} asn1_ctx_t; - -/* some common prefabricated ASN.1 constants */ - -extern const chunk_t ASN1_INTEGER_0; -extern const chunk_t ASN1_INTEGER_1; -extern const chunk_t ASN1_INTEGER_2; - -/* some popular algorithmIdentifiers */ -extern const chunk_t ASN1_md5_id; -extern const chunk_t ASN1_sha1_id; -extern const chunk_t ASN1_rsaEncryption_id; -extern const chunk_t ASN1_md5WithRSA_id; -extern const chunk_t ASN1_sha1WithRSA_id; - -extern chunk_t asn1_algorithmIdentifier(int oid); -extern int asn1_known_oid(chunk_t object); -extern chunk_t asn1_build_known_oid(int n); -extern u_int asn1_length(chunk_t *blob); -extern void code_asn1_length(size_t length, chunk_t *code); -extern u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen); -extern chunk_t asn1_integer_from_mpz(const mpz_t value); -extern chunk_t asn1_simple_object(asn1_t tag, chunk_t content); -extern chunk_t asn1_wrap(asn1_t type, const char *mode, ...); -extern bool is_printablestring(chunk_t str); -extern time_t asn1totime(const chunk_t *utctime, asn1_t type); -extern chunk_t timetoasn1(const time_t *time, asn1_t type); -extern void asn1_init(asn1_ctx_t *ctx, chunk_t blob - , u_int level0, bool implicit, u_int cond); -extern bool extract_object(asn1Object_t const *objects - , u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx); -extern bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level - , const char* name); -extern int parse_algorithmIdentifier(chunk_t blob, int level0 - , chunk_t *parameters); -extern bool is_asn1(chunk_t blob); - -#endif /* _ASN1_H */ - diff --git a/src/pluto/certs.c b/src/pluto/certs.c index c9c270c8a..74ec36368 100644 --- a/src/pluto/certs.c +++ b/src/pluto/certs.c @@ -21,10 +21,11 @@ #include <freeswan.h> #include <ipsec_policy.h> +#include "asn1/asn1.h" + #include "constants.h" #include "defs.h" #include "log.h" -#include "asn1.h" #include "id.h" #include "x509.h" #include "pgp.h" @@ -32,16 +33,15 @@ #include "certs.h" #include "pkcs1.h" -/* +/** * used for initializatin of certs */ const cert_t empty_cert = {CERT_NONE, {NULL}}; -/* +/** * extracts the certificate to be sent to the peer */ -chunk_t -get_mycert(cert_t cert) +chunk_t get_mycert(cert_t cert) { switch (cert.type) { @@ -57,9 +57,8 @@ get_mycert(cert_t cert) /* load a coded key or certificate file with autodetection * of binary DER or base64 PEM ASN.1 formats and armored PGP format */ -bool -load_coded_file(const char *filename, prompt_pass_t *pass, const char *type -, chunk_t *blob, bool *pgp) +bool load_coded_file(char *filename, prompt_pass_t *pass, const char *type, + chunk_t *blob, bool *pgp) { err_t ugh = NULL; @@ -121,18 +120,17 @@ load_coded_file(const char *filename, prompt_pass_t *pass, const char *type return FALSE; } -/* +/** * Loads a PKCS#1 or PGP private RSA key file */ -err_t -load_rsa_private_key(const char* filename, prompt_pass_t *pass -, RSA_private_key_t *key) +err_t load_rsa_private_key(char* filename, prompt_pass_t *pass, + RSA_private_key_t *key) { err_t ugh = NULL; bool pgp = FALSE; chunk_t blob = chunk_empty; - const char *path = concatenate_paths(PRIVATE_KEY_PATH, filename); + char *path = concatenate_paths(PRIVATE_KEY_PATH, filename); if (load_coded_file(path, pass, "private key", &blob, &pgp)) { @@ -153,11 +151,11 @@ load_rsa_private_key(const char* filename, prompt_pass_t *pass return ugh; } -/* + +/** * Loads a X.509 or OpenPGP certificate */ -bool -load_cert(const char *filename, const char *label, cert_t *cert) +bool load_cert(char *filename, const char *label, cert_t *cert) { bool pgp = FALSE; chunk_t blob = chunk_empty; @@ -206,42 +204,38 @@ load_cert(const char *filename, const char *label, cert_t *cert) return FALSE; } -/* +/** * Loads a host certificate */ -bool -load_host_cert(const char *filename, cert_t *cert) +bool load_host_cert(char *filename, cert_t *cert) { - const char *path = concatenate_paths(HOST_CERT_PATH, filename); + char *path = concatenate_paths(HOST_CERT_PATH, filename); return load_cert(path, "host cert", cert); } -/* +/** * Loads a CA certificate */ -bool -load_ca_cert(const char *filename, cert_t *cert) +bool load_ca_cert(char *filename, cert_t *cert) { - const char *path = concatenate_paths(CA_CERT_PATH, filename); + char *path = concatenate_paths(CA_CERT_PATH, filename); return load_cert(path, "CA cert", cert); } -/* +/** * establish equality of two certificates */ -bool -same_cert(const cert_t *a, const cert_t *b) +bool same_cert(const cert_t *a, const cert_t *b) { return a->type == b->type && a->u.x509 == b->u.x509; } -/* for each link pointing to the certif icate - " increase the count by one +/** + * for each link pointing to the certificate increase the count by one */ -void -share_cert(cert_t cert) +void share_cert(cert_t cert) { switch (cert.type) { diff --git a/src/pluto/certs.h b/src/pluto/certs.h index a3701460a..9c913a8a7 100644 --- a/src/pluto/certs.h +++ b/src/pluto/certs.h @@ -61,15 +61,14 @@ extern const cert_t empty_cert; */ extern bool no_cr_send; -extern err_t load_rsa_private_key(const char* filename, prompt_pass_t *pass +extern err_t load_rsa_private_key(char* filename, prompt_pass_t *pass , RSA_private_key_t *key); extern chunk_t get_mycert(cert_t cert); -extern bool load_coded_file(const char *filename, prompt_pass_t *pass +extern bool load_coded_file(char *filename, prompt_pass_t *pass , const char *type, chunk_t *blob, bool *pgp); -extern bool load_cert(const char *filename, const char *label - , cert_t *cert); -extern bool load_host_cert(const char *filename, cert_t *cert); -extern bool load_ca_cert(const char *filename, cert_t *cert); +extern bool load_cert(char *filename, const char *label, cert_t *cert); +extern bool load_host_cert(char *filename, cert_t *cert); +extern bool load_ca_cert(char *filename, cert_t *cert); extern bool same_cert(const cert_t *a, const cert_t *b); extern void share_cert(cert_t cert); extern void release_cert(cert_t cert); diff --git a/src/pluto/connections.c b/src/pluto/connections.c index cbb48f631..163463062 100644 --- a/src/pluto/connections.c +++ b/src/pluto/connections.c @@ -701,8 +701,7 @@ unshare_connection_strings(struct connection *c) alg_info_addref((struct alg_info *)c->alg_info_ike); } -static void -load_end_certificate(const char *filename, struct end *dst) +static void load_end_certificate(char *filename, struct end *dst) { time_t valid_until; cert_t cert; diff --git a/src/pluto/crl.c b/src/pluto/crl.c index d186abac8..f419af0eb 100644 --- a/src/pluto/crl.c +++ b/src/pluto/crl.c @@ -1,5 +1,7 @@ /* Support of X.509 certificate revocation lists (CRLs) - * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur + * Copyright (C) 2000-2009 Andreas Steffen + * + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -25,11 +27,13 @@ #include <freeswan.h> #include <ipsec_policy.h> +#include <asn1/asn1.h> +#include <asn1/asn1_parser.h> +#include <asn1/oid.h> + #include "constants.h" #include "defs.h" #include "log.h" -#include "asn1.h" -#include <asn1/oid.h> #include "x509.h" #include "crl.h" #include "ca.h" @@ -43,64 +47,64 @@ static x509crl_t *x509crls = NULL; -/* ASN.1 definition of an X.509 certificate list */ - +/** + * ASN.1 definition of an X.509 certificate revocation list + */ static const asn1Object_t crlObjects[] = { - { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "version", ASN1_INTEGER, ASN1_OPT | + { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ + { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ + { 2, "version", ASN1_INTEGER, ASN1_OPT | ASN1_BODY }, /* 2 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */ - { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */ - { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */ - { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT | + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */ + { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */ + { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ + { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */ + { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */ + { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT | ASN1_LOOP }, /* 8 */ - { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */ - { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */ - { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */ - { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT | - ASN1_LOOP }, /* 12 */ - { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ - { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */ - { 6, "critical", ASN1_BOOLEAN, ASN1_DEF | + { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */ + { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */ + { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */ + { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT | + ASN1_LOOP }, /* 12 */ + { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ + { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */ + { 6, "critical", ASN1_BOOLEAN, ASN1_DEF | ASN1_BODY }, /* 15 */ - { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */ - { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */ - { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */ - { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */ - { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */ - { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */ - { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */ - { 5, "critical", ASN1_BOOLEAN, ASN1_DEF | + { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */ + { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */ + { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */ + { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */ + { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */ + { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */ + { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */ + { 5, "critical", ASN1_BOOLEAN, ASN1_DEF | ASN1_BODY }, /* 23 */ - { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */ - { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */ - { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 28 */ - }; - -#define CRL_OBJ_CERTIFICATE_LIST 0 -#define CRL_OBJ_TBS_CERT_LIST 1 -#define CRL_OBJ_VERSION 2 -#define CRL_OBJ_SIG_ALG 4 -#define CRL_OBJ_ISSUER 5 -#define CRL_OBJ_THIS_UPDATE 6 -#define CRL_OBJ_NEXT_UPDATE 7 -#define CRL_OBJ_USER_CERTIFICATE 10 -#define CRL_OBJ_REVOCATION_DATE 11 -#define CRL_OBJ_CRL_ENTRY_EXTN_ID 14 -#define CRL_OBJ_CRL_ENTRY_CRITICAL 15 -#define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16 -#define CRL_OBJ_EXTN_ID 22 -#define CRL_OBJ_CRITICAL 23 -#define CRL_OBJ_EXTN_VALUE 24 -#define CRL_OBJ_ALGORITHM 27 -#define CRL_OBJ_SIGNATURE 28 -#define CRL_OBJ_ROOF 29 + { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */ + { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ + { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */ + { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 28 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } +}; +#define CRL_OBJ_CERTIFICATE_LIST 0 +#define CRL_OBJ_TBS_CERT_LIST 1 +#define CRL_OBJ_VERSION 2 +#define CRL_OBJ_SIG_ALG 4 +#define CRL_OBJ_ISSUER 5 +#define CRL_OBJ_THIS_UPDATE 6 +#define CRL_OBJ_NEXT_UPDATE 7 +#define CRL_OBJ_USER_CERTIFICATE 10 +#define CRL_OBJ_REVOCATION_DATE 11 +#define CRL_OBJ_CRL_ENTRY_EXTN_ID 14 +#define CRL_OBJ_CRL_ENTRY_CRITICAL 15 +#define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16 +#define CRL_OBJ_EXTN_ID 22 +#define CRL_OBJ_CRITICAL 23 +#define CRL_OBJ_EXTN_VALUE 24 +#define CRL_OBJ_ALGORITHM 27 +#define CRL_OBJ_SIGNATURE 28 const x509crl_t empty_x509crl = { NULL , /* *next */ @@ -126,11 +130,10 @@ const x509crl_t empty_x509crl = { { NULL, 0 } /* signature */ }; -/* - * get the X.509 CRL with a given issuer +/** + * Get the X.509 CRL with a given issuer */ -static x509crl_t* -get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid) +static x509crl_t* get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid) { x509crl_t *crl = x509crls; x509crl_t *prev_crl = NULL; @@ -156,11 +159,10 @@ get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid) return NULL; } -/* - * free the dynamic memory used to store revoked certificates +/** + * Free the dynamic memory used to store revoked certificates */ -static void -free_revoked_certs(revokedCert_t* revokedCerts) +static void free_revoked_certs(revokedCert_t* revokedCerts) { while (revokedCerts != NULL) { @@ -170,11 +172,10 @@ free_revoked_certs(revokedCert_t* revokedCerts) } } -/* - * free the dynamic memory used to store CRLs +/** + * Free the dynamic memory used to store CRLs */ -void -free_crl(x509crl_t *crl) +void free_crl(x509crl_t *crl) { free_revoked_certs(crl->revokedCertificates); free_generalNames(crl->distributionPoints, TRUE); @@ -182,8 +183,7 @@ free_crl(x509crl_t *crl) free(crl); } -static void -free_first_crl(void) +static void free_first_crl(void) { x509crl_t *crl = x509crls; @@ -191,8 +191,7 @@ free_first_crl(void) free_crl(crl); } -void -free_crls(void) +void free_crls(void) { lock_crl_list("free_crls"); @@ -202,11 +201,10 @@ free_crls(void) unlock_crl_list("free_crls"); } -/* +/** * Insert X.509 CRL into chained list */ -bool -insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl) +bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl) { x509crl_t *crl = malloc_thing(x509crl_t); @@ -322,11 +320,10 @@ insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl) } } -/* +/** * Loads CRLs */ -void -load_crls(void) +void load_crls(void) { struct dirent **filelist; u_char buf[BUF_LEN]; @@ -376,11 +373,10 @@ load_crls(void) ignore_result(chdir(save_dir)); } -/* +/** * Parses a CRL revocation reason code */ -static crl_reason_t -parse_crl_reasonCode(chunk_t object) +static crl_reason_t parse_crl_reasonCode(chunk_t object) { crl_reason_t reason = REASON_UNSPECIFIED; @@ -399,27 +395,22 @@ parse_crl_reasonCode(chunk_t object) /* * Parses an X.509 CRL */ -bool -parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl) +bool parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl) { u_char buf[BUF_LEN]; - asn1_ctx_t ctx; - bool critical; + asn1_parser_t *parser; chunk_t extnID; chunk_t userCertificate = chunk_empty; chunk_t object; - u_int level; - int objectID = 0; + int objectID; + bool success = FALSE; + bool critical; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + parser = asn1_parser_create(crlObjects, blob); - while (objectID < CRL_OBJ_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(crlObjects, &objectID, &object, &level, &ctx)) - return FALSE; - - /* those objects which will parsed further need the next higher level */ - level++; + u_int level = parser->get_level(parser)+1; switch (objectID) { case CRL_OBJ_CERTIFICATE_LIST: @@ -435,7 +426,7 @@ parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl) ) break; case CRL_OBJ_SIG_ALG: - crl->sigAlg = parse_algorithmIdentifier(object, level, NULL); + crl->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL); break; case CRL_OBJ_ISSUER: crl->issuer = object; @@ -445,10 +436,10 @@ parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl) ) break; case CRL_OBJ_THIS_UPDATE: - crl->thisUpdate = parse_time(object, level); + crl->thisUpdate = asn1_parse_time(object, level); break; case CRL_OBJ_NEXT_UPDATE: - crl->nextUpdate = parse_time(object, level); + crl->nextUpdate = asn1_parse_time(object, level); break; case CRL_OBJ_USER_CERTIFICATE: userCertificate = object; @@ -460,7 +451,7 @@ parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl) revokedCert_t *revokedCert = malloc_thing(revokedCert_t); revokedCert->userCertificate = userCertificate; - revokedCert->revocationDate = parse_time(object, level); + revokedCert->revocationDate = asn1_parse_time(object, level); revokedCert->revocationReason = REASON_UNSPECIFIED; revokedCert->next = crl->revokedCertificates; crl->revokedCertificates = revokedCert; @@ -494,14 +485,17 @@ parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl) } else if (extn_oid == OID_CRL_NUMBER) { - if (!parse_asn1_simple_object(&object, ASN1_INTEGER, level, "crlNumber")) - return FALSE; + if (!asn1_parse_simple_object(&object, ASN1_INTEGER, + level, "crlNumber")) + { + goto end; + } crl->crlNumber = object; } } break; case CRL_OBJ_ALGORITHM: - crl->algorithm = parse_algorithmIdentifier(object, level, NULL); + crl->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL); break; case CRL_OBJ_SIGNATURE: crl->signature = object; @@ -509,10 +503,13 @@ parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl) default: break; } - objectID++; } + success = parser->success(parser); time(&crl->installed); - return TRUE; + +end: + parser->destroy(parser); + return success; } /* Checks if the current certificate is revoked. It goes through the diff --git a/src/pluto/defs.c b/src/pluto/defs.c index 84c269aa0..7b327e7e0 100644 --- a/src/pluto/defs.c +++ b/src/pluto/defs.c @@ -68,8 +68,7 @@ temporary_cyclic_buffer(void) /* concatenates two sub paths into a string with a maximum size of BUF_LEN * use for temporary storage only */ -const char* -concatenate_paths(const char *a, const char *b) +char* concatenate_paths(char *a, char *b) { char *c; diff --git a/src/pluto/defs.h b/src/pluto/defs.h index ac4f20e3c..160681b2e 100644 --- a/src/pluto/defs.h +++ b/src/pluto/defs.h @@ -58,7 +58,7 @@ extern void *clone_bytes(const void *orig, size_t size); { memcpy(dst, chunk.ptr, chunk.len); dst += chunk.len;} extern char* temporary_cyclic_buffer(void); -extern const char* concatenate_paths(const char *a, const char *b); +extern char* concatenate_paths(char *a, char *b); /* move a chunk to a memory position and free it after insertion */ extern void mv_chunk(u_char **pos, chunk_t content); diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c index e191f38c5..a8919e630 100644 --- a/src/pluto/fetch.c +++ b/src/pluto/fetch.c @@ -38,11 +38,12 @@ #include <ldap.h> #endif +#include "asn1/asn1.h" + #include "constants.h" #include "defs.h" #include "log.h" #include "id.h" -#include "asn1.h" #include "pem.h" #include "x509.h" #include "ca.h" diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c index 2f3de9ce1..7e53e4069 100644 --- a/src/pluto/ipsec_doi.c +++ b/src/pluto/ipsec_doi.c @@ -58,7 +58,6 @@ #include "whack.h" #include "fetch.h" #include "pkcs7.h" -#include "asn1.h" #include "sha1.h" #include "md5.h" diff --git a/src/pluto/mp_defs.c b/src/pluto/mp_defs.c index 201effc29..ee9dd0360 100644 --- a/src/pluto/mp_defs.c +++ b/src/pluto/mp_defs.c @@ -16,6 +16,9 @@ #include <freeswan.h> +#include <utils.h> +#include <asn1/asn1.h> + #include "constants.h" #include "defs.h" #include "mp_defs.h" @@ -68,3 +71,17 @@ n_to_mpz(MP_INT *mp, const u_char *nbytes, size_t nlen) mpz_add_ui(mp, mp, nbytes[i]); } } + +/* + * convert a MP integer into a DER coded ASN.1 object + */ +chunk_t +asn1_integer_from_mpz(const mpz_t value) +{ + size_t bits = mpz_sizeinbase(value, 2); /* size in bits */ + size_t size = 1 + bits / BITS_PER_BYTE; /* size in bytes */ + chunk_t n = mpz_to_n(value, size); + + return asn1_wrap(ASN1_INTEGER, "m", n); +} + diff --git a/src/pluto/mp_defs.h b/src/pluto/mp_defs.h index 7b3b569ed..fa6d67fdd 100644 --- a/src/pluto/mp_defs.h +++ b/src/pluto/mp_defs.h @@ -20,10 +20,11 @@ #include <gmp.h> -#include "defs.h" +#include <utils.h> extern void n_to_mpz(MP_INT *mp, const u_char *nbytes, size_t nlen); extern chunk_t mpz_to_n(const MP_INT *mp, size_t bytes); +extern chunk_t asn1_integer_from_mpz(const mpz_t value); /* var := mod(base ** exp, mod), ensuring var is mpz_inited */ #define mpz_init_powm(flag, var, base, exp, mod) { \ diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c index ef270cd6c..2516391c2 100644 --- a/src/pluto/ocsp.c +++ b/src/pluto/ocsp.c @@ -26,6 +26,10 @@ #include <freeswan.h> #include <ipsec_policy.h> +#include <asn1/asn1.h> +#include <asn1/asn1_parser.h> +#include <asn1/oid.h> + #include "constants.h" #include "defs.h" #include "log.h" @@ -33,10 +37,8 @@ #include "crl.h" #include "ca.h" #include "rnd.h" -#include "asn1.h" #include "certs.h" #include "smartcard.h" -#include <asn1/oid.h> #include "whack.h" #include "pkcs1.h" #include "keys.h" @@ -160,131 +162,137 @@ static smartcard_t *ocsp_requestor_sc = NULL; static const struct RSA_private_key *ocsp_requestor_pri = NULL; -/* asn.1 definitions for parsing */ - +/** + * ASN.1 definition of ocspResponse + */ static const asn1Object_t ocspResponseObjects[] = { - { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */ - { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */ - { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ - { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */ - { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */ + { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */ + { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */ + { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ + { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */ + { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define OCSP_RESPONSE_STATUS 1 +#define OCSP_RESPONSE_TYPE 4 +#define OCSP_RESPONSE 5 -#define OCSP_RESPONSE_STATUS 1 -#define OCSP_RESPONSE_TYPE 4 -#define OCSP_RESPONSE 5 -#define OCSP_RESPONSE_ROOF 7 - +/** + * ASN.1 definition of basicResponse + */ static const asn1Object_t basicResponseObjects[] = { - { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE | - ASN1_DEF }, /* 2 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ - { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */ - { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */ - { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */ - { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ - { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */ - { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ - { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */ - { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */ - { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */ - { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */ - { 5, "critical", ASN1_BOOLEAN, ASN1_BODY | - ASN1_DEF }, /* 16 */ - { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */ - { 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */ - { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */ - { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */ - { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */ - { 3, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 24 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 26 */ + { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ + { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE | + ASN1_DEF }, /* 2 */ + { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ + { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */ + { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */ + { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */ + { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ + { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */ + { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ + { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */ + { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */ + { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */ + { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */ + { 5, "critical", ASN1_BOOLEAN, ASN1_BODY | + ASN1_DEF }, /* 16 */ + { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */ + { 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ + { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */ + { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */ + { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */ + { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */ + { 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 24 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; - -#define BASIC_RESPONSE_TBS_DATA 1 -#define BASIC_RESPONSE_VERSION 3 -#define BASIC_RESPONSE_ID_BY_NAME 5 -#define BASIC_RESPONSE_ID_BY_KEY 8 -#define BASIC_RESPONSE_PRODUCED_AT 10 -#define BASIC_RESPONSE_RESPONSES 11 -#define BASIC_RESPONSE_EXT_ID 15 -#define BASIC_RESPONSE_CRITICAL 16 -#define BASIC_RESPONSE_EXT_VALUE 17 -#define BASIC_RESPONSE_ALGORITHM 20 -#define BASIC_RESPONSE_SIGNATURE 21 -#define BASIC_RESPONSE_CERTIFICATE 24 -#define BASIC_RESPONSE_ROOF 27 - +#define BASIC_RESPONSE_TBS_DATA 1 +#define BASIC_RESPONSE_VERSION 3 +#define BASIC_RESPONSE_ID_BY_NAME 5 +#define BASIC_RESPONSE_ID_BY_KEY 8 +#define BASIC_RESPONSE_PRODUCED_AT 10 +#define BASIC_RESPONSE_RESPONSES 11 +#define BASIC_RESPONSE_EXT_ID 15 +#define BASIC_RESPONSE_CRITICAL 16 +#define BASIC_RESPONSE_EXT_VALUE 17 +#define BASIC_RESPONSE_ALGORITHM 20 +#define BASIC_RESPONSE_SIGNATURE 21 +#define BASIC_RESPONSE_CERTIFICATE 24 + +/** + * ASN.1 definition of responses + */ static const asn1Object_t responsesObjects[] = { - { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */ - { 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */ + { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ + { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define RESPONSES_SINGLE_RESPONSE 1 -#define RESPONSES_SINGLE_RESPONSE 1 -#define RESPONSES_ROOF 3 - +/** + * ASN.1 definition of singleResponse + */ static const asn1Object_t singleResponseObjects[] = { - { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */ - { 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */ - { 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */ - { 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */ - { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */ - { 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */ - { 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */ - { 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */ - { 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */ - { 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */ - { 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */ - { 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */ - { 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */ - { 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ - { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */ - { 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */ - { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ - { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */ - { 4, "critical", ASN1_BOOLEAN, ASN1_BODY | - ASN1_DEF }, /* 24 */ - { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 27 */ + { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */ + { 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ + { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */ + { 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */ + { 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */ + { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */ + { 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */ + { 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */ + { 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */ + { 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */ + { 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */ + { 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */ + { 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */ + { 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */ + { 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ + { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */ + { 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */ + { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ + { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */ + { 4, "critical", ASN1_BOOLEAN, ASN1_BODY | + ASN1_DEF }, /* 24 */ + { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define SINGLE_RESPONSE_ALGORITHM 2 +#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3 +#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4 +#define SINGLE_RESPONSE_SERIAL_NUMBER 5 +#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6 +#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8 +#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9 +#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11 +#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14 +#define SINGLE_RESPONSE_THIS_UPDATE 16 +#define SINGLE_RESPONSE_NEXT_UPDATE 18 +#define SINGLE_RESPONSE_EXT_ID 23 +#define SINGLE_RESPONSE_CRITICAL 24 +#define SINGLE_RESPONSE_EXT_VALUE 25 -#define SINGLE_RESPONSE_ALGORITHM 2 -#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3 -#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4 -#define SINGLE_RESPONSE_SERIAL_NUMBER 5 -#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6 -#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8 -#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9 -#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11 -#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14 -#define SINGLE_RESPONSE_THIS_UPDATE 16 -#define SINGLE_RESPONSE_NEXT_UPDATE 18 -#define SINGLE_RESPONSE_EXT_ID 23 -#define SINGLE_RESPONSE_CRITICAL 24 -#define SINGLE_RESPONSE_EXT_VALUE 25 -#define SINGLE_RESPONSE_ROOF 28 - -/* build an ocsp location from certificate information +/* + * Build an ocsp location from certificate information * without unsharing its contents */ -static bool -build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location) +static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location) { static u_char digest[SHA1_DIGEST_SIZE]; /* temporary storage */ @@ -330,11 +338,10 @@ build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location) return TRUE; } -/* - * compare two ocsp locations for equality +/** + * Compare two ocsp locations for equality */ -static bool -same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b) +static bool same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b) { return ((a->authKeyID.ptr != NULL) ? same_keyid(a->authKeyID, b->authKeyID) @@ -343,11 +350,10 @@ same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b) && chunk_equals(a->uri, b->uri); } -/* - * find an existing ocsp location in a chained list +/** + * Find an existing ocsp location in a chained list */ -ocsp_location_t* -get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain) +ocsp_location_t* get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain) { while (chain != NULL) @@ -359,12 +365,14 @@ get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain) return NULL; } -/* retrieves the status of a cert from the ocsp cache +/** + * Retrieves the status of a cert from the ocsp cache * returns CERT_UNDEFINED if no status is found */ -static cert_status_t -get_ocsp_status(const ocsp_location_t *loc, chunk_t serialNumber - ,time_t *nextUpdate, time_t *revocationTime, crl_reason_t *revocationReason) +static cert_status_t get_ocsp_status(const ocsp_location_t *loc, + chunk_t serialNumber, + time_t *nextUpdate, time_t *revocationTime, + crl_reason_t *revocationReason) { ocsp_certinfo_t *certinfo, **certinfop; int cmp = -1; @@ -399,12 +407,12 @@ get_ocsp_status(const ocsp_location_t *loc, chunk_t serialNumber return CERT_UNDEFINED; } -/* - * verify the ocsp status of a certificate +/** + * Verify the ocsp status of a certificate */ -cert_status_t -verify_by_ocsp(const x509cert_t *cert, time_t *until -, time_t *revocationDate, crl_reason_t *revocationReason) +cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until, + time_t *revocationDate, + crl_reason_t *revocationReason) { cert_status_t status; ocsp_location_t location; @@ -434,11 +442,10 @@ verify_by_ocsp(const x509cert_t *cert, time_t *until return status; } -/* - * check if an ocsp status is about to expire +/** + * Check if an ocsp status is about to expire */ -void -check_ocsp(void) +void check_ocsp(void) { ocsp_location_t *location; @@ -485,21 +492,19 @@ check_ocsp(void) unlock_ocsp_cache("check_ocsp"); } -/* +/** * frees the allocated memory of a certinfo struct */ -static void -free_certinfo(ocsp_certinfo_t *certinfo) +static void free_certinfo(ocsp_certinfo_t *certinfo) { free(certinfo->serialNumber.ptr); free(certinfo); } -/* +/** * frees all certinfos in a chained list */ -static void -free_certinfos(ocsp_certinfo_t *chain) +static void free_certinfos(ocsp_certinfo_t *chain) { ocsp_certinfo_t *certinfo; @@ -511,11 +516,10 @@ free_certinfos(ocsp_certinfo_t *chain) } } -/* - * frees the memory allocated to an ocsp location including all certinfos +/** + * Frees the memory allocated to an ocsp location including all certinfos */ -static void -free_ocsp_location(ocsp_location_t* location) +static void free_ocsp_location(ocsp_location_t* location) { free(location->issuer.ptr); free(location->authNameID.ptr); @@ -527,10 +531,9 @@ free_ocsp_location(ocsp_location_t* location) } /* - * free a chained list of ocsp locations + * Free a chained list of ocsp locations */ -void -free_ocsp_locations(ocsp_location_t **chain) +void free_ocsp_locations(ocsp_location_t **chain) { while (*chain != NULL) { @@ -540,33 +543,30 @@ free_ocsp_locations(ocsp_location_t **chain) } } -/* - * free the ocsp cache +/** + * Free the ocsp cache */ -void -free_ocsp_cache(void) +void free_ocsp_cache(void) { lock_ocsp_cache("free_ocsp_cache"); free_ocsp_locations(&ocsp_cache); unlock_ocsp_cache("free_ocsp_cache"); } -/* - * frees the ocsp cache and global variables +/** + * Frees the ocsp cache and global variables */ -void -free_ocsp(void) +void free_ocsp(void) { free(ocsp_default_uri.ptr); free_ocsp_cache(); } -/* - * list a chained list of ocsp_locations +/** + * List a chained list of ocsp_locations */ -void -list_ocsp_locations(ocsp_location_t *location, bool requests, bool utc -, bool strict) +void list_ocsp_locations(ocsp_location_t *location, bool requests, + bool utc, bool strict) { bool first = TRUE; @@ -644,19 +644,17 @@ list_ocsp_locations(ocsp_location_t *location, bool requests, bool utc } } -/* - * list the ocsp cache +/** + * List the ocsp cache */ -void -list_ocsp_cache(bool utc, bool strict) +void list_ocsp_cache(bool utc, bool strict) { lock_ocsp_cache("list_ocsp_cache"); list_ocsp_locations(ocsp_cache, FALSE, utc, strict); unlock_ocsp_cache("list_ocsp_cache"); } -static bool -get_ocsp_requestor_cert(ocsp_location_t *location) +static bool get_ocsp_requestor_cert(ocsp_location_t *location) { x509cert_t *cert = NULL; @@ -718,9 +716,8 @@ get_ocsp_requestor_cert(ocsp_location_t *location) return FALSE; } -static chunk_t -generate_signature(chunk_t digest, smartcard_t *sc - , const RSA_private_key_t *pri) +static chunk_t generate_signature(chunk_t digest, smartcard_t *sc, + const RSA_private_key_t *pri) { chunk_t sigdata; u_char *pos; @@ -750,7 +747,7 @@ generate_signature(chunk_t digest, smartcard_t *sc , (int)sc->slot, sc->id) ) - pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); + pos = asn1_build_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); *pos++ = 0x00; scx_sign_hash(sc, digest.ptr, digest.len, pos, siglen); if (!pkcs11_keep_state) @@ -760,20 +757,18 @@ generate_signature(chunk_t digest, smartcard_t *sc { /* RSA signature is done in software */ siglen = pri->pub.k; - pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); + pos = asn1_build_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); *pos++ = 0x00; sign_hash(pri, digest.ptr, digest.len, pos, siglen); } return sigdata; } -/* - * build signature into ocsp request - * gets built only if a request cert with - * a corresponding private key is found +/** + * build signature into ocsp request gets built only if a request cert + * with a corresponding private key is found */ -static chunk_t -build_signature(chunk_t tbsRequest) +static chunk_t build_signature(chunk_t tbsRequest) { chunk_t sigdata, certs; chunk_t digest_info; @@ -788,7 +783,7 @@ build_signature(chunk_t tbsRequest) * an ASN.1 structure for encryption */ digest_info = asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_sha1_id + , asn1_algorithmIdentifier(OID_SHA1) , asn1_simple_object(ASN1_OCTET_STRING, digest_raw)); /* generate the RSA signature */ @@ -811,21 +806,21 @@ build_signature(chunk_t tbsRequest) /* build signature comprising algorithm, signature and cert */ return asn1_wrap(ASN1_CONTEXT_C_0, "m" , asn1_wrap(ASN1_SEQUENCE, "cmm" - , ASN1_sha1WithRSA_id + , asn1_algorithmIdentifier(OID_SHA1_WITH_RSA) , sigdata , certs ) ); } -/* build request (into requestList) +/** + * Build request (into requestList) * no singleRequestExtensions used */ -static chunk_t -build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo) +static chunk_t build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo) { chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm" - , ASN1_sha1_id + , asn1_algorithmIdentifier(OID_SHA1) , asn1_simple_object(ASN1_OCTET_STRING, location->authNameID) , asn1_simple_object(ASN1_OCTET_STRING, location->authKeyID) , asn1_simple_object(ASN1_INTEGER, certinfo->serialNumber)); @@ -833,11 +828,10 @@ build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo) return asn1_wrap(ASN1_SEQUENCE, "m", reqCert); } -/* +/** * build requestList (into TBSRequest) */ -static chunk_t -build_request_list(ocsp_location_t *location) +static chunk_t build_request_list(ocsp_location_t *location) { chunk_t requestList; request_list_t *reqs = NULL; @@ -862,8 +856,7 @@ build_request_list(ocsp_location_t *location) certinfo = certinfo->next; } - pos = build_asn1_object(&requestList, ASN1_SEQUENCE - , datalen); + pos = asn1_build_object(&requestList, ASN1_SEQUENCE, datalen); /* copy all in chained list, free list afterwards */ while (reqs != NULL) @@ -878,22 +871,20 @@ build_request_list(ocsp_location_t *location) return requestList; } -/* - * build requestorName (into TBSRequest) +/** + * Build requestorName (into TBSRequest) */ -static chunk_t -build_requestor_name(void) +static chunk_t build_requestor_name(void) { return asn1_wrap(ASN1_CONTEXT_C_1, "m" , asn1_simple_object(ASN1_CONTEXT_C_4 , ocsp_requestor_cert->subject)); } -/* +/** * build nonce extension (into requestExtensions) */ -static chunk_t -build_nonce_extension(ocsp_location_t *location) +static chunk_t build_nonce_extension(ocsp_location_t *location) { /* generate a random nonce */ location->nonce.ptr = malloc(NONCE_LENGTH), @@ -905,11 +896,10 @@ build_nonce_extension(ocsp_location_t *location) , asn1_simple_object(ASN1_OCTET_STRING, location->nonce)); } -/* - * build requestExtensions (into TBSRequest) +/** + * Build requestExtensions (into TBSRequest) */ -static chunk_t -build_request_ext(ocsp_location_t *location) +static chunk_t build_request_ext(ocsp_location_t *location) { return asn1_wrap(ASN1_CONTEXT_C_2, "m" , asn1_wrap(ASN1_SEQUENCE, "mm" @@ -922,11 +912,10 @@ build_request_ext(ocsp_location_t *location) ); } -/* - * build TBSRequest (into OCSPRequest) +/** + * Build TBSRequest (into OCSPRequest) */ -static chunk_t -build_tbs_request(ocsp_location_t *location, bool has_requestor_cert) +static chunk_t build_tbs_request(ocsp_location_t *location, bool has_requestor_cert) { /* version is skipped since the default is ok */ return asn1_wrap(ASN1_SEQUENCE, "mmm" @@ -937,11 +926,11 @@ build_tbs_request(ocsp_location_t *location, bool has_requestor_cert) , build_request_ext(location)); } -/* assembles an ocsp request to given location +/** + * Assembles an ocsp request to given location * and sets nonce field in location to the sent nonce */ -chunk_t -build_ocsp_request(ocsp_location_t *location) +chunk_t build_ocsp_request(ocsp_location_t *location) { bool has_requestor_cert; chunk_t tbsRequest, signature; @@ -977,11 +966,10 @@ build_ocsp_request(ocsp_location_t *location) , signature); } -/* - * check if the OCSP response has a valid signature +/** + * Check if the OCSP response has a valid signature */ -static bool -valid_ocsp_response(response_t *res) +static bool valid_ocsp_response(response_t *res) { int pathlen; x509cert_t *authcert; @@ -1086,27 +1074,25 @@ valid_ocsp_response(response_t *res) return FALSE; } -/* - * parse a basic OCSP response +/** + * Parse a basic OCSP response */ -static bool -parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) +static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) { - asn1_ctx_t ctx; - bool critical; + asn1_parser_t *parser; chunk_t object; - u_int level, version; + u_int version; u_char buf[BUF_LEN]; - int objectID = 0; + int objectID; int extn_oid = OID_UNKNOWN; + bool success = FALSE; + bool critical; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + parser = asn1_parser_create(basicResponseObjects, blob); + parser->set_top_level(parser, level0); - while (objectID < BASIC_RESPONSE_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(basicResponseObjects, &objectID, &object, &level, &ctx)) - return FALSE; - switch (objectID) { case BASIC_RESPONSE_TBS_DATA: @@ -1117,7 +1103,7 @@ parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) if (version != OCSP_BASIC_RESPONSE_VERSION) { plog("wrong ocsp basic response version (version= %i)", version); - return FALSE; + goto end; } break; case BASIC_RESPONSE_ID_BY_NAME: @@ -1131,7 +1117,7 @@ parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) res->responder_id_key = object; break; case BASIC_RESPONSE_PRODUCED_AT: - res->produced_at = asn1totime(&object, ASN1_GENERALIZEDTIME); + res->produced_at = asn1_to_time(&object, ASN1_GENERALIZEDTIME); break; case BASIC_RESPONSE_RESPONSES: res->responses = object; @@ -1150,7 +1136,8 @@ parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) res->nonce = object; break; case BASIC_RESPONSE_ALGORITHM: - res->algorithm = parse_algorithmIdentifier(object, level+1, NULL); + res->algorithm = asn1_parse_algorithmIdentifier(object, + parser->get_level(parser)+1, NULL); break; case BASIC_RESPONSE_SIGNATURE: res->signature = object; @@ -1162,7 +1149,7 @@ parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) *cert = empty_x509cert; - if (parse_x509cert(blob, level+1, cert) + if (parse_x509cert(blob, parser->get_level(parser)+1, cert) && cert->isOcspSigner && trust_authcert_candidate(cert, NULL)) { @@ -1178,32 +1165,32 @@ parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) } break; } - objectID++; } - return TRUE; + success = parser->success(parser); + +end: + parser->destroy(parser); + return success; + } -/* - * parse an ocsp response and return the result as a response_t struct +/** + * Parse an ocsp response and return the result as a response_t struct */ -static response_status -parse_ocsp_response(chunk_t blob, response_t * res) +static response_status parse_ocsp_response(chunk_t blob, response_t * res) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; int ocspResponseType = OID_UNKNOWN; + bool success = FALSE; response_status rStatus = STATUS_INTERNALERROR; - asn1_init(&ctx, blob, 0, FALSE, DBG_RAW); + parser = asn1_parser_create(ocspResponseObjects, blob); - while (objectID < OCSP_RESPONSE_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(ocspResponseObjects, &objectID, &object, &level, &ctx)) - return STATUS_INTERNALERROR; - switch (objectID) { case OCSP_RESPONSE_STATUS: rStatus = (response_status) *object.ptr; @@ -1219,9 +1206,9 @@ parse_ocsp_response(chunk_t blob, response_t * res) case STATUS_UNAUTHORIZED: plog("ocsp response: server said '%s'" , response_status_names[rStatus]); - return rStatus; + goto end; default: - return STATUS_INTERNALERROR; + goto end; } break; case OCSP_RESPONSE_TYPE: @@ -1231,47 +1218,50 @@ parse_ocsp_response(chunk_t blob, response_t * res) { switch (ocspResponseType) { case OID_BASIC: - if (!parse_basic_ocsp_response(object, level+1, res)) - return STATUS_INTERNALERROR; + success = parse_basic_ocsp_response(object, + parser->get_level(parser)+1, res); break; default: DBG(DBG_CONTROL, DBG_log("ocsp response is not of type BASIC"); DBG_dump_chunk("ocsp response OID: ", object); ) - return STATUS_INTERNALERROR; + goto end; } } break; } - objectID++; } + success &= parser->success(parser); + +end: + parser->destroy(parser); return rStatus; } -/* - * parse a basic OCSP response +/** + * Parse a basic OCSP response */ -static bool -parse_ocsp_single_response(chunk_t blob, int level0, single_response_t *sres) +static bool parse_ocsp_single_response(chunk_t blob, int level0, + single_response_t *sres) { - u_int level, extn_oid; - asn1_ctx_t ctx; - bool critical; + asn1_parser_t *parser; chunk_t object; - int objectID = 0; + u_int extn_oid; + int objectID; + bool critical; + bool success = FALSE; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + parser = asn1_parser_create(singleResponseObjects, blob); + parser->set_top_level(parser, level0); - while (objectID < SINGLE_RESPONSE_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(singleResponseObjects, &objectID, &object, &level, &ctx)) - return FALSE; - switch (objectID) { case SINGLE_RESPONSE_ALGORITHM: - sres->hash_algorithm = parse_algorithmIdentifier(object, level+1, NULL); + sres->hash_algorithm = asn1_parse_algorithmIdentifier(object, + parser->get_level(parser)+1, NULL); break; case SINGLE_RESPONSE_ISSUER_NAME_HASH: sres->issuer_name_hash = object; @@ -1289,7 +1279,7 @@ parse_ocsp_single_response(chunk_t blob, int level0, single_response_t *sres) sres->status = CERT_REVOKED; break; case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME: - sres->revocationTime = asn1totime(&object, ASN1_GENERALIZEDTIME); + sres->revocationTime = asn1_to_time(&object, ASN1_GENERALIZEDTIME); break; case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON: sres->revocationReason = (object.len == 1) @@ -1299,10 +1289,10 @@ parse_ocsp_single_response(chunk_t blob, int level0, single_response_t *sres) sres->status = CERT_UNKNOWN; break; case SINGLE_RESPONSE_THIS_UPDATE: - sres->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); + sres->thisUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME); break; case SINGLE_RESPONSE_NEXT_UPDATE: - sres->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); + sres->nextUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME); break; case SINGLE_RESPONSE_EXT_ID: extn_oid = asn1_known_oid(object); @@ -1315,16 +1305,17 @@ parse_ocsp_single_response(chunk_t blob, int level0, single_response_t *sres) case SINGLE_RESPONSE_EXT_VALUE: break; } - objectID++; } - return TRUE; + success = parser->success(parser); + parser->destroy(parser); + return success; } -/* - * add an ocsp location to a chained list +/** + * Add an ocsp location to a chained list */ -ocsp_location_t* -add_ocsp_location(const ocsp_location_t *loc, ocsp_location_t **chain) +ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc, + ocsp_location_t **chain) { ocsp_location_t *location = malloc_thing(ocsp_location_t); @@ -1347,12 +1338,11 @@ add_ocsp_location(const ocsp_location_t *loc, ocsp_location_t **chain) return location; } -/* +/** * add a certinfo struct to a chained list */ -void -add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info, ocsp_location_t **chain - , bool request) +void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info, + ocsp_location_t **chain, bool request) { ocsp_location_t *location; ocsp_certinfo_t *certinfo, **certinfop; @@ -1362,7 +1352,9 @@ add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info, ocsp_location_t **chai location = get_ocsp_location(loc, *chain); if (location == NULL) + { location = add_ocsp_location(loc, chain); + } /* traverse list of certinfos in increasing order */ certinfop = &location->certinfo; @@ -1404,8 +1396,9 @@ add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info, ocsp_location_t **chai certinfo->status = CERT_UNDEFINED; if (cmp != 0) + { certinfo->thisUpdate = now; - + } certinfo->nextUpdate = UNDEFINED_TIME; } else @@ -1424,11 +1417,11 @@ add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info, ocsp_location_t **chai } } -/* - * process received ocsp single response and add it to ocsp cache +/** + * Process received ocsp single response and add it to ocsp cache */ -static void -process_single_response(ocsp_location_t *location, single_response_t *sres) +static void process_single_response(ocsp_location_t *location, + single_response_t *sres) { ocsp_certinfo_t *certinfo, **certinfop; int cmp = -1; @@ -1481,14 +1474,12 @@ process_single_response(ocsp_location_t *location, single_response_t *sres) /* free certinfo unlinked from ocsp fetch request list */ free_certinfo(certinfo); - } -/* - * parse and verify ocsp response and update the ocsp cache +/** + * Parse and verify ocsp response and update the ocsp cache */ -void -parse_ocsp(ocsp_location_t *location, chunk_t blob) +void parse_ocsp(ocsp_location_t *location, chunk_t blob) { response_t res = empty_response; @@ -1523,28 +1514,27 @@ parse_ocsp(ocsp_location_t *location, chunk_t blob) /* now parse the single responses one at a time */ { - u_int level; - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - int objectID = 0; + int objectID; - asn1_init(&ctx, res.responses, 0, FALSE, DBG_RAW); + parser = asn1_parser_create(responsesObjects, res.responses); - while (objectID < RESPONSES_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx)) - return; - if (objectID == RESPONSES_SINGLE_RESPONSE) { single_response_t sres = empty_single_response; - if (parse_ocsp_single_response(object, level+1, &sres)) + if (!parse_ocsp_single_response(object, + parser->get_level(parser)+1, &sres)) { - process_single_response(location, &sres); + goto end; } + process_single_response(location, &sres); } - objectID++; } +end: + parser->destroy(parser); } } diff --git a/src/pluto/pkcs1.c b/src/pluto/pkcs1.c index b7ef1072a..73fa7cc06 100644 --- a/src/pluto/pkcs1.c +++ b/src/pluto/pkcs1.c @@ -23,11 +23,13 @@ #include <freeswan.h> #include <libsha2/sha2.h> +#include <asn1/asn1.h> +#include <asn1/asn1_parser.h> +#include <asn1/oid.h> + #include "constants.h" #include "defs.h" #include "mp_defs.h" -#include "asn1.h" -#include <asn1/oid.h> #include "log.h" #include "pkcs1.h" #include "md2.h" @@ -48,40 +50,38 @@ const struct fld RSA_private_field[] = { "Coefficient", offsetof(RSA_private_key_t, qInv) }, }; -/* ASN.1 definition of a PKCS#1 RSA private key */ - +/** + * ASN.1 definition of a PKCS#1 RSA private key + */ static const asn1Object_t privkeyObjects[] = { - { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */ - { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */ - { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */ - { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */ - { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */ - { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */ - { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */ - { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */ - { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT | - ASN1_LOOP }, /* 10 */ - { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ - { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */ - { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */ - { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */ + { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ + { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */ + { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */ + { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */ + { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */ + { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */ + { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */ + { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */ + { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */ + { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT | + ASN1_LOOP }, /* 10 */ + { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ + { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */ + { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */ + { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */ + { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 15 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define PKCS1_PRIV_KEY_VERSION 1 +#define PKCS1_PRIV_KEY_MODULUS 2 +#define PKCS1_PRIV_KEY_PUB_EXP 3 +#define PKCS1_PRIV_KEY_COEFF 9 -#define PKCS1_PRIV_KEY_VERSION 1 -#define PKCS1_PRIV_KEY_MODULUS 2 -#define PKCS1_PRIV_KEY_PUB_EXP 3 -#define PKCS1_PRIV_KEY_COEFF 9 -#define PKCS1_PRIV_KEY_ROOF 16 - - -/* - * forms the FreeS/WAN keyid from the public exponent e and modulus n +/** + * Forms the FreeS/WAN keyid from the public exponent e and modulus n */ -void -form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize) +void form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize) { /* eliminate leading zero bytes in modulus from ASN.1 coding */ while (n.len > 1 && *n.ptr == 0x00) @@ -97,11 +97,10 @@ form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize) *keysize = n.len; } -/* - * initialize an RSA_public_key_t object +/** + * Initialize an RSA_public_key_t object */ -void -init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n) +void init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n) { n_to_mpz(&rsa->e, e.ptr, e.len); n_to_mpz(&rsa->n, n.ptr, n.len); @@ -110,8 +109,7 @@ init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n) } #ifdef DEBUG -static void -RSA_show_key_fields(RSA_private_key_t *k, int fieldcnt) +static void RSA_show_key_fields(RSA_private_key_t *k, int fieldcnt) { const struct fld *p; @@ -130,15 +128,15 @@ RSA_show_key_fields(RSA_private_key_t *k, int fieldcnt) } } -/* debugging info that compromises security! */ -void -RSA_show_private_key(RSA_private_key_t *k) +/** + * debugging info that compromises security! + */ +void RSA_show_private_key(RSA_private_key_t *k) { RSA_show_key_fields(k, countof(RSA_private_field)); } -void -RSA_show_public_key(RSA_public_key_t *k) +void RSA_show_public_key(RSA_public_key_t *k) { /* Kludge: pretend that it is a private key, but only display the * first two fields (which are the public key). @@ -148,8 +146,7 @@ RSA_show_public_key(RSA_public_key_t *k) } #endif -err_t -RSA_private_key_sanity(RSA_private_key_t *k) +err_t RSA_private_key_sanity(RSA_private_key_t *k) { /* note that the *last* error found is reported */ err_t ugh = NULL; @@ -226,41 +223,36 @@ RSA_private_key_sanity(RSA_private_key_t *k) return ugh; } -/* +/** * Check the equality of two RSA public keys */ -bool -same_RSA_public_key(const RSA_public_key_t *a, const RSA_public_key_t *b) +bool same_RSA_public_key(const RSA_public_key_t *a, const RSA_public_key_t *b) { return a == b || (a->k == b->k && mpz_cmp(&a->n, &b->n) == 0 && mpz_cmp(&a->e, &b->e) == 0); } -/* +/** * Parses a PKCS#1 private key */ -bool -pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key) +bool pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key) { - err_t ugh = NULL; - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object, modulus, exp; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, 0, FALSE, DBG_PRIVATE); - - while (objectID < PKCS1_PRIV_KEY_ROOF) { - - if (!extract_object(privkeyObjects, &objectID, &object, &level, &ctx)) - return FALSE; + int objectID; + bool success = FALSE; + parser = asn1_parser_create(privkeyObjects, blob); + parser->set_flags(parser, FALSE, TRUE); + + while (parser->iterate(parser, &objectID, &object)) + { if (objectID == PKCS1_PRIV_KEY_VERSION) { if (object.len > 0 && *object.ptr != 0) { plog(" wrong PKCS#1 private key version"); - return FALSE; + goto end; } } else if (objectID >= PKCS1_PRIV_KEY_MODULUS && @@ -276,18 +268,27 @@ pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key) else if (objectID == PKCS1_PRIV_KEY_PUB_EXP) exp = object; } - objectID++; } - form_keyid(exp, modulus, key->pub.keyid, &key->pub.k); - ugh = RSA_private_key_sanity(key); - return (ugh == NULL); + success = parser->success(parser); + +end: + parser->destroy(parser); + + if (success) + { + err_t ugh; + + form_keyid(exp, modulus, key->pub.keyid, &key->pub.k); + ugh = RSA_private_key_sanity(key); + success = (ugh == NULL); + } + return success; } -/* - * compute a digest over a binary blob +/** + * Compute a digest over a binary blob */ -bool -compute_digest(chunk_t tbs, int alg, chunk_t *digest) +bool compute_digest(chunk_t tbs, int alg, chunk_t *digest) { switch (alg) { @@ -367,12 +368,11 @@ compute_digest(chunk_t tbs, int alg, chunk_t *digest) } } -/* - * compute an RSA signature with PKCS#1 padding +/** + * Compute an RSA signature with PKCS#1 padding */ -void -sign_hash(const RSA_private_key_t *k, const u_char *hash_val, size_t hash_len - , u_char *sig_val, size_t sig_len) +void sign_hash(const RSA_private_key_t *k, const u_char *hash_val, + size_t hash_len, u_char *sig_val, size_t sig_len) { chunk_t ch; mpz_t t1, t2; @@ -423,11 +423,10 @@ sign_hash(const RSA_private_key_t *k, const u_char *hash_val, size_t hash_len mpz_clear(t2); } -/* - * encrypt data with an RSA public key after padding +/** + * Encrypt data with an RSA public key after padding */ -chunk_t -RSA_encrypt(const RSA_public_key_t *key, chunk_t in) +chunk_t RSA_encrypt(const RSA_public_key_t *key, chunk_t in) { u_char padded[RSA_MAX_OCTETS]; u_char *pos = padded; @@ -485,11 +484,10 @@ RSA_encrypt(const RSA_public_key_t *key, chunk_t in) } } -/* - * decrypt data with an RSA private key and remove padding +/** + * Decrypt data with an RSA private key and remove padding */ -bool -RSA_decrypt(const RSA_private_key_t *key, chunk_t in, chunk_t *out) +bool RSA_decrypt(const RSA_private_key_t *key, chunk_t in, chunk_t *out) { chunk_t padded, plaintext; u_char *pos; @@ -551,12 +549,11 @@ RSA_decrypt(const RSA_private_key_t *key, chunk_t in, chunk_t *out) return TRUE; } -/* - * build signatureValue +/** + * Build signatureValue */ -chunk_t -pkcs1_build_signature(chunk_t tbs, int hash_alg, const RSA_private_key_t *key -, bool bit_string) +chunk_t pkcs1_build_signature(chunk_t tbs, int hash_alg, + const RSA_private_key_t *key, bool bit_string) { size_t siglen = key->pub.k; @@ -566,37 +563,27 @@ pkcs1_build_signature(chunk_t tbs, int hash_alg, const RSA_private_key_t *key chunk_t digestInfo, alg_id, signatureValue; u_char *pos; - switch (hash_alg) + if (!compute_digest(tbs, hash_alg, &digest)) { - case OID_MD5: - case OID_MD5_WITH_RSA: - alg_id = ASN1_md5_id; - break; - case OID_SHA1: - case OID_SHA1_WITH_RSA: - alg_id = ASN1_sha1_id; - break; - default: return chunk_empty; } - compute_digest(tbs, hash_alg, &digest); /* according to PKCS#1 v2.1 digest must be packaged into * an ASN.1 structure for encryption */ digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm" - , alg_id + , asn1_algorithmIdentifier(hash_alg) , asn1_simple_object(ASN1_OCTET_STRING, digest)); /* generate the RSA signature */ if (bit_string) { - pos = build_asn1_object(&signatureValue, ASN1_BIT_STRING, 1 + siglen); + pos = asn1_build_object(&signatureValue, ASN1_BIT_STRING, 1 + siglen); *pos++ = 0x00; } else { - pos = build_asn1_object(&signatureValue, ASN1_OCTET_STRING, siglen); + pos = asn1_build_object(&signatureValue, ASN1_OCTET_STRING, siglen); } sign_hash(key, digestInfo.ptr, digestInfo.len, pos, siglen); free(digestInfo.ptr); @@ -604,11 +591,10 @@ pkcs1_build_signature(chunk_t tbs, int hash_alg, const RSA_private_key_t *key return signatureValue; } -/* - * build a DER-encoded PKCS#1 private key object +/** + * Build a DER-encoded PKCS#1 private key object */ -chunk_t -pkcs1_build_private_key(const RSA_private_key_t *key) +chunk_t pkcs1_build_private_key(const RSA_private_key_t *key) { chunk_t pkcs1 = asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm" , ASN1_INTEGER_0 @@ -627,44 +613,41 @@ pkcs1_build_private_key(const RSA_private_key_t *key) return pkcs1; } -/* - * build a DER-encoded PKCS#1 public key object +/** + * Build a DER-encoded PKCS#1 public key object */ -chunk_t -pkcs1_build_public_key(const RSA_public_key_t *rsa) +chunk_t pkcs1_build_public_key(const RSA_public_key_t *rsa) { return asn1_wrap(ASN1_SEQUENCE, "mm" , asn1_integer_from_mpz(&rsa->n) , asn1_integer_from_mpz(&rsa->e)); } -/* - * build a DER-encoded publicKeyInfo object +/** + * Build a DER-encoded publicKeyInfo object */ -chunk_t -pkcs1_build_publicKeyInfo(const RSA_public_key_t *rsa) +chunk_t pkcs1_build_publicKeyInfo(const RSA_public_key_t *rsa) { chunk_t publicKey; chunk_t rawKey = pkcs1_build_public_key(rsa); + u_char *pos; - u_char *pos = build_asn1_object(&publicKey, ASN1_BIT_STRING - , 1 + rawKey.len); + pos = asn1_build_object(&publicKey, ASN1_BIT_STRING, 1 + rawKey.len); *pos++ = 0x00; mv_chunk(&pos, rawKey); return asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_rsaEncryption_id + , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION) , publicKey); } -void -free_RSA_public_content(RSA_public_key_t *rsa) + +void free_RSA_public_content(RSA_public_key_t *rsa) { mpz_clear(&rsa->n); mpz_clear(&rsa->e); } -void -free_RSA_private_content(RSA_private_key_t *rsak) +void free_RSA_private_content(RSA_private_key_t *rsak) { free_RSA_public_content(&rsak->pub); mpz_clear(&rsak->d); @@ -674,4 +657,3 @@ free_RSA_private_content(RSA_private_key_t *rsak) mpz_clear(&rsak->dQ); mpz_clear(&rsak->qInv); } - diff --git a/src/pluto/pkcs7.c b/src/pluto/pkcs7.c index 8283a0699..7fa2cb3a4 100644 --- a/src/pluto/pkcs7.c +++ b/src/pluto/pkcs7.c @@ -22,10 +22,12 @@ #include <freeswan.h> +#include <asn1/asn1.h> +#include <asn1/asn1_parser.h> +#include <asn1/oid.h> + #include "constants.h" #include "defs.h" -#include "asn1.h" -#include <asn1/oid.h> #include "log.h" #include "x509.h" #include "certs.h" @@ -37,54 +39,55 @@ const contentInfo_t empty_contentInfo = { { NULL, 0 } /* content */ }; -/* ASN.1 definition of the PKCS#7 ContentInfo type */ - +/** + * ASN.1 definition of the PKCS#7 ContentInfo type + */ static const asn1Object_t contentInfoObjects[] = { - { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */ - { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_BODY }, /* 2 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */ + { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */ + { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_BODY }, /* 2 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; - #define PKCS7_INFO_TYPE 1 #define PKCS7_INFO_CONTENT 2 -#define PKCS7_INFO_ROOF 4 - -/* ASN.1 definition of the PKCS#7 signedData type */ +/** + * ASN.1 definition of the PKCS#7 signedData type + */ static const asn1Object_t signedDataObjects[] = { - { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */ - { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */ - { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */ - { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */ - { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_LOOP }, /* 6 */ - { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */ - { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_LOOP }, /* 9 */ - { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */ - { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */ - { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */ - { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */ - { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */ - { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_OBJ }, /* 19 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */ - { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */ - { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */ - { 1, "end loop", ASN1_EOC, ASN1_END } /* 25 */ + { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ + { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */ + { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */ + { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */ + { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */ + { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_LOOP }, /* 6 */ + { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */ + { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */ + { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT | + ASN1_LOOP }, /* 9 */ + { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */ + { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */ + { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */ + { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ + { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */ + { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */ + { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */ + { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */ + { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */ + { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_OBJ }, /* 19 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ + { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */ + { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */ + { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */ + { 1, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; - #define PKCS7_DIGEST_ALG 3 #define PKCS7_SIGNED_CONTENT_INFO 5 #define PKCS7_SIGNED_CERT 7 @@ -95,28 +98,28 @@ static const asn1Object_t signedDataObjects[] = { #define PKCS7_AUTH_ATTRIBUTES 19 #define PKCS7_DIGEST_ENC_ALGORITHM 21 #define PKCS7_ENCRYPTED_DIGEST 22 -#define PKCS7_SIGNED_ROOF 26 - -/* ASN.1 definition of the PKCS#7 envelopedData type */ +/** + * ASN.1 definition of the PKCS#7 envelopedData type + */ static const asn1Object_t envelopedDataObjects[] = { - { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */ - { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */ - { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */ - { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */ - { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */ - { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */ - { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ - { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */ - { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */ - { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY } /* 14 */ + { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ + { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */ + { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */ + { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */ + { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */ + { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ + { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */ + { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */ + { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */ + { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */ + { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ + { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */ + { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */ + { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY }, /* 14 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; - #define PKCS7_ENVELOPED_VERSION 1 #define PKCS7_RECIPIENT_INFO_VERSION 4 #define PKCS7_ISSUER 6 @@ -128,7 +131,9 @@ static const asn1Object_t envelopedDataObjects[] = { #define PKCS7_ENCRYPTED_CONTENT 14 #define PKCS7_ENVELOPED_ROOF 15 -/* PKCS7 contentInfo OIDs */ +/** + * PKCS7 contentInfo OIDs + */ static u_char ASN1_pkcs7_data_oid_str[] = { 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 @@ -167,7 +172,9 @@ static const chunk_t ASN1_pkcs7_digested_data_oid = static const chunk_t ASN1_pkcs7_encrypted_data_oid = chunk_from_buf(ASN1_pkcs7_encrypted_data_oid_str); -/* 3DES and DES encryption OIDs */ +/** + * 3DES and DES encryption OIDs + */ static u_char ASN1_3des_ede_cbc_oid_str[] = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07 @@ -182,7 +189,9 @@ static const chunk_t ASN1_3des_ede_cbc_oid = static const chunk_t ASN1_des_cbc_oid = chunk_from_buf(ASN1_des_cbc_oid_str); -/* PKCS#7 attribute type OIDs */ +/** + * PKCS#7 attribute type OIDs + */ static u_char ASN1_contentType_oid_str[] = { 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03 @@ -197,24 +206,21 @@ static const chunk_t ASN1_contentType_oid = static const chunk_t ASN1_messageDigest_oid = chunk_from_buf(ASN1_messageDigest_oid_str); -/* +/** * Parse PKCS#7 ContentInfo object */ -bool -pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo) +bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; + bool success = FALSE; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + parser = asn1_parser_create(contentInfoObjects, blob); + parser->set_top_level(parser, level0); - while (objectID < PKCS7_INFO_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(contentInfoObjects, &objectID, &object, &level, &ctx)) - return FALSE; - if (objectID == PKCS7_INFO_TYPE) { cInfo->type = asn1_known_oid(object); @@ -222,57 +228,60 @@ pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo) || cInfo->type > OID_PKCS7_ENCRYPTED_DATA) { plog("unknown pkcs7 content type"); - return FALSE; + goto end; } } else if (objectID == PKCS7_INFO_CONTENT) { cInfo->content = object; } - objectID++; } - return TRUE; + success = parser->success(parser); + +end: + parser->destroy(parser); + return success; } -/* +/** * Parse a PKCS#7 signedData object */ -bool -pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert -, chunk_t *attributes, const x509cert_t *cacert) +bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert, + chunk_t *attributes, const x509cert_t *cacert) { u_char buf[BUF_LEN]; - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; int digest_alg = OID_UNKNOWN; int enc_alg = OID_UNKNOWN; int signerInfos = 0; - int objectID = 0; + int objectID; + bool success = FALSE; contentInfo_t cInfo = empty_contentInfo; chunk_t encrypted_digest = chunk_empty; if (!pkcs7_parse_contentInfo(blob, 0, &cInfo)) + { return FALSE; - + } if (cInfo.type != OID_PKCS7_SIGNED_DATA) { plog("pkcs7 content type is not signedData"); return FALSE; } - asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW); + parser = asn1_parser_create(signedDataObjects, blob); + parser->set_top_level(parser, 2); - while (objectID < PKCS7_SIGNED_ROOF) - { - if (!extract_object(signedDataObjects, &objectID, &object, &level, &ctx)) - return FALSE; + while (parser->iterate(parser, &objectID, &object)) + { + u_int level = parser->get_level(parser); switch (objectID) { case PKCS7_DIGEST_ALG: - digest_alg = parse_algorithmIdentifier(object, level, NULL); + digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL); break; case PKCS7_SIGNED_CONTENT_INFO: if (data != NULL) @@ -322,15 +331,20 @@ pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert } break; case PKCS7_DIGEST_ALGORITHM: - digest_alg = parse_algorithmIdentifier(object, level, NULL); + digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL); break; case PKCS7_DIGEST_ENC_ALGORITHM: - enc_alg = parse_algorithmIdentifier(object, level, NULL); + enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL); break; case PKCS7_ENCRYPTED_DIGEST: encrypted_digest = object; } - objectID++; + } + success = parser->success(parser); + parser->destroy(parser); + if (!success) + { + return FALSE; } /* check the signature only if a cacert is available */ @@ -367,44 +381,45 @@ pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert return TRUE; } -/* +/** * Parse a PKCS#7 envelopedData object */ -bool -pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data -, chunk_t serialNumber, const RSA_private_key_t *key) +bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data, + chunk_t serialNumber, + const RSA_private_key_t *key) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; chunk_t iv = chunk_empty; chunk_t symmetric_key = chunk_empty; chunk_t encrypted_content = chunk_empty; u_char buf[BUF_LEN]; - u_int level; u_int total_keys = 3; int enc_alg = OID_UNKNOWN; int content_enc_alg = OID_UNKNOWN; - int objectID = 0; + int objectID; + bool success = FALSE; contentInfo_t cInfo = empty_contentInfo; *data = chunk_empty; if (!pkcs7_parse_contentInfo(blob, 0, &cInfo)) - goto failed; - + { + goto end; + } if (cInfo.type != OID_PKCS7_ENVELOPED_DATA) { plog("pkcs7 content type is not envelopedData"); - return FALSE; + goto end; } - asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW); + parser = asn1_parser_create(envelopedDataObjects, cInfo.content); + parser->set_top_level(parser, 2); - while (objectID < PKCS7_ENVELOPED_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(envelopedDataObjects, &objectID, &object, &level, &ctx)) - goto failed; + u_int level = parser->get_level(parser); switch (objectID) { @@ -412,14 +427,14 @@ pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data if (*object.ptr != 0) { plog("envelopedData version is not 0"); - goto failed; + goto end; } break; case PKCS7_RECIPIENT_INFO_VERSION: if (*object.ptr != 0) { plog("recipient info version is not 0"); - goto failed; + goto end; } break; case PKCS7_ISSUER: @@ -432,22 +447,22 @@ pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data if (!chunk_equals(serialNumber, object)) { plog("serial numbers do not match"); - goto failed; + goto end; } break; case PKCS7_ENCRYPTION_ALG: - enc_alg = parse_algorithmIdentifier(object, level, NULL); + enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL); if (enc_alg != OID_RSA_ENCRYPTION) { plog("only rsa encryption supported"); - goto failed; + goto end; } break; case PKCS7_ENCRYPTED_KEY: if (!RSA_decrypt(key, object, &symmetric_key)) { plog("symmetric key could not be decrypted with rsa"); - goto failed; + goto end; } DBG(DBG_PRIVATE, DBG_dump_chunk("symmetric key :", symmetric_key) @@ -457,11 +472,11 @@ pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data if (asn1_known_oid(object) != OID_PKCS7_DATA) { plog("encrypted content not of type pkcs7 data"); - goto failed; + goto end; } break; case PKCS7_CONTENT_ENC_ALGORITHM: - content_enc_alg = parse_algorithmIdentifier(object, level, &iv); + content_enc_alg = asn1_parse_algorithmIdentifier(object, level, &iv); switch (content_enc_alg) { @@ -473,29 +488,33 @@ pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data break; default: plog("Only DES and 3DES supported for symmetric encryption"); - goto failed; + goto end; } if (symmetric_key.len != (total_keys * DES_CBC_BLOCK_SIZE)) { plog("key length is not %d",(total_keys * DES_CBC_BLOCK_SIZE)); - goto failed; + goto end; } - if (!parse_asn1_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV")) + if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV")) { plog("IV could not be parsed"); - goto failed; + goto end; } if (iv.len != DES_CBC_BLOCK_SIZE) { plog("IV has wrong length"); - goto failed; + goto end; } break; case PKCS7_ENCRYPTED_CONTENT: encrypted_content = object; break; } - objectID++; + } +; + if (!parser->success(parser)) + { + goto end; } /* decrypt the content */ @@ -512,7 +531,7 @@ pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data if (des_set_key(&des_key[i], key_s[i])) { plog("des key schedule failed"); - goto failed; + goto end; } } @@ -546,7 +565,7 @@ pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data if (padding > data->len) { plog("padding greater than data length"); - goto failed; + goto end; } data->len -= padding; @@ -555,17 +574,19 @@ pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data if (*pos-- != pattern) { plog("wrong padding pattern"); - goto failed; + goto end; } } } - chunk_clear(&symmetric_key); - return TRUE; + success = TRUE; -failed: +end: chunk_clear(&symmetric_key); - free(data->ptr); - return FALSE; + if (!success) + { + free(data->ptr); + } + return success; } /** @@ -573,8 +594,7 @@ failed: * * @return ASN.1 encoded contentType attribute */ -chunk_t -pkcs7_contentType_attribute(void) +chunk_t pkcs7_contentType_attribute(void) { return asn1_wrap(ASN1_SEQUENCE, "cm" , ASN1_contentType_oid @@ -590,8 +610,7 @@ pkcs7_contentType_attribute(void) * @return ASN.1 encoded messageDigest attribute * */ -chunk_t -pkcs7_messageDigest_attribute(chunk_t content, int digest_alg) +chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg) { u_char digest_buf[MAX_DIGEST_LEN]; chunk_t digest = { digest_buf, MAX_DIGEST_LEN }; @@ -605,11 +624,11 @@ pkcs7_messageDigest_attribute(chunk_t content, int digest_alg) ) ); } -/* + +/** * build a DER-encoded contentInfo object */ -static chunk_t -pkcs7_build_contentInfo(contentInfo_t *cInfo) +static chunk_t pkcs7_build_contentInfo(contentInfo_t *cInfo) { chunk_t content_type; @@ -648,23 +667,22 @@ pkcs7_build_contentInfo(contentInfo_t *cInfo) ); } -/* +/** * build issuerAndSerialNumber object */ -chunk_t -pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert) +chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert) { return asn1_wrap(ASN1_SEQUENCE, "cm" , cert->issuer , asn1_simple_object(ASN1_INTEGER, cert->serialNumber)); } -/* +/** * create a signed pkcs7 contentInfo object */ -chunk_t -pkcs7_build_signedData(chunk_t data, chunk_t attributes, const x509cert_t *cert -, int digest_alg, const RSA_private_key_t *key) +chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes, + const x509cert_t *cert, int digest_alg, + const RSA_private_key_t *key) { contentInfo_t pkcs7Data, signedData; chunk_t authenticatedAttributes, encryptedDigest, signerInfo, cInfo; @@ -690,7 +708,7 @@ pkcs7_build_signedData(chunk_t data, chunk_t attributes, const x509cert_t *cert , pkcs7_build_issuerAndSerialNumber(cert) , digestAlgorithm , authenticatedAttributes - , ASN1_rsaEncryption_id + , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION) , encryptedDigest); pkcs7Data.type = OID_PKCS7_DATA; @@ -715,11 +733,10 @@ pkcs7_build_signedData(chunk_t data, chunk_t attributes, const x509cert_t *cert return cInfo; } -/* +/** * create a symmetrically encrypted pkcs7 contentInfo object */ -chunk_t -pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int cipher) +chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int cipher) { bool des_check_key_save; des_key_schedule ks[3]; @@ -833,7 +850,7 @@ pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int cipher) chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm" , ASN1_INTEGER_0 , pkcs7_build_issuerAndSerialNumber(cert) - , ASN1_rsaEncryption_id + , asn1_algorithmIdentifier(OID_RSA_ENCRYPTION) , encryptedKey); chunk_t cInfo; diff --git a/src/pluto/x509.c b/src/pluto/x509.c index 5d308eb90..7ef163683 100644 --- a/src/pluto/x509.c +++ b/src/pluto/x509.c @@ -28,13 +28,15 @@ #include <freeswan.h> #include <ipsec_policy.h> +#include <asn1/asn1.h> +#include <asn1/asn1_parser.h> +#include <asn1/oid.h> + #include "constants.h" #include "defs.h" #include "mp_defs.h" #include "log.h" #include "id.h" -#include "asn1.h" -#include <asn1/oid.h> #include "pkcs1.h" #include "x509.h" #include "crl.h" @@ -46,218 +48,190 @@ #include "ocsp.h" #include "sha1.h" -/* chained lists of X.509 end certificates */ - +/** + * Chained lists of X.509 end certificates + */ static x509cert_t *x509certs = NULL; -/* ASN.1 definition of a basicConstraints extension */ - +/** + * ASN.1 definition of a basicConstraints extension + */ static const asn1Object_t basicConstraintsObjects[] = { - { 0, "basicConstraints", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "CA", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 1 */ - { 1, "pathLenConstraint", ASN1_INTEGER, ASN1_OPT | - ASN1_BODY }, /* 2 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */ -}; - -#define BASIC_CONSTRAINTS_CA 1 -#define BASIC_CONSTRAINTS_ROOF 4 - -/* ASN.1 definition of time */ - -static const asn1Object_t timeObjects[] = { - { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT | - ASN1_BODY }, /* 0 */ - { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */ - { 0, "generalizeTime", ASN1_GENERALIZEDTIME, ASN1_OPT | - ASN1_BODY }, /* 2 */ - { 0, "end opt", ASN1_EOC, ASN1_END } /* 3 */ + { 0, "basicConstraints", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "CA", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 1 */ + { 1, "pathLenConstraint", ASN1_INTEGER, ASN1_OPT|ASN1_BODY }, /* 2 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define BASIC_CONSTRAINTS_CA 1 -#define TIME_UTC 0 -#define TIME_GENERALIZED 2 -#define TIME_ROOF 4 - -/* ASN.1 definition of a keyIdentifier */ - -static const asn1Object_t keyIdentifierObjects[] = { - { 0, "keyIdentifier", ASN1_OCTET_STRING, ASN1_BODY } /* 0 */ -}; - -/* ASN.1 definition of a authorityKeyIdentifier extension */ - -static const asn1Object_t authorityKeyIdentifierObjects[] = { - { 0, "authorityKeyIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "keyIdentifier", ASN1_CONTEXT_S_0, ASN1_OPT | - ASN1_OBJ }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "authorityCertIssuer", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_OBJ }, /* 3 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */ - { 1, "authorityCertSerialNumber", ASN1_CONTEXT_S_2, ASN1_OPT | - ASN1_BODY }, /* 5 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */ +/** + * ASN.1 definition of a authorityKeyIdentifier extension + */ +static const asn1Object_t authKeyIdentifierObjects[] = { + { 0, "authorityKeyIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "keyIdentifier", ASN1_CONTEXT_S_0, ASN1_OPT|ASN1_BODY }, /* 1 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ + { 1, "authorityCertIssuer", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_OBJ }, /* 3 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */ + { 1, "authorityCertSerialNumber", ASN1_CONTEXT_S_2, ASN1_OPT|ASN1_BODY }, /* 5 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define AUTH_KEY_ID_KEY_ID 1 +#define AUTH_KEY_ID_CERT_ISSUER 3 +#define AUTH_KEY_ID_CERT_SERIAL 5 -#define AUTH_KEY_ID_KEY_ID 1 -#define AUTH_KEY_ID_CERT_ISSUER 3 -#define AUTH_KEY_ID_CERT_SERIAL 5 -#define AUTH_KEY_ID_ROOF 7 - -/* ASN.1 definition of a authorityInfoAccess extension */ - -static const asn1Object_t authorityInfoAccessObjects[] = { - { 0, "authorityInfoAccess", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "accessDescription", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "accessMethod", ASN1_OID, ASN1_BODY }, /* 2 */ - { 2, "accessLocation", ASN1_EOC, ASN1_RAW }, /* 3 */ - { 0, "end loop", ASN1_EOC, ASN1_END } /* 4 */ +/** + * ASN.1 definition of a authorityInfoAccess extension + */ +static const asn1Object_t authInfoAccessObjects[] = { + { 0, "authorityInfoAccess", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ + { 1, "accessDescription", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ + { 2, "accessMethod", ASN1_OID, ASN1_BODY }, /* 2 */ + { 2, "accessLocation", ASN1_EOC, ASN1_RAW }, /* 3 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 4 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define AUTH_INFO_ACCESS_METHOD 2 +#define AUTH_INFO_ACCESS_LOCATION 3 -#define AUTH_INFO_ACCESS_METHOD 2 -#define AUTH_INFO_ACCESS_LOCATION 3 -#define AUTH_INFO_ACCESS_ROOF 5 - -/* ASN.1 definition of a extendedKeyUsage extension */ - +/** + * ASN.1 definition of a extendedKeyUsage extension + */ static const asn1Object_t extendedKeyUsageObjects[] = { - { 0, "extendedKeyUsage", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "keyPurposeID", ASN1_OID, ASN1_BODY }, /* 1 */ - { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */ + { 0, "extendedKeyUsage", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ + { 1, "keyPurposeID", ASN1_OID, ASN1_BODY }, /* 1 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define EXT_KEY_USAGE_PURPOSE_ID 1 -#define EXT_KEY_USAGE_PURPOSE_ID 1 -#define EXT_KEY_USAGE_ROOF 3 - -/* ASN.1 definition of generalNames */ - +/** + * ASN.1 definition of generalNames + */ static const asn1Object_t generalNamesObjects[] = { - { 0, "generalNames", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "generalName", ASN1_EOC, ASN1_RAW }, /* 1 */ - { 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */ + { 0, "generalNames", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ + { 1, "generalName", ASN1_EOC, ASN1_RAW }, /* 1 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define GENERAL_NAMES_GN 1 -#define GENERAL_NAMES_GN 1 -#define GENERAL_NAMES_ROOF 3 - -/* ASN.1 definition of generalName */ - +/** + * ASN.1 definition of generalName + */ static const asn1Object_t generalNameObjects[] = { - { 0, "otherName", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_BODY }, /* 0 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 1 */ - { 0, "rfc822Name", ASN1_CONTEXT_S_1, ASN1_OPT | - ASN1_BODY }, /* 2 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 3 */ - { 0, "dnsName", ASN1_CONTEXT_S_2, ASN1_OPT | - ASN1_BODY }, /* 4 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ - { 0, "x400Address", ASN1_CONTEXT_S_3, ASN1_OPT | - ASN1_BODY }, /* 6 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ - { 0, "directoryName", ASN1_CONTEXT_C_4, ASN1_OPT | - ASN1_BODY }, /* 8 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ - { 0, "ediPartyName", ASN1_CONTEXT_C_5, ASN1_OPT | - ASN1_BODY }, /* 10 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 11 */ - { 0, "uniformResourceIdentifier", ASN1_CONTEXT_S_6, ASN1_OPT | - ASN1_BODY }, /* 12 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 13 */ - { 0, "ipAddress", ASN1_CONTEXT_S_7, ASN1_OPT | - ASN1_BODY }, /* 14 */ - { 0, "end choice", ASN1_EOC, ASN1_END }, /* 15 */ - { 0, "registeredID", ASN1_CONTEXT_S_8, ASN1_OPT | - ASN1_BODY }, /* 16 */ - { 0, "end choice", ASN1_EOC, ASN1_END } /* 17 */ + { 0, "otherName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_BODY }, /* 0 */ + { 0, "end choice", ASN1_EOC, ASN1_END }, /* 1 */ + { 0, "rfc822Name", ASN1_CONTEXT_S_1, ASN1_OPT|ASN1_BODY }, /* 2 */ + { 0, "end choice", ASN1_EOC, ASN1_END }, /* 3 */ + { 0, "dnsName", ASN1_CONTEXT_S_2, ASN1_OPT|ASN1_BODY }, /* 4 */ + { 0, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ + { 0, "x400Address", ASN1_CONTEXT_S_3, ASN1_OPT|ASN1_BODY }, /* 6 */ + { 0, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ + { 0, "directoryName", ASN1_CONTEXT_C_4, ASN1_OPT|ASN1_BODY }, /* 8 */ + { 0, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ + { 0, "ediPartyName", ASN1_CONTEXT_C_5, ASN1_OPT|ASN1_BODY }, /* 10 */ + { 0, "end choice", ASN1_EOC, ASN1_END }, /* 11 */ + { 0, "URI", ASN1_CONTEXT_S_6, ASN1_OPT|ASN1_BODY }, /* 12 */ + { 0, "end choice", ASN1_EOC, ASN1_END }, /* 13 */ + { 0, "ipAddress", ASN1_CONTEXT_S_7, ASN1_OPT|ASN1_BODY }, /* 14 */ + { 0, "end choice", ASN1_EOC, ASN1_END }, /* 15 */ + { 0, "registeredID", ASN1_CONTEXT_S_8, ASN1_OPT|ASN1_BODY }, /* 16 */ + { 0, "end choice", ASN1_EOC, ASN1_END }, /* 17 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; - -#define GN_OBJ_OTHER_NAME 0 -#define GN_OBJ_RFC822_NAME 2 -#define GN_OBJ_DNS_NAME 4 -#define GN_OBJ_X400_ADDRESS 6 -#define GN_OBJ_DIRECTORY_NAME 8 -#define GN_OBJ_EDI_PARTY_NAME 10 -#define GN_OBJ_URI 12 -#define GN_OBJ_IP_ADDRESS 14 -#define GN_OBJ_REGISTERED_ID 16 -#define GN_OBJ_ROOF 18 - -/* ASN.1 definition of otherName */ - +#define GN_OBJ_OTHER_NAME 0 +#define GN_OBJ_RFC822_NAME 2 +#define GN_OBJ_DNS_NAME 4 +#define GN_OBJ_X400_ADDRESS 6 +#define GN_OBJ_DIRECTORY_NAME 8 +#define GN_OBJ_EDI_PARTY_NAME 10 +#define GN_OBJ_URI 12 +#define GN_OBJ_IP_ADDRESS 14 +#define GN_OBJ_REGISTERED_ID 16 + +/** + * ASN.1 definition of otherName + */ static const asn1Object_t otherNameObjects[] = { - {0, "type-id", ASN1_OID, ASN1_BODY }, /* 0 */ - {0, "value", ASN1_CONTEXT_C_0, ASN1_BODY } /* 1 */ + {0, "type-id", ASN1_OID, ASN1_BODY }, /* 0 */ + {0, "value", ASN1_CONTEXT_C_0, ASN1_BODY }, /* 1 */ + {0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define ON_OBJ_ID_TYPE 0 +#define ON_OBJ_VALUE 1 -#define ON_OBJ_ID_TYPE 0 -#define ON_OBJ_VALUE 1 -#define ON_OBJ_ROOF 2 - -/* ASN.1 definition of crlDistributionPoints */ - +/** + * ASN.1 definition of crlDistributionPoints + */ static const asn1Object_t crlDistributionPointsObjects[] = { - { 0, "crlDistributionPoints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ - { 1, "DistributionPoint", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "distributionPoint", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_LOOP }, /* 2 */ - { 3, "fullName", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_OBJ }, /* 3 */ - { 3, "end choice", ASN1_EOC, ASN1_END }, /* 4 */ - { 3, "nameRelativeToCRLIssuer", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_BODY }, /* 5 */ - { 3, "end choice", ASN1_EOC, ASN1_END }, /* 6 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 7 */ - { 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_BODY }, /* 8 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ - { 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT | - ASN1_BODY }, /* 10 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ - { 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */ + { 0, "crlDistributionPoints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ + { 1, "DistributionPoint", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ + { 2, "distributionPoint", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 2 */ + { 3, "fullName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 3 */ + { 3, "end choice", ASN1_EOC, ASN1_END }, /* 4 */ + { 3, "nameRelToCRLIssuer",ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 5 */ + { 3, "end choice", ASN1_EOC, ASN1_END }, /* 6 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 7 */ + { 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 8 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ + { 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_BODY }, /* 10 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; +#define CRL_DIST_POINTS_FULLNAME 3 -#define CRL_DIST_POINTS_FULLNAME 3 -#define CRL_DIST_POINTS_ROOF 13 - -/* ASN.1 definition of an X.509v3 certificate */ +/** + * ASN.1 definition of RSApublicKey + */ +static const asn1Object_t pubkeyObjects[] = { + { 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ + { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */ + { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } +}; +#define PUB_KEY_RSA_PUBLIC_KEY 0 +#define PUB_KEY_MODULUS 1 +#define PUB_KEY_EXPONENT 2 +/** + * ASN.1 definition of an X.509v3 x509_cert + */ static const asn1Object_t certObjects[] = { - { 0, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ - { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */ - { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ - { 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */ - { 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */ - { 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */ - { 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */ - { 2, "subjectPublicKeyInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ - { 3, "algorithm", ASN1_EOC, ASN1_RAW }, /* 12 */ - { 3, "subjectPublicKey", ASN1_BIT_STRING, ASN1_NONE }, /* 13 */ - { 4, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 14 */ - { 5, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 15 */ - { 5, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 16 */ - { 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 17 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 18 */ - { 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 19 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 21 */ - { 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 22 */ - { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 23 */ - { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 24 */ - { 5, "critical", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 25 */ - { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 26 */ - { 3, "end loop", ASN1_EOC, ASN1_END }, /* 27 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 28 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 29 */ - { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 30 */ + { 0, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ + { 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ + { 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */ + { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ + { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */ + { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */ + { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ + { 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */ + { 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */ + { 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */ + { 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */ + { 2, "subjectPublicKeyInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ + { 3, "algorithm", ASN1_EOC, ASN1_RAW }, /* 12 */ + { 3, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 13 */ + { 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 14 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 15 */ + { 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 16 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ + { 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 18 */ + { 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 19 */ + { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 20 */ + { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 21 */ + { 5, "critical", ASN1_BOOLEAN, ASN1_DEF | + ASN1_BODY }, /* 22 */ + { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 23 */ + { 3, "end loop", ASN1_EOC, ASN1_END }, /* 24 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 25 */ + { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 26 */ + { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 27 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; - #define X509_OBJ_CERTIFICATE 0 #define X509_OBJ_TBS_CERTIFICATE 1 #define X509_OBJ_VERSION 3 @@ -269,16 +243,11 @@ static const asn1Object_t certObjects[] = { #define X509_OBJ_SUBJECT 10 #define X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM 12 #define X509_OBJ_SUBJECT_PUBLIC_KEY 13 -#define X509_OBJ_RSA_PUBLIC_KEY 14 -#define X509_OBJ_MODULUS 15 -#define X509_OBJ_PUBLIC_EXPONENT 16 -#define X509_OBJ_EXTN_ID 24 -#define X509_OBJ_CRITICAL 25 -#define X509_OBJ_EXTN_VALUE 26 -#define X509_OBJ_ALGORITHM 29 -#define X509_OBJ_SIGNATURE 30 -#define X509_OBJ_ROOF 31 - +#define X509_OBJ_EXTN_ID 21 +#define X509_OBJ_CRITICAL 22 +#define X509_OBJ_EXTN_VALUE 23 +#define X509_OBJ_ALGORITHM 26 +#define X509_OBJ_SIGNATURE 27 const x509cert_t empty_x509cert = { NULL , /* *next */ @@ -396,19 +365,17 @@ static u_char ASN1_subjectAltName_oid_str[] = { static const chunk_t ASN1_subjectAltName_oid = chunk_from_buf(ASN1_subjectAltName_oid_str); -static void -update_chunk(chunk_t *ch, int n) +static void update_chunk(chunk_t *ch, int n) { n = (n > -1 && n < (int)ch->len)? n : (int)ch->len-1; ch->ptr += n; ch->len -= n; } -/* +/** * Pointer is set to the first RDN in a DN */ -static err_t -init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next) +static err_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next) { *rdn = chunk_empty; *attribute = chunk_empty; @@ -434,12 +401,11 @@ init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next) return NULL; } -/* +/** * Fetches the next RDN in a DN */ -static err_t -get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value -, asn1_t *type, bool *next) +static err_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, + chunk_t *value, asn1_t *type, bool *next) { chunk_t body; @@ -524,11 +490,10 @@ get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value return NULL; } -/* +/** * Parses an ASN.1 distinguished name int its OID/value pairs */ -static err_t -dn_parse(chunk_t dn, chunk_t *str) +static err_t dn_parse(chunk_t dn, chunk_t *str) { chunk_t rdn, oid, attribute, value; asn1_t type; @@ -580,11 +545,10 @@ dn_parse(chunk_t dn, chunk_t *str) return NULL; } -/* +/** * Count the number of wildcard RDNs in a distinguished name */ -int -dn_count_wildcards(chunk_t dn) +int dn_count_wildcards(chunk_t dn) { chunk_t rdn, attribute, oid, value; asn1_t type; @@ -614,11 +578,10 @@ dn_count_wildcards(chunk_t dn) return wildcards; } -/* +/** * Prints a binary string in hexadecimal form */ -void -hex_str(chunk_t bin, chunk_t *str) +void hex_str(chunk_t bin, chunk_t *str) { u_int i; update_chunk(str, snprintf(str->ptr,str->len,"0x")); @@ -627,11 +590,10 @@ hex_str(chunk_t bin, chunk_t *str) } -/* Converts a binary DER-encoded ASN.1 distinguished name +/** Converts a binary DER-encoded ASN.1 distinguished name * into LDAP-style human-readable ASCII format */ -int -dntoa(char *dst, size_t dstlen, chunk_t dn) +int dntoa(char *dst, size_t dstlen, chunk_t dn) { err_t ugh = NULL; chunk_t str; @@ -652,11 +614,10 @@ dntoa(char *dst, size_t dstlen, chunk_t dn) return (int)(dstlen - str.len); } -/* +/** * Same as dntoa but prints a special string for a null dn */ -int -dntoa_or_null(char *dst, size_t dstlen, chunk_t dn, const char* null_dn) +int dntoa_or_null(char *dst, size_t dstlen, chunk_t dn, const char* null_dn) { if (dn.ptr == NULL) { @@ -668,11 +629,45 @@ dntoa_or_null(char *dst, size_t dstlen, chunk_t dn, const char* null_dn) } } -/* Converts an LDAP-style human-readable ASCII-encoded + +/** + * Codes ASN.1 lengths up to a size of 16'777'215 bytes + */ +static void code_asn1_length(size_t length, chunk_t *code) +{ + if (length < 128) + { + code->ptr[0] = length; + code->len = 1; + } + else if (length < 256) + { + code->ptr[0] = 0x81; + code->ptr[1] = (u_char) length; + code->len = 2; + } + else if (length < 65536) + { + code->ptr[0] = 0x82; + code->ptr[1] = length >> 8; + code->ptr[2] = length & 0x00ff; + code->len = 3; + } + else + { + code->ptr[0] = 0x83; + code->ptr[1] = length >> 16; + code->ptr[2] = (length >> 8) & 0x00ff; + code->ptr[3] = length & 0x0000ff; + code->len = 4; + } +} + +/** + * Converts an LDAP-style human-readable ASCII-encoded * ASN.1 distinguished name into binary DER-encoded format */ -err_t -atodn(char *src, chunk_t *dn) +err_t atodn(char *src, chunk_t *dn) { /* finite state machine for atodn */ @@ -796,7 +791,7 @@ atodn(char *src, chunk_t *dn) chunkcpy(dn_ptr, x501rdns[pos].oid); /* encode the ASN.1 character string type of the name */ *dn_ptr++ = (x501rdns[pos].type == ASN1_PRINTABLESTRING - && !is_printablestring(name))? ASN1_T61STRING : x501rdns[pos].type; + && !asn1_is_printablestring(name))? ASN1_T61STRING : x501rdns[pos].type; chunkcpy(dn_ptr, asn1_name_len); chunkcpy(dn_ptr, name); @@ -823,11 +818,10 @@ atodn(char *src, chunk_t *dn) return ugh; } -/* compare two distinguished names by - * comparing the individual RDNs +/** + * compare two distinguished names by comparing the individual RDNs */ -bool -same_dn(chunk_t a, chunk_t b) +bool same_dn(chunk_t a, chunk_t b) { chunk_t rdn_a, rdn_b, attribute_a, attribute_b; chunk_t oid_a, oid_b, value_a, value_b; @@ -903,11 +897,11 @@ same_dn(chunk_t a, chunk_t b) } -/* compare two distinguished names by comparing the individual RDNs. +/** + * Compare two distinguished names by comparing the individual RDNs. * A single'*' character designates a wildcard RDN in DN b. */ -bool -match_dn(chunk_t a, chunk_t b, int *wildcards) +bool match_dn(chunk_t a, chunk_t b, int *wildcards) { chunk_t rdn_a, rdn_b, attribute_a, attribute_b; chunk_t oid_a, oid_b, value_a, value_b; @@ -981,20 +975,18 @@ match_dn(chunk_t a, chunk_t b, int *wildcards) return TRUE; } -/* - * compare two X.509 certificates by comparing their signatures +/** + * Compare two X.509 certificates by comparing their signatures */ -bool -same_x509cert(const x509cert_t *a, const x509cert_t *b) +bool same_x509cert(const x509cert_t *a, const x509cert_t *b) { return chunk_equals(a->signature, b->signature); } -/* for each link pointing to the certificate - " increase the count by one +/** + * For each link pointing to the certificate increase the count by one */ -void -share_x509cert(x509cert_t *cert) +void share_x509cert(x509cert_t *cert) { if (cert != NULL) { @@ -1002,11 +994,10 @@ share_x509cert(x509cert_t *cert) } } -/* - * add a X.509 user/host certificate to the chained list +/** + * Add a X.509 user/host certificate to the chained list */ -x509cert_t* -add_x509cert(x509cert_t *cert) +x509cert_t* add_x509cert(x509cert_t *cert) { x509cert_t *c = x509certs; @@ -1031,11 +1022,10 @@ add_x509cert(x509cert_t *cert) return cert; } -/* - * choose either subject DN or a subjectAltName as connection end ID +/** + * Choose either subject DN or a subjectAltName as connection end ID */ -void -select_x509cert_id(x509cert_t *cert, struct id *end_id) +void select_x509cert_id(x509cert_t *cert, struct id *end_id) { bool copy_subject_dn = TRUE; /* ID is subject DN */ @@ -1073,11 +1063,10 @@ select_x509cert_id(x509cert_t *cert, struct id *end_id) } } -/* - * check for equality between two key identifiers +/** + * Check for equality between two key identifiers */ -bool -same_keyid(chunk_t a, chunk_t b) +bool same_keyid(chunk_t a, chunk_t b) { if (a.ptr == NULL || b.ptr == NULL) { @@ -1086,11 +1075,10 @@ same_keyid(chunk_t a, chunk_t b) return chunk_equals(a, b); } -/* - * check for equality between two serial numbers +/** + * Check for equality between two serial numbers */ -bool -same_serial(chunk_t a, chunk_t b) +bool same_serial(chunk_t a, chunk_t b) { /* do not compare serial numbers if one of them is not defined */ if (a.ptr == NULL || b.ptr == NULL) @@ -1100,11 +1088,11 @@ same_serial(chunk_t a, chunk_t b) return chunk_equals(a, b); } -/* - * get a X.509 certificate with a given issuer found at a certain position +/** + * Get a X.509 certificate with a given issuer found at a certain position */ -x509cert_t* -get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid, x509cert_t *chain) +x509cert_t* get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid, + x509cert_t *chain) { x509cert_t *cert = (chain != NULL)? chain->next : x509certs; @@ -1121,11 +1109,10 @@ get_x509cert(chunk_t issuer, chunk_t serial, chunk_t keyid, x509cert_t *chain) return NULL; } -/* - * encode a linked list of subjectAltNames +/** + * Encode a linked list of subjectAltNames */ -chunk_t -build_subjectAltNames(generalName_t *subjectAltNames) +chunk_t build_subjectAltNames(generalName_t *subjectAltNames) { u_char *pos; chunk_t names; @@ -1139,7 +1126,7 @@ build_subjectAltNames(generalName_t *subjectAltNames) gn = gn->next; } - pos = build_asn1_object(&names, ASN1_SEQUENCE, len); + pos = asn1_build_object(&names, ASN1_SEQUENCE, len); gn = subjectAltNames; while (gn != NULL) @@ -1153,11 +1140,10 @@ build_subjectAltNames(generalName_t *subjectAltNames) , asn1_wrap(ASN1_OCTET_STRING, "m", names)); } -/* - * build a to-be-signed X.509 certificate body +/** + * Build a to-be-signed X.509 certificate body */ -static chunk_t -build_tbs_x509cert(x509cert_t *cert, const RSA_public_key_t *rsa) +static chunk_t build_tbs_x509cert(x509cert_t *cert, const RSA_public_key_t *rsa) { /* version is always X.509v3 */ chunk_t version = asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2); @@ -1177,8 +1163,8 @@ build_tbs_x509cert(x509cert_t *cert, const RSA_public_key_t *rsa) , asn1_algorithmIdentifier(cert->sigAlg) , cert->issuer , asn1_wrap(ASN1_SEQUENCE, "mm" - , timetoasn1(&cert->notBefore, ASN1_UTCTIME) - , timetoasn1(&cert->notAfter, ASN1_UTCTIME) + , asn1_from_time(&cert->notBefore, ASN1_UTCTIME) + , asn1_from_time(&cert->notAfter, ASN1_UTCTIME) ) , cert->subject , pkcs1_build_publicKeyInfo(rsa) @@ -1186,12 +1172,11 @@ build_tbs_x509cert(x509cert_t *cert, const RSA_public_key_t *rsa) ); } -/* - * build a DER-encoded X.509 certificate +/** + * Build a DER-encoded X.509 certificate */ -void -build_x509cert(x509cert_t *cert, const RSA_public_key_t *cert_key -, const RSA_private_key_t *signer_key) +void build_x509cert(x509cert_t *cert, const RSA_public_key_t *cert_key, + const RSA_private_key_t *signer_key) { chunk_t tbs_cert = build_tbs_x509cert(cert, cert_key); @@ -1204,11 +1189,10 @@ build_x509cert(x509cert_t *cert, const RSA_public_key_t *cert_key , signature); } -/* - * free the dynamic memory used to store generalNames +/** + * Free the dynamic memory used to store generalNames */ -void -free_generalNames(generalName_t* gn, bool free_name) +void free_generalNames(generalName_t* gn, bool free_name) { while (gn != NULL) { @@ -1222,11 +1206,10 @@ free_generalNames(generalName_t* gn, bool free_name) } } -/* - * free a X.509 certificate +/** + * Free a X.509 certificate */ -void -free_x509cert(x509cert_t *cert) +void free_x509cert(x509cert_t *cert) { if (cert != NULL) { @@ -1238,11 +1221,11 @@ free_x509cert(x509cert_t *cert) } } -/* release of a certificate decreases the count by one - " the certificate is freed when the counter reaches zero +/** + * Release of a certificate decreases the count by one + * the certificate is freed when the counter reaches zero */ -void -release_x509cert(x509cert_t *cert) +void release_x509cert(x509cert_t *cert) { if (cert != NULL && --cert->count == 0) { @@ -1256,12 +1239,10 @@ release_x509cert(x509cert_t *cert) } } - -/* - * stores a chained list of end certs and CA certs +/** + * Stores a chained list of end certs and CA certs */ -void -store_x509certs(x509cert_t **firstcert, bool strict) +void store_x509certs(x509cert_t **firstcert, bool strict) { x509cert_t *cacerts = NULL; x509cert_t **pp = firstcert; @@ -1339,12 +1320,11 @@ store_x509certs(x509cert_t **firstcert, bool strict) } } -/* - * decrypts an RSA signature using the issuer's certificate +/** + * Decrypts an RSA signature using the issuer's certificate */ -static bool -decrypt_sig(chunk_t sig, int alg, const x509cert_t *issuer_cert, - chunk_t *digest) +static bool decrypt_sig(chunk_t sig, int alg, const x509cert_t *issuer_cert, + chunk_t *digest) { switch (alg) { @@ -1393,12 +1373,11 @@ decrypt_sig(chunk_t sig, int alg, const x509cert_t *issuer_cert, } } -/* - * Check if a signature over binary blob is genuine +/** + * Check if a signature over binary blob is genuine */ -bool -check_signature(chunk_t tbs, chunk_t sig, int digest_alg, int enc_alg -, const x509cert_t *issuer_cert) +bool check_signature(chunk_t tbs, chunk_t sig, int digest_alg, int enc_alg, + const x509cert_t *issuer_cert) { u_char digest_buf[MAX_DIGEST_LEN]; u_char decrypted_buf[MAX_DIGEST_LEN]; @@ -1449,27 +1428,21 @@ check_signature(chunk_t tbs, chunk_t sig, int digest_alg, int enc_alg return memeq(decrypted.ptr, digest.ptr, digest.len); } -/* - * extracts the basicConstraints extension +/** + * Extracts the basicConstraints extension */ -static bool -parse_basicConstraints(chunk_t blob, int level0) +static bool parse_basicConstraints(chunk_t blob, int level0) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; bool isCA = FALSE; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + parser = asn1_parser_create(basicConstraintsObjects, blob); + parser->set_top_level(parser, level0); - while (objectID < BASIC_CONSTRAINTS_ROOF) { - - if (!extract_object(basicConstraintsObjects, &objectID, - &object,&level, &ctx)) - { - break; - } + while (parser->iterate(parser, &objectID, &object)) + { if (objectID == BASIC_CONSTRAINTS_CA) { isCA = object.len && *object.ptr; @@ -1477,16 +1450,16 @@ parse_basicConstraints(chunk_t blob, int level0) DBG_log(" %s",(isCA)?"TRUE":"FALSE"); ) } - objectID++; } + parser->destroy(parser); + return isCA; } -/* +/** * Converts a X.500 generalName into an ID */ -void -gntoid(struct id *id, const generalName_t *gn) +void gntoid(struct id *id, const generalName_t *gn) { switch(gn->kind) { @@ -1513,11 +1486,11 @@ gntoid(struct id *id, const generalName_t *gn) } } -/* compute the subjectKeyIdentifier according to section 4.2.1.2 of RFC 3280 +/** + * Compute the subjectKeyIdentifier according to section 4.2.1.2 of RFC 3280 * as the 160 bit SHA-1 hash of the public key */ -void -compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID) +void compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID) { SHA1_CTX context; @@ -1529,27 +1502,22 @@ compute_subjectKeyID(x509cert_t *cert, chunk_t subjectKeyID) subjectKeyID.len = SHA1_DIGEST_SIZE; } -/* - * extracts an otherName +/** + * Extracts an otherName */ -static bool -parse_otherName(chunk_t blob, int level0) +static bool parse_otherName(chunk_t blob, int level0) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - int objectID = 0; - u_int level; + int objectID; int oid = OID_UNKNOWN; + bool success = FALSE; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + parser = asn1_parser_create(otherNameObjects, blob); + parser->set_top_level(parser, level0); - while (objectID < ON_OBJ_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(otherNameObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - switch (objectID) { case ON_OBJ_ID_TYPE: @@ -1558,45 +1526,43 @@ parse_otherName(chunk_t blob, int level0) case ON_OBJ_VALUE: if (oid == OID_XMPP_ADDR) { - if (!parse_asn1_simple_object(&object, ASN1_UTF8STRING - , level + 1, "xmppAddr")) + if (!asn1_parse_simple_object(&object, ASN1_UTF8STRING, + parser->get_level(parser) + 1, "xmppAddr")) { - return FALSE; + goto end; } } break; default: break; } - objectID++; } - return TRUE; + success = parser->success(parser); + +end: + parser->destroy(parser); + return success; } -/* - * extracts a generalName +/** + * Extracts a generalName */ -static generalName_t* -parse_generalName(chunk_t blob, int level0) +static generalName_t* parse_generalName(chunk_t blob, int level0) { u_char buf[BUF_LEN]; - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - int objectID = 0; - u_int level; + generalName_t *gn = NULL; + int objectID; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - - while (objectID < GN_OBJ_ROOF) + parser = asn1_parser_create(generalNameObjects, blob); + parser->set_top_level(parser, level0); + + while (parser->iterate(parser, &objectID, &object)) { bool valid_gn = FALSE; - if (!extract_object(generalNameObjects, &objectID, &object, &level, &ctx)) - { - return NULL; - } - switch (objectID) { case GN_OBJ_RFC822_NAME: case GN_OBJ_DNS_NAME: @@ -1621,8 +1587,10 @@ parse_generalName(chunk_t blob, int level0) valid_gn = TRUE; break; case GN_OBJ_OTHER_NAME: - if (!parse_otherName(object, level + 1)) - return NULL; + if (!parse_otherName(object, parser->get_level(parser)+1)) + { + goto end; + } break; case GN_OBJ_X400_ADDRESS: case GN_OBJ_EDI_PARTY_NAME: @@ -1634,55 +1602,53 @@ parse_generalName(chunk_t blob, int level0) if (valid_gn) { - generalName_t *gn = malloc_thing(generalName_t); + gn = malloc_thing(generalName_t); gn->kind = (objectID - GN_OBJ_OTHER_NAME) / 2; gn->name = object; gn->next = NULL; - return gn; + goto end; } - objectID++; } - return NULL; + +end: + parser->destroy(parser); + return gn; } - -/* - * extracts one or several GNs and puts them into a chained list +/** + * Extracts one or several GNs and puts them into a chained list */ -static generalName_t* -parse_generalNames(chunk_t blob, int level0, bool implicit) +static generalName_t* parse_generalNames(chunk_t blob, int level0, bool implicit) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; - + int objectID; generalName_t *top_gn = NULL; - asn1_init(&ctx, blob, level0, implicit, DBG_RAW); - - while (objectID < GENERAL_NAMES_ROOF) + parser = asn1_parser_create(generalNamesObjects, blob); + parser->set_top_level(parser, level0); + parser->set_flags(parser, implicit, FALSE); + + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(generalNamesObjects, &objectID, &object, &level, &ctx)) - { - return NULL; - } if (objectID == GENERAL_NAMES_GN) { - generalName_t *gn = parse_generalName(object, level+1); - if (gn != NULL) + generalName_t *gn = parse_generalName(object, + parser->get_level(parser)+1); + if (gn) { gn->next = top_gn; top_gn = gn; } } - objectID++; } + parser->destroy(parser); + return top_gn; } -/* - * returns a directoryName +/** + * Returns a directoryName */ chunk_t get_directoryName(chunk_t blob, int level, bool implicit) { @@ -1697,80 +1663,31 @@ chunk_t get_directoryName(chunk_t blob, int level, bool implicit) return name; } -/* - * extracts and converts a UTCTIME or GENERALIZEDTIME object +/** + * Extracts an authoritykeyIdentifier */ -time_t -parse_time(chunk_t blob, int level0) +void parse_authorityKeyIdentifier(chunk_t blob, int level0, + chunk_t *authKeyID, + chunk_t *authKeySerialNumber) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - - while (objectID < TIME_ROOF) - { - if (!extract_object(timeObjects, &objectID, &object, &level, &ctx)) - { - return UNDEFINED_TIME; - } - if (objectID == TIME_UTC || objectID == TIME_GENERALIZED) - { - return asn1totime(&object, (objectID == TIME_UTC) - ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME); - } - objectID++; - } - return UNDEFINED_TIME; - } - -/* - * extracts a keyIdentifier - */ -static chunk_t -parse_keyIdentifier(chunk_t blob, int level0, bool implicit) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, implicit, DBG_RAW); + int objectID; - extract_object(keyIdentifierObjects, &objectID, &object, &level, &ctx); - return object; -} - -/* - * extracts an authoritykeyIdentifier - */ -void -parse_authorityKeyIdentifier(chunk_t blob, int level0 - , chunk_t *authKeyID, chunk_t *authKeySerialNumber) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - - while (objectID < AUTH_KEY_ID_ROOF) + parser = asn1_parser_create(authKeyIdentifierObjects, blob); + parser->set_top_level(parser, level0); + + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(authorityKeyIdentifierObjects, &objectID, &object, &level, &ctx)) - { - return; - } switch (objectID) { case AUTH_KEY_ID_KEY_ID: - *authKeyID = parse_keyIdentifier(object, level+1, TRUE); + *authKeyID = object; break; case AUTH_KEY_ID_CERT_ISSUER: { - generalName_t * gn = parse_generalNames(object, level+1, TRUE); + generalName_t * gn = parse_generalNames(object, + parser->get_level(parser) + 1, TRUE); free_generalNames(gn, FALSE); } @@ -1781,31 +1698,26 @@ parse_authorityKeyIdentifier(chunk_t blob, int level0 default: break; } - objectID++; } + parser->destroy(parser); } -/* - * extracts an authorityInfoAcess location +/** + * Extracts an authorityInfoAcess location */ -static void -parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessLocation) +static void parse_authorityInfoAccess(chunk_t blob, int level0, + chunk_t *accessLocation) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; int accessMethod = OID_UNKNOWN; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - - while (objectID < AUTH_INFO_ACCESS_ROOF) + parser = asn1_parser_create(authInfoAccessObjects, blob); + parser->set_top_level(parser, level0); + + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(authorityInfoAccessObjects, &objectID, &object, &level, &ctx)) - { - return; - } - switch (objectID) { case AUTH_INFO_ACCESS_METHOD: @@ -1820,7 +1732,7 @@ parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessLocation) { if (asn1_length(&object) == ASN1_INVALID_LENGTH) { - return; + goto end; } DBG(DBG_PARSING, DBG_log(" '%.*s'",(int)object.len, object.ptr) @@ -1830,7 +1742,7 @@ parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessLocation) if (strncasecmp(object.ptr, "http", 4) == 0) { *accessLocation = object; - return; + goto end; } } plog("warning: ignoring OCSP InfoAccessLocation with unkown protocol"); @@ -1844,67 +1756,61 @@ parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessLocation) default: break; } - objectID++; } - + +end: + parser->destroy(parser); } -/* - * extracts extendedKeyUsage OIDs +/** + * Extracts extendedKeyUsage OIDs */ -static bool -parse_extendedKeyUsage(chunk_t blob, int level0) +static bool parse_extendedKeyUsage(chunk_t blob, int level0) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; + bool ocsp_signing = FALSE; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - - while (objectID < EXT_KEY_USAGE_ROOF) + parser = asn1_parser_create(extendedKeyUsageObjects, blob); + parser->set_top_level(parser, level0); + + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(extendedKeyUsageObjects, &objectID - , &object, &level, &ctx)) - { - return FALSE; - } if (objectID == EXT_KEY_USAGE_PURPOSE_ID && asn1_known_oid(object) == OID_OCSP_SIGNING) { - return TRUE; + ocsp_signing = TRUE; } - objectID++; } - return FALSE; + parser->destroy(parser); + + return ocsp_signing; } -/* extracts one or several crlDistributionPoints and puts them into - * a chained list +/** + * Extracts one or several crlDistributionPoints + * and puts them into a chained list */ -static generalName_t* -parse_crlDistributionPoints(chunk_t blob, int level0) +static generalName_t* parse_crlDistributionPoints(chunk_t blob, int level0) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; generalName_t *top_gn = NULL; /* top of the chained list */ generalName_t **tail_gn = &top_gn; /* tail of the chained list */ - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - - while (objectID < CRL_DIST_POINTS_ROOF) + parser = asn1_parser_create(crlDistributionPointsObjects, blob); + parser->set_top_level(parser, level0); + + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(crlDistributionPointsObjects, &objectID, - &object, &level, &ctx)) - { - return NULL; - } if (objectID == CRL_DIST_POINTS_FULLNAME) { - generalName_t *gn = parse_generalNames(object, level+1, TRUE); + generalName_t *gn; + + gn = parse_generalNames(object, parser->get_level(parser)+1, TRUE); /* append extracted generalNames to existing chained list */ *tail_gn = gn; /* find new tail of the chained list */ @@ -1913,38 +1819,76 @@ parse_crlDistributionPoints(chunk_t blob, int level0) tail_gn = &gn->next; gn = gn->next; } } - objectID++; } + parser->destroy(parser); + return top_gn; } +/** + * Parses an RSA public key + */ +bool parse_RSA_public_key(chunk_t blob, u_int level0, x509cert_t *cert) +{ + asn1_parser_t *parser; + chunk_t object; + int objectID; + bool success = FALSE; + + parser = asn1_parser_create(pubkeyObjects, blob); + parser->set_top_level(parser, level0); + + while (parser->iterate(parser, &objectID, &object)) + { + switch (objectID) { + case PUB_KEY_RSA_PUBLIC_KEY: + cert->subjectPublicKey = object; + break; + case PUB_KEY_MODULUS: + if (object.len < RSA_MIN_OCTETS + 1) + { + plog(" " RSA_MIN_OCTETS_UGH); + goto end; + } + if (object.len > RSA_MAX_OCTETS + (size_t)(*object.ptr == 0x00)) + { + plog(" " RSA_MAX_OCTETS_UGH); + goto end; + } + cert->modulus = object; + break; + case PUB_KEY_EXPONENT: + cert->publicExponent = object; + break; + } + } + success = parser->success(parser); + +end: + parser->destroy(parser); + return success; +} -/* +/** * Parses an X.509v3 certificate */ -bool -parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert) +bool parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert) { u_char buf[BUF_LEN]; - asn1_ctx_t ctx; - bool critical; + asn1_parser_t *parser; chunk_t object; - u_int level; - int objectID = 0; + int objectID; int extn_oid = OID_UNKNOWN; + bool critical; + bool success = FALSE; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + parser = asn1_parser_create(certObjects, blob); + parser->set_top_level(parser, level0); - while (objectID < X509_OBJ_ROOF) + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(certObjects, &objectID, &object, &level, &ctx)) - { - return FALSE; - } - - /* those objects which will parsed further need the next higher level */ - level++; - + u_int level = parser->get_level(parser) + 1; + switch (objectID) { case X509_OBJ_CERTIFICATE: cert->certificate = object; @@ -1962,7 +1906,7 @@ parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert) cert->serialNumber = object; break; case X509_OBJ_SIG_ALG: - cert->sigAlg = parse_algorithmIdentifier(object, level, NULL); + cert->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL); break; case X509_OBJ_ISSUER: cert->issuer = object; @@ -1972,10 +1916,10 @@ parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert) ) break; case X509_OBJ_NOT_BEFORE: - cert->notBefore = parse_time(object, level); + cert->notBefore = asn1_parse_time(object, level); break; case X509_OBJ_NOT_AFTER: - cert->notAfter = parse_time(object, level); + cert->notAfter = asn1_parse_time(object, level); break; case X509_OBJ_SUBJECT: cert->subject = object; @@ -1985,47 +1929,32 @@ parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert) ) break; case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM: - if (parse_algorithmIdentifier(object, level, NULL) == OID_RSA_ENCRYPTION) + if (asn1_parse_algorithmIdentifier(object, level, NULL) == OID_RSA_ENCRYPTION) { cert->subjectPublicKeyAlgorithm = PUBKEY_ALG_RSA; } else { plog(" unsupported public key algorithm"); - return FALSE; + goto end; } break; case X509_OBJ_SUBJECT_PUBLIC_KEY: - if (ctx.blobs[4].len > 0 && *ctx.blobs[4].ptr == 0x00) + if (object.len > 0 && *object.ptr == 0x00) { /* skip initial bit string octet defining 0 unused bits */ - ctx.blobs[4].ptr++; ctx.blobs[4].len--; + object = chunk_skip(object, 1); + if (!parse_RSA_public_key(object, level, cert)) + { + goto end; + } } else { plog(" invalid RSA public key format"); - return FALSE; + goto end; } break; - case X509_OBJ_RSA_PUBLIC_KEY: - cert->subjectPublicKey = object; - break; - case X509_OBJ_MODULUS: - if (object.len < RSA_MIN_OCTETS + 1) - { - plog(" " RSA_MIN_OCTETS_UGH); - return FALSE; - } - if (object.len > RSA_MAX_OCTETS + (size_t)(*object.ptr == 0x00)) - { - plog(" " RSA_MAX_OCTETS_UGH); - return FALSE; - } - cert->modulus = object; - break; - case X509_OBJ_PUBLIC_EXPONENT: - cert->publicExponent = object; - break; case X509_OBJ_EXTN_ID: extn_oid = asn1_known_oid(object); break; @@ -2039,8 +1968,12 @@ parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert) { switch (extn_oid) { case OID_SUBJECT_KEY_ID: - cert->subjectKeyID = - parse_keyIdentifier(object, level, FALSE); + if (!asn1_parse_simple_object(&object, ASN1_OCTET_STRING, + level, "keyIdentifier")) + { + goto end; + } + cert->subjectKeyID = object; break; case OID_SUBJECT_ALT_NAME: cert->subjectAltName = @@ -2068,10 +2001,10 @@ parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert) case OID_NS_CA_REVOCATION_URL: case OID_NS_CA_POLICY_URL: case OID_NS_COMMENT: - if (!parse_asn1_simple_object(&object, ASN1_IA5STRING + if (!asn1_parse_simple_object(&object, ASN1_IA5STRING , level, oid_names[extn_oid].name)) { - return FALSE; + goto end; } break; default: @@ -2080,7 +2013,7 @@ parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert) } break; case X509_OBJ_ALGORITHM: - cert->algorithm = parse_algorithmIdentifier(object, level, NULL); + cert->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL); break; case X509_OBJ_SIGNATURE: cert->signature = object; @@ -2088,17 +2021,20 @@ parse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert) default: break; } - objectID++; } + success = parser->success(parser); time(&cert->installed); - return TRUE; + +end: + parser->destroy(parser); + return success; } -/* verify the validity of a certificate by +/** + * Verify the validity of a certificate by * checking the notBefore and notAfter dates */ -err_t -check_validity(const x509cert_t *cert, time_t *until) +err_t check_validity(const x509cert_t *cert, time_t *until) { time_t current_time; @@ -2127,11 +2063,10 @@ check_validity(const x509cert_t *cert, time_t *until) } } -/* - * verifies a X.509 certificate +/** + * Verifies a X.509 certificate */ -bool -verify_x509cert(const x509cert_t *cert, bool strict, time_t *until) +bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until) { int pathlen; @@ -2270,12 +2205,11 @@ verify_x509cert(const x509cert_t *cert, bool strict, time_t *until) return FALSE; } -/* - * list all X.509 certs in a chained list +/** + * List all X.509 certs in a chained list */ -void -list_x509cert_chain(const char *caption, x509cert_t* cert, u_char auth_flags - , bool utc) +void list_x509cert_chain(const char *caption, x509cert_t* cert, + u_char auth_flags, bool utc) { bool first = TRUE; time_t now; @@ -2346,11 +2280,10 @@ list_x509cert_chain(const char *caption, x509cert_t* cert, u_char auth_flags } } -/* - * list all X.509 end certificates in a chained list +/** + * List all X.509 end certificates in a chained list */ -void -list_x509_end_certs(bool utc) +void list_x509_end_certs(bool utc) { list_x509cert_chain("End", x509certs, AUTH_NONE, utc); } diff --git a/src/pluto/x509.h b/src/pluto/x509.h index b6a702c6a..104ef6d62 100644 --- a/src/pluto/x509.h +++ b/src/pluto/x509.h @@ -20,6 +20,7 @@ #ifndef _X509_H #define _X509_H +#include "constants.h" #include "pkcs1.h" #include "id.h" diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am index 6681407ca..62146b246 100644 --- a/src/scepclient/Makefile.am +++ b/src/scepclient/Makefile.am @@ -18,15 +18,16 @@ INCLUDES = \ AM_CFLAGS = \ -DIPSEC_CONFDIR=\"${confdir}\" \ -DSTRONGSWAN_CONF=\"${strongswan_conf}\" \ --DDEBUG -DNO_PLUTO +-DDEBUG -DNO_PLUTO \ +-Wformat=0 LIBFREESWANBUILDDIR=$(top_builddir)/src/libfreeswan LIBCRYPTOBUILDDIR=$(top_builddir)/src/libcrypto scepclient_LDADD = \ -asn1.o ca.o crl.o certs.o constants.o defs.o fetch.o id.o keys.o \ -lex.o library.o md2.o md5.o mp_defs.o ocsp.o pem.o pgp.o pkcs1.o \ -pkcs7.o rnd.o sha1.o smartcard.o x509.o \ +ca.o crl.o certs.o constants.o defs.o fetch.o id.o keys.o lex.o library.o \ +md2.o md5.o mp_defs.o ocsp.o pem.o pgp.o pkcs1.o pkcs7.o rnd.o sha1.o \ +smartcard.o x509.o \ $(LIBSTRONGSWANDIR)/libstrongswan-lite.la \ $(LIBFREESWANBUILDDIR)/libfreeswan.a \ $(LIBCRYPTOBUILDDIR)/libcrypto.a \ @@ -51,9 +52,6 @@ endif dist_man_MANS = scepclient.8 -asn1.o : $(PLUTODIR)/asn1.c $(PLUTODIR)/asn1.h - $(COMPILE) $(INCLUDES) -c -o $@ $< - ca.o : $(PLUTODIR)/ca.c $(PLUTODIR)/ca.h $(COMPILE) $(INCLUDES) -c -o $@ $< diff --git a/src/scepclient/pkcs10.c b/src/scepclient/pkcs10.c index d6b53d8d0..6933adaf8 100644 --- a/src/scepclient/pkcs10.c +++ b/src/scepclient/pkcs10.c @@ -26,11 +26,11 @@ #include <arpa/inet.h> #include <freeswan.h> +#include <asn1/asn1.h> #include <asn1/oid.h> #include "../pluto/constants.h" #include "../pluto/defs.h" -#include "../pluto/asn1.h" #include "../pluto/pkcs1.h" #include "../pluto/log.h" #include "../pluto/x509.h" @@ -133,7 +133,7 @@ build_req_info_attributes(pkcs10_t* pkcs10) if (pkcs10->challengePassword.len > 0) { - asn1_t type = is_printablestring(pkcs10->challengePassword) + asn1_t type = asn1_is_printablestring(pkcs10->challengePassword) ? ASN1_PRINTABLESTRING : ASN1_T61STRING; challengePassword = asn1_wrap(ASN1_SEQUENCE, "cm" diff --git a/src/scepclient/rsakey.c b/src/scepclient/rsakey.c index 87ec37cb2..9f40b32a7 100644 --- a/src/scepclient/rsakey.c +++ b/src/scepclient/rsakey.c @@ -36,7 +36,6 @@ #include "../pluto/defs.h" #include "../pluto/mp_defs.h" #include "../pluto/log.h" -#include "../pluto/asn1.h" #include "../pluto/pkcs1.h" #include "rsakey.h" diff --git a/src/scepclient/scep.c b/src/scepclient/scep.c index 1d921ba99..f880fe734 100644 --- a/src/scepclient/scep.c +++ b/src/scepclient/scep.c @@ -24,6 +24,9 @@ #include <stdlib.h> #include <freeswan.h> + +#include <asn1/asn1.h> +#include <asn1/asn1_parser.h> #include <asn1/oid.h> #ifdef LIBCURL @@ -33,7 +36,6 @@ #include "../pluto/constants.h" #include "../pluto/defs.h" #include "../pluto/rnd.h" -#include "../pluto/asn1.h" #include "../pluto/pkcs1.h" #include "../pluto/fetch.h" #include "../pluto/log.h" @@ -62,62 +64,60 @@ static const chunk_t ASN1_transId_oid = static const char *pkiStatus_values[] = { "0", "2", "3" }; static const char *pkiStatus_names[] = { - "SUCCESS", - "FAILURE", - "PENDING", - "UNKNOWN" + "SUCCESS", + "FAILURE", + "PENDING", + "UNKNOWN" }; static const char *msgType_values[] = { "3", "19", "20", "21", "22" }; static const char *msgType_names[] = { - "CertRep", - "PKCSReq", - "GetCertInitial", - "GetCert", - "GetCRL", - "Unknown" + "CertRep", + "PKCSReq", + "GetCertInitial", + "GetCert", + "GetCRL", + "Unknown" }; static const char *failInfo_reasons[] = { - "badAlg - unrecognized or unsupported algorithm identifier", - "badMessageCheck - integrity check failed", - "badRequest - transaction not permitted or supported", - "badTime - Message time field was not sufficiently close to the system time", - "badCertId - No certificate could be identified matching the provided criteria" + "badAlg - unrecognized or unsupported algorithm identifier", + "badMessageCheck - integrity check failed", + "badRequest - transaction not permitted or supported", + "badTime - Message time field was not sufficiently close to the system time", + "badCertId - No certificate could be identified matching the provided criteria" }; const scep_attributes_t empty_scep_attributes = { - SCEP_Unknown_MSG , /* msgType */ - SCEP_UNKNOWN , /* pkiStatus */ - SCEP_unknown_REASON, /* failInfo */ - { NULL, 0 } , /* transID */ - { NULL, 0 } , /* senderNonce */ - { NULL, 0 } , /* recipientNonce */ + SCEP_Unknown_MSG , /* msgType */ + SCEP_UNKNOWN , /* pkiStatus */ + SCEP_unknown_REASON, /* failInfo */ + { NULL, 0 } , /* transID */ + { NULL, 0 } , /* senderNonce */ + { NULL, 0 } , /* recipientNonce */ }; /* ASN.1 definition of the X.501 atttribute type */ static const asn1Object_t attributesObjects[] = { - { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */ - { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */ - { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */ - { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */ - { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */ + { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */ + { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ + { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */ + { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */ + { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; - #define ATTRIBUTE_OBJ_TYPE 2 #define ATTRIBUTE_OBJ_VALUE 4 -#define ATTRIBUTE_OBJ_ROOF 7 -/* - * extract and store an attribute +/** + * Extract and store an attribute */ -static bool -extract_attribute(int oid, chunk_t object, u_int level -, scep_attributes_t *attrs) +static bool extract_attribute(int oid, chunk_t object, u_int level, + scep_attributes_t *attrs) { asn1_t type = ASN1_EOC; const char *name = "none"; @@ -167,7 +167,7 @@ extract_attribute(int oid, chunk_t object, u_int level if (type == ASN1_EOC) return TRUE; - if (!parse_asn1_simple_object(&object, type, level+1, name)) + if (!asn1_parse_simple_object(&object, type, level+1, name)) return FALSE; switch (oid) @@ -227,41 +227,41 @@ extract_attribute(int oid, chunk_t object, u_int level return TRUE; } -/* - * parse X.501 attributes +/** + * Parse X.501 attributes */ -bool -parse_attributes(chunk_t blob, scep_attributes_t *attrs) +bool parse_attributes(chunk_t blob, scep_attributes_t *attrs) { - asn1_ctx_t ctx; + asn1_parser_t *parser; chunk_t object; - u_int level; int oid = OID_UNKNOWN; - int objectID = 0; - - asn1_init(&ctx, blob, 0, FALSE, DBG_RAW); + int objectID; + bool success = FALSE; + parser = asn1_parser_create(attributesObjects, blob); DBG(DBG_CONTROL | DBG_PARSING, DBG_log("parsing attributes") ) - while (objectID < ATTRIBUTE_OBJ_ROOF) + + while (parser->iterate(parser, &objectID, &object)) { - if (!extract_object(attributesObjects, &objectID - , &object, &level, &ctx)) - return FALSE; - switch (objectID) { case ATTRIBUTE_OBJ_TYPE: oid = asn1_known_oid(object); break; case ATTRIBUTE_OBJ_VALUE: - if (!extract_attribute(oid, object, level, attrs)) - return FALSE; + if (!extract_attribute(oid, object, parser->get_level(parser), attrs)) + { + goto end; + } } - objectID++; } - return TRUE; + success = parser->success(parser); + +end: + parser->destroy(parser); + return success; } /* generates a unique fingerprint of the pkcs10 request diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c index eb1c2af42..d8d44fdbc 100644 --- a/src/scepclient/scepclient.c +++ b/src/scepclient/scepclient.c @@ -38,13 +38,13 @@ #include <freeswan.h> #include <library.h> #include <debug.h> +#include <asn1/asn1.h> #include <asn1/oid.h> #include <utils/optionsfrom.h> #include "../pluto/constants.h" #include "../pluto/defs.h" #include "../pluto/log.h" -#include "../pluto/asn1.h" #include "../pluto/pkcs1.h" #include "../pluto/pkcs7.h" #include "../pluto/certs.h" @@ -604,7 +604,7 @@ int main(int argc, char **argv) usage("date format must be YYMMDDHHMMSSZ"); { chunk_t date = { optarg, 13 }; - notBefore = asn1totime(&date, ASN1_UTCTIME); + notBefore = asn1_to_time(&date, ASN1_UTCTIME); } continue; @@ -613,7 +613,7 @@ int main(int argc, char **argv) usage("date format must be YYMMDDHHMMSSZ"); { chunk_t date = { optarg, 13 }; - notAfter = asn1totime(&date, ASN1_UTCTIME); + notAfter = asn1_to_time(&date, ASN1_UTCTIME); } continue; @@ -800,7 +800,7 @@ int main(int argc, char **argv) if (filetype_in & PKCS1) /* load an RSA key pair from file */ { prompt_pass_t pass = { "", FALSE, STDIN_FILENO }; - const char *path = concatenate_paths(PRIVATE_KEY_PATH, file_in_pkcs1); + char *path = concatenate_paths(PRIVATE_KEY_PATH, file_in_pkcs1); ugh = load_rsa_private_key(path, &pass, private_key); } @@ -877,9 +877,9 @@ int main(int argc, char **argv) */ if (filetype_out & PKCS10) { - const char *path = concatenate_paths(REQ_PATH, file_out_pkcs10); + char *path = concatenate_paths(REQ_PATH, file_out_pkcs10); - if (!chunk_write(pkcs10->request,path, "pkcs10", 0022, force)) + if (!chunk_write(pkcs10->request, path, "pkcs10", 0022, force)) exit_scepclient("could not write pkcs10 file '%s'", path); filetype_out &= ~PKCS10; /* delete PKCS10 flag */ @@ -895,7 +895,7 @@ int main(int argc, char **argv) */ if (filetype_out & PKCS1) { - const char *path = concatenate_paths(PRIVATE_KEY_PATH, file_out_pkcs1); + char *path = concatenate_paths(PRIVATE_KEY_PATH, file_out_pkcs1); DBG(DBG_CONTROL, DBG_log("building pkcs1 object:") @@ -938,7 +938,7 @@ int main(int argc, char **argv) */ if (filetype_out & CERT_SELF) { - const char *path = concatenate_paths(HOST_CERT_PATH, file_out_cert_self); + char *path = concatenate_paths(HOST_CERT_PATH, file_out_cert_self); if (!chunk_write(x509_signer->certificate, path, "self-signed cert", 0022, force)) exit_scepclient("could not write self-signed cert file '%s'", path); @@ -955,7 +955,7 @@ int main(int argc, char **argv) * load ca encryption certificate */ { - const char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_enc); + char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_enc); cert_t cert; if (!load_cert(path, "encryption cacert", &cert)) @@ -994,7 +994,7 @@ int main(int argc, char **argv) */ if (filetype_out & PKCS7) { - const char *path = concatenate_paths(REQ_PATH, file_out_pkcs7); + char *path = concatenate_paths(REQ_PATH, file_out_pkcs7); if (!chunk_write(pkcs7, path, "pkcs7 encrypted request", 0022, force)) exit_scepclient("could not write pkcs7 file '%s'", path); @@ -1012,7 +1012,7 @@ int main(int argc, char **argv) */ if (filetype_out & CERT) { - const char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_sig); + char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_sig); cert_t cert; time_t poll_start; @@ -1094,7 +1094,7 @@ int main(int argc, char **argv) envelopedData = data.content; if (data.type != OID_PKCS7_DATA - || !parse_asn1_simple_object(&envelopedData, ASN1_OCTET_STRING, 0, "data")) + || !asn1_parse_simple_object(&envelopedData, ASN1_OCTET_STRING, 0, "data")) { exit_scepclient("contentInfo is not of type 'data'"); } |