scepclient and pluto use asn1 from libstrongswan

This commit is contained in:
Andreas Steffen
2009-04-20 20:53:38 +00:00
parent 09f706ec3e
commit 08b2d288a1
38 changed files with 1518 additions and 2565 deletions
+2 -1
View File
@@ -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
+1 -1
View File
@@ -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 = \
+2 -1
View File
@@ -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 \
+4 -1
View File
@@ -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
+1 -1
View File
@@ -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 = \
+3 -1
View File
@@ -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
+6 -2
View File
@@ -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
+1 -1
View File
@@ -21,7 +21,7 @@
#include <string.h>
#include <time.h>
#include <library.h>
#include <utils.h>
#include <debug.h>
#include "oid.h"
+2 -1
View File
@@ -27,7 +27,8 @@
#include <stdarg.h>
#include <library.h>
#include <utils.h>
#include <chunk.h>
/**
* Definition of some primitive ASN1 types
+1 -1
View File
@@ -21,7 +21,7 @@
#include <string.h>
#include <time.h>
#include <library.h>
#include <utils.h>
#include <debug.h>
#include "asn1.h"
+3 -1
View File
@@ -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
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -1,7 +1,7 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
AM_CFLAGS = -rdynamic -Wformat=0
plugin_LTLIBRARIES = libstrongswan-x509.la
+2 -1
View File
@@ -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
+2 -2
View File
@@ -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 \
+192 -213
View File
@@ -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);
parser = asn1_parser_create(acObjects, blob);
while (objectID < AC_OBJ_ROOF) {
if (!extract_object(acObjects, &objectID, &object, &level, &ctx))
return FALSE;
/* 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;
-825
View File
@@ -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;
}
-142
View File
@@ -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 */
+25 -31
View File
@@ -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)
{
+5 -6
View File
@@ -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);
+1 -2
View File
@@ -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;
+99 -102
View File
@@ -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
+1 -2
View File
@@ -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;
+1 -1
View File
@@ -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);
+2 -1
View File
@@ -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"
-1
View File
@@ -58,7 +58,6 @@
#include "whack.h"
#include "fetch.h"
#include "pkcs7.h"
#include "asn1.h"
#include "sha1.h"
#include "md5.h"
+17
View File
@@ -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);
}
+2 -1
View File
@@ -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) { \
+285 -295
View File
@@ -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_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
/**
* 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);
}
}
+108 -126
View File
@@ -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 */
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 */
};
#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
/**
* ASN.1 definition of a PKCS#1 RSA private key
*/
void
form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize)
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, "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
/**
* 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)
{
/* 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);
}
+168 -151
View File
@@ -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;
+504 -571
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -20,6 +20,7 @@
#ifndef _X509_H
#define _X509_H
#include "constants.h"
#include "pkcs1.h"
#include "id.h"
+5 -7
View File
@@ -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 $@ $<
+2 -2
View File
@@ -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"
-1
View File
@@ -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"
+55 -55
View File
@@ -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
+12 -12
View File
@@ -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'");
}