summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/openssl
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/openssl')
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.am10
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.in84
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_crl.c4
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_pkcs12.c266
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_pkcs12.h37
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.c104
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rng.c15
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_x509.c194
8 files changed, 617 insertions, 97 deletions
diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am
index 0ca27983f..cbfd69b71 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.am
+++ b/src/libstrongswan/plugins/openssl/Makefile.am
@@ -1,7 +1,9 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -DFIPS_MODE=${fips_mode}
-INCLUDES = -I$(top_srcdir)/src/libstrongswan
-
-AM_CFLAGS = -rdynamic -DFIPS_MODE=${fips_mode}
+AM_CFLAGS = \
+ -rdynamic
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-openssl.la
@@ -24,10 +26,10 @@ libstrongswan_openssl_la_SOURCES = \
openssl_x509.c openssl_x509.h \
openssl_crl.c openssl_crl.h \
openssl_pkcs7.c openssl_pkcs7.h \
+ openssl_pkcs12.c openssl_pkcs12.h \
openssl_rng.c openssl_rng.h \
openssl_hmac.c openssl_hmac.h \
openssl_gcm.c openssl_gcm.h
libstrongswan_openssl_la_LDFLAGS = -module -avoid-version
libstrongswan_openssl_la_LIBADD = -lcrypto
-
diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in
index ba45e4bbc..ad5aa6057 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.in
+++ b/src/libstrongswan/plugins/openssl/Makefile.in
@@ -62,7 +62,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
$(top_srcdir)/m4/macros/with.m4 \
$(top_srcdir)/m4/macros/enable-disable.m4 \
$(top_srcdir)/m4/macros/add-plugin.m4 \
- $(top_srcdir)/configure.in
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -105,12 +105,17 @@ am_libstrongswan_openssl_la_OBJECTS = openssl_plugin.lo \
openssl_rsa_private_key.lo openssl_rsa_public_key.lo \
openssl_ec_diffie_hellman.lo openssl_ec_private_key.lo \
openssl_ec_public_key.lo openssl_x509.lo openssl_crl.lo \
- openssl_pkcs7.lo openssl_rng.lo openssl_hmac.lo openssl_gcm.lo
+ openssl_pkcs7.lo openssl_pkcs12.lo openssl_rng.lo \
+ openssl_hmac.lo openssl_gcm.lo
libstrongswan_openssl_la_OBJECTS = \
$(am_libstrongswan_openssl_la_OBJECTS)
-libstrongswan_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(libstrongswan_openssl_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libstrongswan_openssl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_openssl_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
@MONOLITHIC_FALSE@am_libstrongswan_openssl_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
@MONOLITHIC_TRUE@am_libstrongswan_openssl_la_rpath =
@@ -120,13 +125,26 @@ am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(libstrongswan_openssl_la_SOURCES)
DIST_SOURCES = $(libstrongswan_openssl_la_SOURCES)
am__can_run_installinfo = \
@@ -140,6 +158,7 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -152,6 +171,8 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CHECK_CFLAGS = @CHECK_CFLAGS@
CHECK_LIBS = @CHECK_LIBS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -167,6 +188,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
GREP = @GREP@
@@ -175,6 +197,7 @@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
@@ -221,6 +244,7 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SOCKLIB = @SOCKLIB@
STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
@@ -249,6 +273,7 @@ charon_natt_port = @charon_natt_port@
charon_plugins = @charon_plugins@
charon_udp_port = @charon_udp_port@
clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
@@ -326,8 +351,13 @@ top_srcdir = @top_srcdir@
urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
-INCLUDES = -I$(top_srcdir)/src/libstrongswan
-AM_CFLAGS = -rdynamic -DFIPS_MODE=${fips_mode}
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -DFIPS_MODE=${fips_mode}
+
+AM_CFLAGS = \
+ -rdynamic
+
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-openssl.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-openssl.la
libstrongswan_openssl_la_SOURCES = \
@@ -345,6 +375,7 @@ libstrongswan_openssl_la_SOURCES = \
openssl_x509.c openssl_x509.h \
openssl_crl.c openssl_crl.h \
openssl_pkcs7.c openssl_pkcs7.h \
+ openssl_pkcs12.c openssl_pkcs12.h \
openssl_rng.c openssl_rng.h \
openssl_hmac.c openssl_hmac.h \
openssl_gcm.c openssl_gcm.h
@@ -427,7 +458,7 @@ clean-pluginLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libstrongswan-openssl.la: $(libstrongswan_openssl_la_OBJECTS) $(libstrongswan_openssl_la_DEPENDENCIES) $(EXTRA_libstrongswan_openssl_la_DEPENDENCIES)
- $(libstrongswan_openssl_la_LINK) $(am_libstrongswan_openssl_la_rpath) $(libstrongswan_openssl_la_OBJECTS) $(libstrongswan_openssl_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(libstrongswan_openssl_la_LINK) $(am_libstrongswan_openssl_la_rpath) $(libstrongswan_openssl_la_OBJECTS) $(libstrongswan_openssl_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -444,6 +475,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_gcm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_hasher.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_hmac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_pkcs12.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_pkcs7.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_plugin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rng.Plo@am__quote@
@@ -454,25 +486,25 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_x509.Plo@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c
index d4f36f58b..18aa5ceca 100644
--- a/src/libstrongswan/plugins/openssl/openssl_crl.c
+++ b/src/libstrongswan/plugins/openssl/openssl_crl.c
@@ -464,6 +464,10 @@ static bool parse_extensions(private_openssl_crl_t *this)
case NID_crl_number:
ok = parse_crlNumber_ext(this, ext);
break;
+ case NID_issuing_distribution_point:
+ /* TODO support of IssuingDistributionPoints */
+ ok = TRUE;
+ break;
default:
ok = X509_EXTENSION_get_critical(ext) == 0 ||
!lib->settings->get_bool(lib->settings,
diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs12.c b/src/libstrongswan/plugins/openssl/openssl_pkcs12.c
new file mode 100644
index 000000000..d16b2cc05
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_pkcs12.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * 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
+ * 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.
+ */
+
+#define _GNU_SOURCE /* for asprintf() */
+#include <stdio.h>
+#include <openssl/pkcs12.h>
+
+#include "openssl_pkcs12.h"
+#include "openssl_util.h"
+
+#include <library.h>
+#include <credentials/sets/mem_cred.h>
+
+typedef struct private_pkcs12_t private_pkcs12_t;
+
+/**
+ * Private data of a pkcs12_t object.
+ */
+struct private_pkcs12_t {
+
+ /**
+ * Public pkcs12_t interface.
+ */
+ pkcs12_t public;
+
+ /**
+ * OpenSSL PKCS#12 structure
+ */
+ PKCS12 *p12;
+
+ /**
+ * Credentials contained in container
+ */
+ mem_cred_t *creds;
+};
+
+/**
+ * Decode certificate and add it to our credential set
+ */
+static bool add_cert(private_pkcs12_t *this, X509 *x509)
+{
+ certificate_t *cert = NULL;
+ chunk_t encoding;
+
+ if (!x509)
+ { /* no certificate is ok */
+ return TRUE;
+ }
+ encoding = openssl_i2chunk(X509, x509);
+ if (encoding.ptr)
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, encoding,
+ BUILD_END);
+ if (cert)
+ {
+ this->creds->add_cert(this->creds, FALSE, cert);
+ }
+ }
+ chunk_free(&encoding);
+ X509_free(x509);
+ return cert != NULL;
+}
+
+/**
+ * Add CA certificates to our credential set
+ */
+static bool add_cas(private_pkcs12_t *this, STACK_OF(X509) *cas)
+{
+ bool success = TRUE;
+ int i;
+
+ if (!cas)
+ { /* no CAs is ok */
+ return TRUE;
+ }
+ for (i = 0; i < sk_X509_num(cas); i++)
+ {
+ if (!add_cert(this, sk_X509_value(cas, i)))
+ { /* continue to free all X509 objects */
+ success = FALSE;
+ }
+ }
+ sk_X509_free(cas);
+ return success;
+}
+
+/**
+ * Decode private key and add it to our credential set
+ */
+static bool add_key(private_pkcs12_t *this, EVP_PKEY *private)
+{
+ private_key_t *key = NULL;
+ chunk_t encoding;
+ key_type_t type;
+
+ if (!private)
+ { /* no private key is ok */
+ return TRUE;
+ }
+ switch (EVP_PKEY_type(private->type))
+ {
+ case EVP_PKEY_RSA:
+ type = KEY_RSA;
+ break;
+ case EVP_PKEY_EC:
+ type = KEY_ECDSA;
+ break;
+ default:
+ EVP_PKEY_free(private);
+ return FALSE;
+ }
+ encoding = openssl_i2chunk(PrivateKey, private);
+ if (encoding.ptr)
+ {
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+ BUILD_BLOB_ASN1_DER, encoding,
+ BUILD_END);
+ if (key)
+ {
+ this->creds->add_key(this->creds, key);
+ }
+ }
+ chunk_clear(&encoding);
+ EVP_PKEY_free(private);
+ return key != NULL;
+}
+
+/**
+ * Decrypt PKCS#12 file and unpack credentials
+ */
+static bool decrypt_and_unpack(private_pkcs12_t *this)
+{
+ enumerator_t *enumerator;
+ shared_key_t *shared;
+ STACK_OF(X509) *cas = NULL;
+ EVP_PKEY *private;
+ X509 *cert;
+ chunk_t key;
+ char *password;
+ bool success = FALSE;
+
+ enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
+ SHARED_PRIVATE_KEY_PASS, NULL, NULL);
+ while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
+ {
+ key = shared->get_key(shared);
+ if (!key.ptr || asprintf(&password, "%.*s", (int)key.len, key.ptr) < 0)
+ {
+ password = NULL;
+ }
+ if (PKCS12_parse(this->p12, password, &private, &cert, &cas))
+ {
+ success = add_key(this, private);
+ success &= add_cert(this, cert);
+ success &= add_cas(this, cas);
+ free(password);
+ break;
+ }
+ free(password);
+ }
+ enumerator->destroy(enumerator);
+ return success;
+}
+
+METHOD(container_t, get_type, container_type_t,
+ private_pkcs12_t *this)
+{
+ return CONTAINER_PKCS12;
+}
+
+METHOD(pkcs12_t, create_cert_enumerator, enumerator_t*,
+ private_pkcs12_t *this)
+{
+ return this->creds->set.create_cert_enumerator(&this->creds->set, CERT_ANY,
+ KEY_ANY, NULL, FALSE);
+}
+
+METHOD(pkcs12_t, create_key_enumerator, enumerator_t*,
+ private_pkcs12_t *this)
+{
+ return this->creds->set.create_private_enumerator(&this->creds->set,
+ KEY_ANY, NULL);
+}
+
+METHOD(container_t, destroy, void,
+ private_pkcs12_t *this)
+{
+ if (this->p12)
+ {
+ PKCS12_free(this->p12);
+ }
+ this->creds->destroy(this->creds);
+ free(this);
+}
+
+/**
+ * Parse a PKCS#12 container
+ */
+static pkcs12_t *parse(chunk_t blob)
+{
+ private_pkcs12_t *this;
+ BIO *bio;
+
+ INIT(this,
+ .public = {
+ .container = {
+ .get_type = _get_type,
+ .create_signature_enumerator = (void*)enumerator_create_empty,
+ .get_data = (void*)return_false,
+ .get_encoding = (void*)return_false,
+ .destroy = _destroy,
+ },
+ .create_cert_enumerator = _create_cert_enumerator,
+ .create_key_enumerator = _create_key_enumerator,
+ },
+ .creds = mem_cred_create(),
+ );
+
+ bio = BIO_new_mem_buf(blob.ptr, blob.len);
+ this->p12 = d2i_PKCS12_bio(bio, NULL);
+ BIO_free(bio);
+
+ if (!this->p12 || !decrypt_and_unpack(this))
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
+
+/*
+ * Defined in header
+ */
+pkcs12_t *openssl_pkcs12_load(container_type_t type, va_list args)
+{
+ chunk_t blob = chunk_empty;
+
+ while (TRUE)
+ {
+ switch (va_arg(args, builder_part_t))
+ {
+ case BUILD_BLOB_ASN1_DER:
+ blob = va_arg(args, chunk_t);
+ continue;
+ case BUILD_END:
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ }
+ return blob.len ? parse(blob) : NULL;
+}
diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs12.h b/src/libstrongswan/plugins/openssl/openssl_pkcs12.h
new file mode 100644
index 000000000..5c3e5933d
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_pkcs12.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * 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
+ * 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.
+ */
+
+/**
+ * @defgroup openssl_pkcs12 openssl_pkcs12
+ * @{ @ingroup openssl_p
+ */
+
+#ifndef OPENSSL_PKCS12_H_
+#define OPENSSL_PKCS12_H_
+
+#include <credentials/containers/pkcs12.h>
+
+/**
+ * Load a PKCS#12 container.
+ *
+ * The argument list must contain a single BUILD_BLOB_ASN1_DER argument.
+ *
+ * @param type type of the container, CONTAINER_PKCS12
+ * @param args builder_part_t argument list
+ * @return container, NULL on failure
+ */
+pkcs12_t *openssl_pkcs12_load(container_type_t type, va_list args);
+
+#endif /** OPENSSL_PKCS12_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index ce6610ad6..fb34a6858 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2013 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -14,6 +14,7 @@
* for more details.
*/
+#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/conf.h>
#include <openssl/rand.h>
@@ -28,6 +29,7 @@
#include <utils/debug.h>
#include <threading/thread.h>
#include <threading/mutex.h>
+#include <threading/thread_value.h>
#include "openssl_util.h"
#include "openssl_crypter.h"
#include "openssl_hasher.h"
@@ -41,10 +43,15 @@
#include "openssl_x509.h"
#include "openssl_crl.h"
#include "openssl_pkcs7.h"
+#include "openssl_pkcs12.h"
#include "openssl_rng.h"
#include "openssl_hmac.h"
#include "openssl_gcm.h"
+#ifndef FIPS_MODE
+#define FIPS_MODE 0
+#endif
+
typedef struct private_openssl_plugin_t private_openssl_plugin_t;
/**
@@ -127,14 +134,51 @@ static void destroy_function(struct CRYPTO_dynlock_value *lock,
}
/**
+ * Thread-local value used to cleanup thread-specific error buffers
+ */
+static thread_value_t *cleanup;
+
+/**
+ * Called when a thread is destroyed. Avoid recursion by setting the thread id
+ * explicitly.
+ */
+static void cleanup_thread(void *arg)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ CRYPTO_THREADID tid;
+
+ CRYPTO_THREADID_set_numeric(&tid, (u_long)(uintptr_t)arg);
+ ERR_remove_thread_state(&tid);
+#else
+ ERR_remove_state((u_long)(uintptr_t)arg);
+#endif
+}
+
+/**
* Thread-ID callback function
*/
-static unsigned long id_function(void)
+static u_long id_function(void)
{
+ u_long id;
+
/* ensure the thread ID is never zero, otherwise OpenSSL might try to
* acquire locks recursively */
- return 1 + (unsigned long)thread_current_id();
+ id = 1 + (u_long)thread_current_id();
+
+ /* cleanup a thread's state later if OpenSSL interacted with it */
+ cleanup->set(cleanup, (void*)(uintptr_t)id);
+ return id;
+}
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+/**
+ * Callback for thread ID
+ */
+static void threadid_function(CRYPTO_THREADID *threadid)
+{
+ CRYPTO_THREADID_set_numeric(threadid, id_function());
}
+#endif /* OPENSSL_VERSION_NUMBER */
/**
* initialize OpenSSL for multi-threaded use
@@ -143,7 +187,14 @@ static void threading_init()
{
int i, num_locks;
+ cleanup = thread_value_create(cleanup_thread);
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ CRYPTO_THREADID_set_callback(threadid_function);
+#else
CRYPTO_set_id_callback(id_function);
+#endif
+
CRYPTO_set_locking_callback(locking_function);
CRYPTO_set_dynlock_create_callback(create_function);
@@ -159,6 +210,24 @@ static void threading_init()
}
/**
+ * cleanup OpenSSL threading locks
+ */
+static void threading_cleanup()
+{
+ int i, num_locks;
+
+ num_locks = CRYPTO_num_locks();
+ for (i = 0; i < num_locks; i++)
+ {
+ mutex[i]->destroy(mutex[i]);
+ }
+ free(mutex);
+ mutex = NULL;
+
+ cleanup->destroy(cleanup);
+}
+
+/**
* Seed the OpenSSL RNG, if required
*/
static bool seed_rng()
@@ -187,22 +256,6 @@ static bool seed_rng()
return TRUE;
}
-/**
- * cleanup OpenSSL threading locks
- */
-static void threading_cleanup()
-{
- int i, num_locks;
-
- num_locks = CRYPTO_num_locks();
- for (i = 0; i < num_locks; i++)
- {
- mutex[i]->destroy(mutex[i]);
- }
- free(mutex);
- mutex = NULL;
-}
-
METHOD(plugin_t, get_name, char*,
private_openssl_plugin_t *this)
{
@@ -303,6 +356,7 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_192),
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_384),
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256),
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_512),
#endif
#endif /* OPENSSL_NO_HMAC */
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL
@@ -388,6 +442,8 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(CONTAINER_DECODE, CONTAINER_PKCS7),
#endif /* OPENSSL_NO_CMS */
#endif /* OPENSSL_VERSION_NUMBER */
+ PLUGIN_REGISTER(CONTAINER_DECODE, openssl_pkcs12_load, TRUE),
+ PLUGIN_PROVIDE(CONTAINER_DECODE, CONTAINER_PKCS12),
#ifndef OPENSSL_NO_ECDH
/* EC DH groups */
PLUGIN_REGISTER(DH, openssl_ec_diffie_hellman_create),
@@ -440,13 +496,15 @@ METHOD(plugin_t, get_features, int,
METHOD(plugin_t, destroy, void,
private_openssl_plugin_t *this)
{
+ CONF_modules_free();
+ OBJ_cleanup();
+ EVP_cleanup();
#ifndef OPENSSL_NO_ENGINE
ENGINE_cleanup();
#endif /* OPENSSL_NO_ENGINE */
- EVP_cleanup();
- CONF_modules_free();
-
+ CRYPTO_cleanup_all_ex_data();
threading_cleanup();
+ ERR_free_strings();
free(this);
}
@@ -470,9 +528,9 @@ plugin_t *openssl_plugin_create()
DBG1(DBG_LIB, "openssl FIPS mode(%d) - %sabled ",fips_mode,
fips_mode ? "en" : "dis");
#else
- DBG1(DBG_LIB, "openssl FIPS mode(%d) unavailable", fips_mode);
if (fips_mode)
{
+ DBG1(DBG_LIB, "openssl FIPS mode(%d) unavailable", fips_mode);
return NULL;
}
#endif
diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.c b/src/libstrongswan/plugins/openssl/openssl_rng.c
index 10db6293a..815cf4f0c 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rng.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rng.c
@@ -47,17 +47,14 @@ struct private_openssl_rng_t {
METHOD(rng_t, get_bytes, bool,
private_openssl_rng_t *this, size_t bytes, u_int8_t *buffer)
{
- u_int32_t ret;
-
- if (this->quality == RNG_STRONG)
- {
- ret = RAND_bytes((char*)buffer, bytes);
- }
- else
+ if (this->quality == RNG_WEAK)
{
- ret = RAND_pseudo_bytes((char*)buffer, bytes);
+ /* RAND_pseudo_bytes() returns 1 if returned bytes are strong,
+ * 0 if of not. Both is acceptable for RNG_WEAK. */
+ return RAND_pseudo_bytes((char*)buffer, bytes) != -1;
}
- return ret == 1;
+ /* A 0 return value is a failure for RAND_bytes() */
+ return RAND_bytes((char*)buffer, bytes) == 1;
}
METHOD(rng_t, allocate_bytes, bool,
diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c
index 676b97f7a..24b12d50c 100644
--- a/src/libstrongswan/plugins/openssl/openssl_x509.c
+++ b/src/libstrongswan/plugins/openssl/openssl_x509.c
@@ -17,6 +17,9 @@
*/
/*
+ * Copyright (C) 2013 Michael Rossberg
+ * Copyright (C) 2013 Technische Universität Ilmenau
+ *
* Copyright (C) 2010 secunet Security Networks AG
* Copyright (C) 2010 Thomas Egerer
*
@@ -50,7 +53,12 @@
#include <utils/debug.h>
#include <asn1/oid.h>
#include <collections/linked_list.h>
+#include <selectors/traffic_selector.h>
+/* IP Addr block extension support was introduced with 0.9.8e */
+#if OPENSSL_VERSION_NUMBER < 0x0090805fL
+#define OPENSSL_NO_RFC3779
+#endif
typedef struct private_openssl_x509_t private_openssl_x509_t;
@@ -150,6 +158,12 @@ struct private_openssl_x509_t {
linked_list_t *ocsp_uris;
/**
+ * List of ipAddrBlocks as traffic_selector_t
+ */
+ linked_list_t *ipAddrBlocks;
+
+
+ /**
* References to this cert
*/
refcount_t ref;
@@ -283,6 +297,12 @@ METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
return this->ocsp_uris->create_enumerator(this->ocsp_uris);
}
+METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
+ private_openssl_x509_t *this)
+{
+ return this->ipAddrBlocks->create_enumerator(this->ipAddrBlocks);
+}
+
METHOD(certificate_t, get_type, certificate_type_t,
private_openssl_x509_t *this)
{
@@ -506,6 +526,8 @@ METHOD(certificate_t, destroy, void,
offsetof(identification_t, destroy));
this->crl_uris->destroy_function(this->crl_uris, (void*)crl_uri_destroy);
this->ocsp_uris->destroy_function(this->ocsp_uris, free);
+ this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks,
+ offsetof(traffic_selector_t, destroy));
free(this);
}
}
@@ -542,7 +564,7 @@ static private_openssl_x509_t *create_empty()
.create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
.create_crl_uri_enumerator = _create_crl_uri_enumerator,
.create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
- .create_ipAddrBlock_enumerator = (void*)enumerator_create_empty,
+ .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
.create_name_constraint_enumerator = (void*)enumerator_create_empty,
.create_cert_policy_enumerator = (void*)enumerator_create_empty,
.create_policy_mapping_enumerator = (void*)enumerator_create_empty,
@@ -552,6 +574,7 @@ static private_openssl_x509_t *create_empty()
.issuerAltNames = linked_list_create(),
.crl_uris = linked_list_create(),
.ocsp_uris = linked_list_create(),
+ .ipAddrBlocks = linked_list_create(),
.pathlen = X509_NO_CONSTRAINT,
.ref = 1,
);
@@ -656,6 +679,41 @@ static bool parse_keyUsage_ext(private_openssl_x509_t *this,
}
/**
+ * Parse ExtendedKeyUsage
+ */
+static bool parse_extKeyUsage_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ EXTENDED_KEY_USAGE *usage;
+ int i;
+
+ usage = X509V3_EXT_d2i(ext);
+ if (usage)
+ {
+ for (i = 0; i < sk_ASN1_OBJECT_num(usage); i++)
+ {
+ switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage, i)))
+ {
+ case NID_server_auth:
+ this->flags |= X509_SERVER_AUTH;
+ break;
+ case NID_client_auth:
+ this->flags |= X509_CLIENT_AUTH;
+ break;
+ case NID_OCSP_sign:
+ this->flags |= X509_OCSP_SIGNER;
+ break;
+ default:
+ break;
+ }
+ }
+ sk_ASN1_OBJECT_pop_free(usage, ASN1_OBJECT_free);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
* Parse CRL distribution points
*/
static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this,
@@ -772,6 +830,92 @@ static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
return TRUE;
}
+#ifndef OPENSSL_NO_RFC3779
+
+/**
+ * Parse a single block of ipAddrBlock extension
+ */
+static void parse_ipAddrBlock_ext_fam(private_openssl_x509_t *this,
+ IPAddressFamily *fam)
+{
+ const IPAddressOrRanges *list;
+ IPAddressOrRange *aor;
+ traffic_selector_t *ts;
+ ts_type_t type;
+ chunk_t from, to;
+ int i, afi;
+
+ if (fam->ipAddressChoice->type != IPAddressChoice_addressesOrRanges)
+ {
+ return;
+ }
+
+ afi = v3_addr_get_afi(fam);
+ switch (afi)
+ {
+ case IANA_AFI_IPV4:
+ from = chunk_alloca(4);
+ to = chunk_alloca(4);
+ type = TS_IPV4_ADDR_RANGE;
+ break;
+ case IANA_AFI_IPV6:
+ from = chunk_alloca(16);
+ to = chunk_alloca(16);
+ type = TS_IPV6_ADDR_RANGE;
+ break;
+ default:
+ return;
+ }
+
+ list = fam->ipAddressChoice->u.addressesOrRanges;
+ for (i = 0; i < sk_IPAddressOrRange_num(list); i++)
+ {
+ aor = sk_IPAddressOrRange_value(list, i);
+ if (v3_addr_get_range(aor, afi, from.ptr, to.ptr, from.len) > 0)
+ {
+ ts = traffic_selector_create_from_bytes(0, type, from, 0, to, 65535);
+ if (ts)
+ {
+ this->ipAddrBlocks->insert_last(this->ipAddrBlocks, ts);
+ }
+ }
+ }
+}
+
+/**
+ * Parse ipAddrBlock extension
+ */
+static bool parse_ipAddrBlock_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ STACK_OF(IPAddressFamily) *blocks;
+ IPAddressFamily *fam;
+
+ blocks = (STACK_OF(IPAddressFamily)*)X509V3_EXT_d2i(ext);
+ if (!blocks)
+ {
+ return FALSE;
+ }
+
+ if (!v3_addr_is_canonical(blocks))
+ {
+ sk_IPAddressFamily_free(blocks);
+ return FALSE;
+ }
+
+ while (sk_IPAddressFamily_num(blocks) > 0)
+ {
+ fam = sk_IPAddressFamily_pop(blocks);
+ parse_ipAddrBlock_ext_fam(this, fam);
+ IPAddressFamily_free(fam);
+ }
+ sk_IPAddressFamily_free(blocks);
+
+ this->flags |= X509_IP_ADDR_BLOCKS;
+ return TRUE;
+}
+#endif /* !OPENSSL_NO_RFC3779 */
+
/**
* Parse authorityKeyIdentifier extension
*/
@@ -854,16 +998,29 @@ static bool parse_extensions(private_openssl_x509_t *this)
case NID_key_usage:
ok = parse_keyUsage_ext(this, ext);
break;
+ case NID_ext_key_usage:
+ ok = parse_extKeyUsage_ext(this, ext);
+ break;
case NID_crl_distribution_points:
ok = parse_crlDistributionPoints_ext(this, ext);
break;
+#ifndef OPENSSL_NO_RFC3779
+ case NID_sbgp_ipAddrBlock:
+ ok = parse_ipAddrBlock_ext(this, ext);
+ break;
+#endif /* !OPENSSL_NO_RFC3779 */
default:
ok = X509_EXTENSION_get_critical(ext) == 0 ||
!lib->settings->get_bool(lib->settings,
"libstrongswan.x509.enforce_critical", TRUE);
if (!ok)
{
- DBG1(DBG_LIB, "found unsupported critical X.509 extension");
+ char buf[80] = "";
+
+ OBJ_obj2txt(buf, sizeof(buf),
+ X509_EXTENSION_get_object(ext), 0);
+ DBG1(DBG_LIB, "found unsupported critical X.509 "
+ "extension: %s", buf);
}
break;
}
@@ -877,38 +1034,6 @@ static bool parse_extensions(private_openssl_x509_t *this)
}
/**
- * Parse ExtendedKeyUsage
- */
-static void parse_extKeyUsage(private_openssl_x509_t *this)
-{
- EXTENDED_KEY_USAGE *usage;
- int i;
-
- usage = X509_get_ext_d2i(this->x509, NID_ext_key_usage, NULL, NULL);
- if (usage)
- {
- for (i = 0; i < sk_ASN1_OBJECT_num(usage); i++)
- {
- switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage, i)))
- {
- case NID_server_auth:
- this->flags |= X509_SERVER_AUTH;
- break;
- case NID_client_auth:
- this->flags |= X509_CLIENT_AUTH;
- break;
- case NID_OCSP_sign:
- this->flags |= X509_OCSP_SIGNER;
- break;
- default:
- break;
- }
- }
- sk_ASN1_OBJECT_pop_free(usage, ASN1_OBJECT_free);
- }
-}
-
-/**
* Parse a DER encoded x509 certificate
*/
static bool parse_certificate(private_openssl_x509_t *this)
@@ -974,7 +1099,6 @@ static bool parse_certificate(private_openssl_x509_t *this)
{
return FALSE;
}
- parse_extKeyUsage(this);
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher || !hasher->allocate_hash(hasher, this->encoding, &this->hash))