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.am4
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.in10
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_crl.c530
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_crl.h48
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c6
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_private_key.c27
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_public_key.c31
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.c36
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c28
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c44
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_sha1_prf.h2
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_util.c83
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_util.h56
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_x509.c871
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_x509.h50
15 files changed, 1763 insertions, 63 deletions
diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am
index a50799798..5c845a19c 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.am
+++ b/src/libstrongswan/plugins/openssl/Makefile.am
@@ -20,7 +20,9 @@ libstrongswan_openssl_la_SOURCES = \
openssl_rsa_public_key.c openssl_rsa_public_key.h \
openssl_ec_diffie_hellman.c openssl_ec_diffie_hellman.h \
openssl_ec_private_key.c openssl_ec_private_key.h \
- openssl_ec_public_key.c openssl_ec_public_key.h
+ openssl_ec_public_key.c openssl_ec_public_key.h \
+ openssl_x509.c openssl_x509.h \
+ openssl_crl.c openssl_crl.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 a2a931d42..de9df7271 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.in
+++ b/src/libstrongswan/plugins/openssl/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -79,7 +79,7 @@ am_libstrongswan_openssl_la_OBJECTS = openssl_plugin.lo \
openssl_sha1_prf.lo openssl_diffie_hellman.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_ec_public_key.lo openssl_x509.lo openssl_crl.lo
libstrongswan_openssl_la_OBJECTS = \
$(am_libstrongswan_openssl_la_OBJECTS)
libstrongswan_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -276,7 +276,9 @@ libstrongswan_openssl_la_SOURCES = \
openssl_rsa_public_key.c openssl_rsa_public_key.h \
openssl_ec_diffie_hellman.c openssl_ec_diffie_hellman.h \
openssl_ec_private_key.c openssl_ec_private_key.h \
- openssl_ec_public_key.c openssl_ec_public_key.h
+ openssl_ec_public_key.c openssl_ec_public_key.h \
+ openssl_x509.c openssl_x509.h \
+ openssl_crl.c openssl_crl.h
libstrongswan_openssl_la_LDFLAGS = -module -avoid-version
libstrongswan_openssl_la_LIBADD = -lcrypto
@@ -363,6 +365,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_crl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_crypter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_diffie_hellman.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_diffie_hellman.Plo@am__quote@
@@ -374,6 +377,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_public_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_sha1_prf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_util.Plo@am__quote@
+@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 $@ $<
diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c
new file mode 100644
index 000000000..5645d72d7
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_crl.c
@@ -0,0 +1,530 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2010 secunet Security Networks AG
+ * Copyright (C) 2010 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "openssl_crl.h"
+#include "openssl_util.h"
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include <debug.h>
+#include <utils/enumerator.h>
+#include <credentials/certificates/x509.h>
+
+typedef struct private_openssl_crl_t private_openssl_crl_t;
+
+/**
+ * Private data of an openssl_crl_t object.
+ */
+struct private_openssl_crl_t {
+
+ /**
+ * Public openssl_crl_t interface.
+ */
+ openssl_crl_t public;
+
+ /**
+ * OpenSSL representation of a CRL
+ */
+ X509_CRL *crl;
+
+ /**
+ * DER encoding of the CRL
+ */
+ chunk_t encoding;
+
+ /**
+ * Serial Number (crlNumber) of the CRL)
+ */
+ chunk_t serial;
+
+ /**
+ * AuthorityKeyIdentifier of the issuing CA
+ */
+ chunk_t authKeyIdentifier;
+
+ /**
+ * Date of this CRL
+ */
+ time_t thisUpdate;
+
+ /**
+ * Date of next CRL expected
+ */
+ time_t nextUpdate;
+
+ /**
+ * Issuer of this CRL
+ */
+ identification_t *issuer;
+
+ /**
+ * Signature scheme used in this CRL
+ */
+ signature_scheme_t scheme;
+
+ /**
+ * References to this CRL
+ */
+ refcount_t ref;
+};
+
+/**
+ * Enumerator over revoked certificates
+ */
+typedef struct {
+ /**
+ * Implements enumerator_t
+ */
+ enumerator_t public;
+
+ /**
+ * stack of revoked certificates
+ */
+ STACK_OF(X509_REVOKED) *stack;
+
+ /**
+ * Total number of revoked certificates
+ */
+ int num;
+
+ /**
+ * Current position of enumerator
+ */
+ int i;
+} crl_enumerator_t;
+
+
+METHOD(enumerator_t, crl_enumerate, bool,
+ crl_enumerator_t *this, chunk_t *serial, time_t *date, crl_reason_t *reason)
+{
+ if (this->i < this->num)
+ {
+ X509_REVOKED *revoked;
+ ASN1_ENUMERATED *crlrsn;
+
+ revoked = sk_X509_REVOKED_value(this->stack, this->i);
+ if (serial)
+ {
+ *serial = openssl_asn1_str2chunk(revoked->serialNumber);
+ }
+ if (date)
+ {
+ *date = openssl_asn1_to_time(revoked->revocationDate);
+ }
+ if (reason)
+ {
+ *reason = CRL_REASON_UNSPECIFIED;
+ crlrsn = X509_REVOKED_get_ext_d2i(revoked, NID_crl_reason,
+ NULL, NULL);
+ if (crlrsn)
+ {
+ if (ASN1_STRING_type(crlrsn) == V_ASN1_ENUMERATED &&
+ ASN1_STRING_length(crlrsn) == 1)
+ {
+ *reason = *ASN1_STRING_data(crlrsn);
+ }
+ ASN1_STRING_free(crlrsn);
+ }
+ }
+ this->i++;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(crl_t, create_enumerator, enumerator_t*,
+ private_openssl_crl_t *this)
+{
+ crl_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_crl_enumerate,
+ .destroy = (void*)free,
+ },
+ .stack = X509_CRL_get_REVOKED(this->crl),
+ );
+ if (!enumerator->stack)
+ {
+ free(enumerator);
+ return enumerator_create_empty();
+ }
+ enumerator->num = sk_X509_EXTENSION_num(enumerator->stack);
+ return &enumerator->public;
+}
+
+METHOD(crl_t, get_serial, chunk_t,
+ private_openssl_crl_t *this)
+{
+ return this->serial;
+}
+
+METHOD(crl_t, get_authKeyIdentifier, chunk_t,
+ private_openssl_crl_t *this)
+{
+ return this->authKeyIdentifier;
+}
+
+METHOD(certificate_t, get_type, certificate_type_t,
+ private_openssl_crl_t *this)
+{
+ return CERT_X509_CRL;
+}
+
+METHOD(certificate_t, get_subject_or_issuer, identification_t*,
+ private_openssl_crl_t *this)
+{
+ return this->issuer;
+}
+
+METHOD(certificate_t, has_subject_or_issuer, id_match_t,
+ private_openssl_crl_t *this, identification_t *id)
+{
+ if (id->get_type(id) == ID_KEY_ID &&
+ chunk_equals(this->authKeyIdentifier, id->get_encoding(id)))
+ {
+ return ID_MATCH_PERFECT;
+ }
+ return this->issuer->matches(this->issuer, id);
+}
+
+METHOD(certificate_t, issued_by, bool,
+ private_openssl_crl_t *this, certificate_t *issuer)
+{
+ chunk_t fingerprint, tbs;
+ public_key_t *key;
+ x509_t *x509;
+ bool valid;
+
+ if (issuer->get_type(issuer) != CERT_X509)
+ {
+ return FALSE;
+ }
+ x509 = (x509_t*)issuer;
+ if (!(x509->get_flags(x509) & X509_CA))
+ {
+ return FALSE;
+ }
+ key = issuer->get_public_key(issuer);
+ if (!key)
+ {
+ return FALSE;
+ }
+ if (this->authKeyIdentifier.ptr && key)
+ {
+ if (!key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) ||
+ !chunk_equals(fingerprint, this->authKeyIdentifier))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
+ {
+ return FALSE;
+ }
+ }
+ if (this->scheme == SIGN_UNKNOWN)
+ {
+ return FALSE;
+ }
+ tbs = openssl_i2chunk(X509_CRL_INFO, this->crl->crl);
+ valid = key->verify(key, this->scheme, tbs,
+ openssl_asn1_str2chunk(this->crl->signature));
+ free(tbs.ptr);
+ key->destroy(key);
+ return valid;
+}
+
+METHOD(certificate_t, get_public_key, public_key_t*,
+ private_openssl_crl_t *this)
+{
+ return NULL;
+}
+
+METHOD(certificate_t, get_validity, bool,
+ private_openssl_crl_t *this,
+ time_t *when, time_t *not_before, time_t *not_after)
+{
+ time_t t = when ? *when : time(NULL);
+
+ if (not_before)
+ {
+ *not_before = this->thisUpdate;
+ }
+ if (not_after)
+ {
+ *not_after = this->nextUpdate;
+ }
+ return t <= this->nextUpdate;
+}
+
+METHOD(certificate_t, get_encoding, bool,
+ private_openssl_crl_t *this, cred_encoding_type_t type, chunk_t *encoding)
+{
+ if (type == CERT_ASN1_DER)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_X509_CRL_ASN1_DER, this->encoding, CRED_PART_END);
+}
+
+METHOD(certificate_t, equals, bool,
+ private_openssl_crl_t *this, certificate_t *other)
+{
+ chunk_t encoding;
+ bool equal;
+
+ if (&this->public.crl.certificate == other)
+ {
+ return TRUE;
+ }
+ if (other->equals == (void*)equals)
+ { /* skip allocation if we have the same implementation */
+ return chunk_equals(this->encoding,
+ ((private_openssl_crl_t*)other)->encoding);
+ }
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
+ equal = chunk_equals(this->encoding, encoding);
+ free(encoding.ptr);
+ return equal;
+}
+
+METHOD(certificate_t, get_ref, certificate_t*,
+ private_openssl_crl_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.crl.certificate;
+}
+
+METHOD(certificate_t, destroy, void,
+ private_openssl_crl_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ if (this->crl)
+ {
+ X509_CRL_free(this->crl);
+ }
+ DESTROY_IF(this->issuer);
+ free(this->authKeyIdentifier.ptr);
+ free(this->serial.ptr);
+ free(this->encoding.ptr);
+ free(this);
+ }
+}
+
+/**
+ * Create an empty CRL.
+ */
+static private_openssl_crl_t *create_empty()
+{
+ private_openssl_crl_t *this;
+
+ INIT(this,
+ .public = {
+ .crl = {
+ .certificate = {
+ .get_type = _get_type,
+ .get_subject = _get_subject_or_issuer,
+ .get_issuer = _get_subject_or_issuer,
+ .has_subject = _has_subject_or_issuer,
+ .has_issuer = _has_subject_or_issuer,
+ .issued_by = _issued_by,
+ .get_public_key = _get_public_key,
+ .get_validity = _get_validity,
+ .get_encoding = _get_encoding,
+ .equals = _equals,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_serial = _get_serial,
+ .get_authKeyIdentifier = _get_authKeyIdentifier,
+ .create_enumerator = _create_enumerator,
+ },
+ },
+ .ref = 1,
+ );
+ return this;
+}
+
+/**
+ * Parse the authKeyIdentifier extension
+ */
+static bool parse_authKeyIdentifier_ext(private_openssl_crl_t *this,
+ X509_EXTENSION *ext)
+{
+ AUTHORITY_KEYID *keyid;
+
+ keyid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
+ if (keyid)
+ {
+ free(this->authKeyIdentifier.ptr);
+ this->authKeyIdentifier = chunk_clone(
+ openssl_asn1_str2chunk(keyid->keyid));
+ AUTHORITY_KEYID_free(keyid);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse the crlNumber extension
+ */
+static bool parse_crlNumber_ext(private_openssl_crl_t *this,
+ X509_EXTENSION *ext)
+{
+ free(this->serial.ptr);
+ this->serial = chunk_clone(
+ openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext)));
+ return this->serial.len != 0;
+}
+
+/**
+ * Parse X509 CRL extensions
+ */
+static bool parse_extensions(private_openssl_crl_t *this)
+{
+ bool ok;
+ int i, num;
+ X509_EXTENSION *ext;
+ STACK_OF(X509_EXTENSION) *extensions;
+
+ extensions = this->crl->crl->extensions;
+ if (extensions)
+ {
+ num = sk_X509_EXTENSION_num(extensions);
+ for (i = 0; i < num; ++i)
+ {
+ ext = sk_X509_EXTENSION_value(extensions, i);
+
+ switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
+ {
+ case NID_authority_key_identifier:
+ ok = parse_authKeyIdentifier_ext(this, ext);
+ break;
+ case NID_crl_number:
+ ok = parse_crlNumber_ext(this, ext);
+ break;
+ default:
+ ok = TRUE;
+ break;
+ }
+ if (!ok)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Parse a X509 CRL
+ */
+static bool parse_crl(private_openssl_crl_t *this)
+{
+ const unsigned char *ptr = this->encoding.ptr;
+
+ this->crl = d2i_X509_CRL(NULL, &ptr, this->encoding.len);
+ if (!this->crl)
+ {
+ return FALSE;
+ }
+
+ if (!chunk_equals(
+ openssl_asn1_obj2chunk(this->crl->crl->sig_alg->algorithm),
+ openssl_asn1_obj2chunk(this->crl->sig_alg->algorithm)))
+ {
+ return FALSE;
+ }
+ this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(
+ this->crl->sig_alg->algorithm));
+
+ this->issuer = openssl_x509_name2id(X509_CRL_get_issuer(this->crl));
+ if (!this->issuer)
+ {
+ return FALSE;
+ }
+ this->thisUpdate = openssl_asn1_to_time(X509_CRL_get_lastUpdate(this->crl));
+ this->nextUpdate = openssl_asn1_to_time(X509_CRL_get_nextUpdate(this->crl));
+
+ return parse_extensions(this);
+}
+
+/**
+ * Load the CRL.
+ */
+openssl_crl_t *openssl_crl_load(certificate_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;
+ }
+ if (blob.ptr)
+ {
+ private_openssl_crl_t *this = create_empty();
+
+ this->encoding = chunk_clone(blob);
+ if (parse_crl(this))
+ {
+ return &this->public;
+ }
+ destroy(this);
+ }
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.h b/src/libstrongswan/plugins/openssl/openssl_crl.h
new file mode 100644
index 000000000..a0837cf50
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_crl.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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_crl openssl_crl
+ * @{ @ingroup openssl_p
+ */
+
+#ifndef OPENSSL_CRL_H_
+#define OPENSSL_CRL_H_
+
+typedef struct openssl_crl_t openssl_crl_t;
+
+#include <credentials/certificates/crl.h>
+
+/**
+ * X.509 Certificate Revocation list implemented with OpenSSL.
+ */
+struct openssl_crl_t {
+
+ /**
+ * Implements the crl_t interface.
+ */
+ crl_t crl;
+};
+
+/**
+ * Load a X.509 CRL using OpenSSL.
+ *
+ * @param type certificate type, CERT_X509_CRL only
+ * @param args builder_part_t argument list
+ * @return X.509 CRL, NULL on failure
+ */
+openssl_crl_t *openssl_crl_load(certificate_type_t type, va_list args);
+
+#endif /** OPENSSL_CRL_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
index faec411cd..a53e8aea0 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
@@ -13,6 +13,10 @@
* for more details.
*/
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_EC
+
#include <openssl/ec.h>
#include <openssl/objects.h>
@@ -331,3 +335,5 @@ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_gro
return &this->public;
}
+#endif /* OPENSSL_NO_EC */
+
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
index bdcfda974..281155913 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
@@ -14,6 +14,10 @@
* for more details.
*/
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_EC
+
#include "openssl_ec_private_key.h"
#include "openssl_ec_public_key.h"
#include "openssl_util.h"
@@ -47,7 +51,7 @@ struct private_openssl_ec_private_key_t {
};
/* from ec public key */
-bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp);
+bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp);
/**
* Build a signature as in RFC 4754
@@ -217,7 +221,7 @@ static public_key_t* get_public_key(private_openssl_ec_private_key_t *this)
* Implementation of private_key_t.get_fingerprint.
*/
static bool get_fingerprint(private_openssl_ec_private_key_t *this,
- key_encoding_type_t type, chunk_t *fingerprint)
+ cred_encoding_type_t type, chunk_t *fingerprint)
{
return openssl_ec_fingerprint(this->ec, type, fingerprint);
}
@@ -226,14 +230,14 @@ static bool get_fingerprint(private_openssl_ec_private_key_t *this,
* Implementation of private_key_t.get_encoding.
*/
static bool get_encoding(private_openssl_ec_private_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
u_char *p;
switch (type)
{
- case KEY_PRIV_ASN1_DER:
- case KEY_PRIV_PEM:
+ case PRIVKEY_ASN1_DER:
+ case PRIVKEY_PEM:
{
bool success = TRUE;
@@ -241,13 +245,13 @@ static bool get_encoding(private_openssl_ec_private_key_t *this,
p = encoding->ptr;
i2d_ECPrivateKey(this->ec, &p);
- if (type == KEY_PRIV_PEM)
+ if (type == PRIVKEY_PEM)
{
chunk_t asn1_encoding = *encoding;
- success = lib->encoding->encode(lib->encoding, KEY_PRIV_PEM,
- NULL, encoding, KEY_PART_ECDSA_PRIV_ASN1_DER,
- asn1_encoding, KEY_PART_END);
+ success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
+ NULL, encoding, CRED_PART_ECDSA_PRIV_ASN1_DER,
+ asn1_encoding, CRED_PART_END);
chunk_clear(&asn1_encoding);
}
return success;
@@ -296,9 +300,9 @@ static private_openssl_ec_private_key_t *create_empty(void)
this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key;
this->public.interface.equals = private_key_equals;
this->public.interface.belongs_to = private_key_belongs_to;
- this->public.interface.get_fingerprint = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(private_key_t*, chunk_t fp))private_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref;
this->public.interface.destroy = (void (*)(private_key_t *this))destroy;
@@ -402,4 +406,5 @@ openssl_ec_private_key_t *openssl_ec_private_key_load(key_type_t type,
}
return &this->public;
}
+#endif /* OPENSSL_NO_EC */
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
index 790a8487d..def36c92f 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
@@ -14,6 +14,10 @@
* for more details.
*/
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_EC
+
#include "openssl_ec_public_key.h"
#include "openssl_util.h"
@@ -189,7 +193,7 @@ static size_t get_keysize(private_openssl_ec_public_key_t *this)
/**
* Calculate fingerprint from a EC_KEY, also used in ec private key.
*/
-bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp)
+bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp)
{
hasher_t *hasher;
chunk_t key;
@@ -201,12 +205,12 @@ bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp)
}
switch (type)
{
- case KEY_ID_PUBKEY_SHA1:
+ case KEYID_PUBKEY_SHA1:
key = chunk_alloc(i2o_ECPublicKey(ec, NULL));
p = key.ptr;
i2o_ECPublicKey(ec, &p);
break;
- case KEY_ID_PUBKEY_INFO_SHA1:
+ case KEYID_PUBKEY_INFO_SHA1:
key = chunk_alloc(i2d_EC_PUBKEY(ec, NULL));
p = key.ptr;
i2d_EC_PUBKEY(ec, &p);
@@ -232,7 +236,7 @@ bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp)
* Implementation of private_key_t.get_fingerprint.
*/
static bool get_fingerprint(private_openssl_ec_public_key_t *this,
- key_encoding_type_t type, chunk_t *fingerprint)
+ cred_encoding_type_t type, chunk_t *fingerprint)
{
return openssl_ec_fingerprint(this->ec, type, fingerprint);
}
@@ -241,14 +245,14 @@ static bool get_fingerprint(private_openssl_ec_public_key_t *this,
* Implementation of private_key_t.get_encoding.
*/
static bool get_encoding(private_openssl_ec_public_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
u_char *p;
switch (type)
{
- case KEY_PUB_SPKI_ASN1_DER:
- case KEY_PUB_PEM:
+ case PUBKEY_SPKI_ASN1_DER:
+ case PUBKEY_PEM:
{
bool success = TRUE;
@@ -256,13 +260,13 @@ static bool get_encoding(private_openssl_ec_public_key_t *this,
p = encoding->ptr;
i2d_EC_PUBKEY(this->ec, &p);
- if (type == KEY_PUB_PEM)
+ if (type == PUBKEY_PEM)
{
chunk_t asn1_encoding = *encoding;
- success = lib->encoding->encode(lib->encoding, KEY_PUB_PEM,
- NULL, encoding, KEY_PART_ECDSA_PUB_ASN1_DER,
- asn1_encoding, KEY_PART_END);
+ success = lib->encoding->encode(lib->encoding, PUBKEY_PEM,
+ NULL, encoding, CRED_PART_ECDSA_PUB_ASN1_DER,
+ asn1_encoding, CRED_PART_END);
chunk_clear(&asn1_encoding);
}
return success;
@@ -309,9 +313,9 @@ static private_openssl_ec_public_key_t *create_empty()
this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
this->public.interface.equals = public_key_equals;
- this->public.interface.get_fingerprint = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(public_key_t*, chunk_t fp))public_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
@@ -358,4 +362,5 @@ openssl_ec_public_key_t *openssl_ec_public_key_load(key_type_t type,
}
return &this->public;
}
+#endif /* OPENSSL_NO_EC */
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index c1545ffb8..31697dcb8 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -14,10 +14,12 @@
* for more details.
*/
-#include <openssl/conf.h>
#include <openssl/evp.h>
-#include <openssl/engine.h>
+#include <openssl/conf.h>
#include <openssl/crypto.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
#include "openssl_plugin.h"
@@ -34,6 +36,8 @@
#include "openssl_rsa_public_key.h"
#include "openssl_ec_private_key.h"
#include "openssl_ec_public_key.h"
+#include "openssl_x509.h"
+#include "openssl_crl.h"
typedef struct private_openssl_plugin_t private_openssl_plugin_t;
@@ -175,8 +179,6 @@ static void destroy(private_openssl_plugin_t *this)
(prf_constructor_t)openssl_sha1_prf_create);
lib->crypto->remove_dh(lib->crypto,
(dh_constructor_t)openssl_diffie_hellman_create);
- lib->crypto->remove_dh(lib->crypto,
- (dh_constructor_t)openssl_ec_diffie_hellman_create);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_rsa_private_key_load);
lib->creds->remove_builder(lib->creds,
@@ -185,14 +187,24 @@ static void destroy(private_openssl_plugin_t *this)
(builder_function_t)openssl_rsa_private_key_connect);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_rsa_public_key_load);
+#ifndef OPENSSL_NO_EC
+ lib->crypto->remove_dh(lib->crypto,
+ (dh_constructor_t)openssl_ec_diffie_hellman_create);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_ec_private_key_load);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_ec_private_key_gen);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_ec_public_key_load);
+#endif /* OPENSSL_NO_EC */
+ lib->creds->remove_builder(lib->creds,
+ (builder_function_t)openssl_x509_load);
+ lib->creds->remove_builder(lib->creds,
+ (builder_function_t)openssl_crl_load);
+#ifndef OPENSSL_NO_ENGINE
ENGINE_cleanup();
+#endif /* OPENSSL_NO_ENGINE */
EVP_cleanup();
CONF_modules_free();
@@ -215,9 +227,11 @@ plugin_t *openssl_plugin_create()
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
+#ifndef OPENSSL_NO_ENGINE
/* activate support for hardware accelerators */
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
+#endif /* OPENSSL_NO_ENGINE */
/* crypter */
lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC,
@@ -272,6 +286,7 @@ plugin_t *openssl_plugin_create()
(dh_constructor_t)openssl_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_1536_BIT,
(dh_constructor_t)openssl_diffie_hellman_create);
+#ifndef OPENSSL_NO_EC
lib->crypto->add_dh(lib->crypto, ECP_256_BIT,
(dh_constructor_t)openssl_ec_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, ECP_384_BIT,
@@ -282,6 +297,7 @@ plugin_t *openssl_plugin_create()
(dh_constructor_t)openssl_ec_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, ECP_192_BIT,
(dh_constructor_t)openssl_ec_diffie_hellman_create);
+#endif /* OPENSSL_NO_EC */
lib->crypto->add_dh(lib->crypto, MODP_3072_BIT,
(dh_constructor_t)openssl_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_4096_BIT,
@@ -306,14 +322,24 @@ plugin_t *openssl_plugin_create()
(builder_function_t)openssl_rsa_private_key_connect);
lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
(builder_function_t)openssl_rsa_public_key_load);
+ lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
+ (builder_function_t)openssl_rsa_public_key_load);
- /* ec */
+#ifndef OPENSSL_NO_EC
+ /* ecdsa */
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
(builder_function_t)openssl_ec_private_key_load);
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
(builder_function_t)openssl_ec_private_key_gen);
lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
(builder_function_t)openssl_ec_public_key_load);
+#endif /* OPENSSL_NO_EC */
+
+ /* X509 certificates */
+ lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ (builder_function_t)openssl_x509_load);
+ lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+ (builder_function_t)openssl_crl_load);
return &this->public.plugin;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
index de751fe89..5817ade9e 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
@@ -21,7 +21,9 @@
#include <openssl/evp.h>
#include <openssl/rsa.h>
+#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
+#endif /* OPENSSL_NO_ENGINE */
/**
* Public exponent to use for key generation.
@@ -56,7 +58,7 @@ struct private_openssl_rsa_private_key_t {
};
/* implemented in rsa public key */
-bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp);
+bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp);
/**
* Build an EMPSA PKCS1 signature described in PKCS#1
@@ -206,7 +208,7 @@ static public_key_t* get_public_key(private_openssl_rsa_private_key_t *this)
* Implementation of public_key_t.get_fingerprint.
*/
static bool get_fingerprint(private_openssl_rsa_private_key_t *this,
- key_encoding_type_t type, chunk_t *fingerprint)
+ cred_encoding_type_t type, chunk_t *fingerprint)
{
return openssl_rsa_fingerprint(this->rsa, type, fingerprint);
}
@@ -215,7 +217,7 @@ static bool get_fingerprint(private_openssl_rsa_private_key_t *this,
* Implementation of public_key_t.get_encoding.
*/
static bool get_encoding(private_openssl_rsa_private_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
u_char *p;
@@ -225,8 +227,8 @@ static bool get_encoding(private_openssl_rsa_private_key_t *this,
}
switch (type)
{
- case KEY_PRIV_ASN1_DER:
- case KEY_PRIV_PEM:
+ case PRIVKEY_ASN1_DER:
+ case PRIVKEY_PEM:
{
bool success = TRUE;
@@ -234,13 +236,13 @@ static bool get_encoding(private_openssl_rsa_private_key_t *this,
p = encoding->ptr;
i2d_RSAPrivateKey(this->rsa, &p);
- if (type == KEY_PRIV_PEM)
+ if (type == PRIVKEY_PEM)
{
chunk_t asn1_encoding = *encoding;
- success = lib->encoding->encode(lib->encoding, KEY_PRIV_PEM,
- NULL, encoding, KEY_PART_RSA_PRIV_ASN1_DER,
- asn1_encoding, KEY_PART_END);
+ success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
+ NULL, encoding, CRED_PART_RSA_PRIV_ASN1_DER,
+ asn1_encoding, CRED_PART_END);
chunk_clear(&asn1_encoding);
}
return success;
@@ -289,9 +291,9 @@ static private_openssl_rsa_private_key_t *create_empty(void)
this->public.interface.get_public_key = (public_key_t* (*) (private_key_t*))get_public_key;
this->public.interface.equals = private_key_equals;
this->public.interface.belongs_to = private_key_belongs_to;
- this->public.interface.get_fingerprint = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(private_key_t*, chunk_t fp))private_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (private_key_t* (*) (private_key_t*))get_ref;
this->public.interface.destroy = (void (*) (private_key_t*))destroy;
@@ -447,6 +449,7 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type,
openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
va_list args)
{
+#ifndef OPENSSL_NO_ENGINE
private_openssl_rsa_private_key_t *this;
char *keyid = NULL, *pin = NULL;
EVP_PKEY *key;
@@ -511,5 +514,8 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
this->engine = TRUE;
return &this->public;
+#else /* OPENSSL_NO_ENGINE */
+ return NULL;
+#endif /* OPENSSL_NO_ENGINE */
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
index ffa575a97..6ac61a65c 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
@@ -172,7 +172,7 @@ static size_t get_keysize(private_openssl_rsa_public_key_t *this)
/**
* Calculate fingerprint from a RSA key, also used in rsa private key.
*/
-bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp)
+bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp)
{
hasher_t *hasher;
chunk_t key;
@@ -184,12 +184,12 @@ bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp)
}
switch (type)
{
- case KEY_ID_PUBKEY_SHA1:
+ case KEYID_PUBKEY_SHA1:
key = chunk_alloc(i2d_RSAPublicKey(rsa, NULL));
p = key.ptr;
i2d_RSAPublicKey(rsa, &p);
break;
- case KEY_ID_PUBKEY_INFO_SHA1:
+ case KEYID_PUBKEY_INFO_SHA1:
key = chunk_alloc(i2d_RSA_PUBKEY(rsa, NULL));
p = key.ptr;
i2d_RSA_PUBKEY(rsa, &p);
@@ -215,7 +215,7 @@ bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp)
* Implementation of public_key_t.get_fingerprint.
*/
static bool get_fingerprint(private_openssl_rsa_public_key_t *this,
- key_encoding_type_t type, chunk_t *fingerprint)
+ cred_encoding_type_t type, chunk_t *fingerprint)
{
return openssl_rsa_fingerprint(this->rsa, type, fingerprint);
}
@@ -224,14 +224,14 @@ static bool get_fingerprint(private_openssl_rsa_public_key_t *this,
* Implementation of public_key_t.get_encoding.
*/
static bool get_encoding(private_openssl_rsa_public_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
u_char *p;
switch (type)
{
- case KEY_PUB_SPKI_ASN1_DER:
- case KEY_PUB_PEM:
+ case PUBKEY_SPKI_ASN1_DER:
+ case PUBKEY_PEM:
{
bool success = TRUE;
@@ -239,18 +239,18 @@ static bool get_encoding(private_openssl_rsa_public_key_t *this,
p = encoding->ptr;
i2d_RSA_PUBKEY(this->rsa, &p);
- if (type == KEY_PUB_PEM)
+ if (type == PUBKEY_PEM)
{
chunk_t asn1_encoding = *encoding;
- success = lib->encoding->encode(lib->encoding, KEY_PUB_PEM,
- NULL, encoding, KEY_PART_RSA_PUB_ASN1_DER,
- asn1_encoding, KEY_PART_END);
+ success = lib->encoding->encode(lib->encoding, PUBKEY_PEM,
+ NULL, encoding, CRED_PART_RSA_PUB_ASN1_DER,
+ asn1_encoding, CRED_PART_END);
chunk_clear(&asn1_encoding);
}
return success;
}
- case KEY_PUB_ASN1_DER:
+ case PUBKEY_ASN1_DER:
{
*encoding = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL));
p = encoding->ptr;
@@ -299,9 +299,9 @@ static private_openssl_rsa_public_key_t *create_empty()
this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
this->public.interface.equals = public_key_equals;
this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
- this->public.interface.get_fingerprint = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(public_key_t*, chunk_t fp))public_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
@@ -345,13 +345,25 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type,
this = create_empty();
if (blob.ptr)
{
- this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&blob.ptr, blob.len);
+ switch (type)
+ {
+ case KEY_ANY:
+ this->rsa = d2i_RSA_PUBKEY(NULL, (const u_char**)&blob.ptr,
+ blob.len);
+ break;
+ case KEY_RSA:
+ this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&blob.ptr,
+ blob.len);
+ break;
+ default:
+ break;
+ }
if (this->rsa)
{
return &this->public;
}
}
- else if (n.ptr && e.ptr)
+ else if (n.ptr && e.ptr && type == KEY_RSA)
{
this->rsa = RSA_new();
this->rsa->n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL);
diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h
index 9a24e7ee1..384e328e2 100644
--- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h
+++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h
@@ -15,7 +15,7 @@
/**
* @defgroup openssl_sha1_prf openssl_sha1_prf
- * @{ @ingroup sha1_p
+ * @{ @ingroup openssl_p
*/
#ifndef OPENSSL_SHA1_PRF_H_
diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c
index 55b18a524..99dca3631 100644
--- a/src/libstrongswan/plugins/openssl/openssl_util.c
+++ b/src/libstrongswan/plugins/openssl/openssl_util.c
@@ -100,7 +100,6 @@ error:
return FALSE;
}
-
/**
* Described in header.
*/
@@ -124,3 +123,85 @@ bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b)
return TRUE;
}
+/**
+ * Described in header.
+ */
+chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1)
+{
+ if (asn1)
+ {
+ return chunk_create(asn1->data, asn1->length);
+ }
+ return chunk_empty;
+}
+
+/**
+ * Described in header.
+ */
+chunk_t openssl_asn1_str2chunk(ASN1_STRING *asn1)
+{
+ if (asn1)
+ {
+ return chunk_create(ASN1_STRING_data(asn1), ASN1_STRING_length(asn1));
+ }
+ return chunk_empty;
+}
+
+/**
+ * Convert a X509 name to a ID_DER_ASN1_DN identification_t
+ */
+identification_t *openssl_x509_name2id(X509_NAME *name)
+{
+ if (name)
+ {
+ identification_t *id;
+ chunk_t chunk;
+
+ chunk = openssl_i2chunk(X509_NAME, name);
+ if (chunk.len)
+ {
+ id = identification_create_from_encoding(ID_DER_ASN1_DN, chunk);
+ free(chunk.ptr);
+ return id;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * We can't include <asn1/asn1.h>, as the ASN1_ definitions would clash
+ * with OpenSSL. Redeclare what we need.
+ */
+int asn1_known_oid(chunk_t);
+time_t asn1_to_time(chunk_t *,int);
+
+/**
+ * Described in header.
+ */
+int openssl_asn1_known_oid(ASN1_OBJECT *obj)
+{
+ return asn1_known_oid(openssl_asn1_obj2chunk(obj));
+}
+
+/**
+ * Described in header.
+ */
+time_t openssl_asn1_to_time(ASN1_TIME *time)
+{
+ chunk_t chunk;
+
+ if (time)
+ {
+ chunk = openssl_asn1_str2chunk(time);
+ switch (time->type)
+ {
+ case V_ASN1_UTCTIME:
+ case V_ASN1_GENERALIZEDTIME:
+ return asn1_to_time(&chunk, time->type);
+ default:
+ break;
+ }
+ }
+ DBG1(DBG_LIB, "invalid ASN1 time");
+ return 0;
+}
diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h
index 538008f2c..25c692a1a 100644
--- a/src/libstrongswan/plugins/openssl/openssl_util.h
+++ b/src/libstrongswan/plugins/openssl/openssl_util.h
@@ -23,6 +23,7 @@
#include <library.h>
#include <openssl/bn.h>
+#include <openssl/asn1.h>
/**
* Returns the length in bytes of a field element
@@ -37,7 +38,7 @@
* @param hash_type NID of the hash
* @param data the chunk of data to hash
* @param hash chunk that contains the hash
- * @return TRUE on success, FALSE otherwise
+ * @return TRUE on success, FALSE otherwise
*/
bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash);
@@ -65,4 +66,57 @@ bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk);
*/
bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b);
+
+/**
+ * Allocate a chunk using the i2d function of a given object
+ *
+ * @param type type of the object
+ * @param obj object to convert to DER
+ * @returns allocated chunk of the object, or chunk_empty
+ */
+#define openssl_i2chunk(type, obj) ({ \
+ unsigned char *ptr = NULL; \
+ int len = i2d_##type(obj, &ptr); \
+ len < 0 ? chunk_empty : chunk_create(ptr, len);})
+
+/**
+ * Convert an OpenSSL ASN1_OBJECT to a chunk.
+ *
+ * @param asn1 asn1 object to convert
+ * @return chunk, pointing into asn1 object
+ */
+chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1);
+
+/**
+ * Convert an OpenSSL ASN1_STRING to a chunk.
+ *
+ * @param asn1 asn1 string to convert
+ * @return chunk, pointing into asn1 string
+ */
+chunk_t openssl_asn1_str2chunk(ASN1_STRING *asn1);
+
+/**
+ * Convert an openssl X509_NAME to a identification_t of type ID_DER_ASN1_DN.
+ *
+ * @param name name to convert
+ * @return identification_t, NULL on error
+ */
+identification_t *openssl_x509_name2id(X509_NAME *name);
+
+/**
+ * Check if an ASN1 oid is a an OID known by libstrongswan.
+ *
+ * @param obj openssl ASN1 object
+ * @returns OID, as defined in <asn1/oid.h>
+ */
+int openssl_asn1_known_oid(ASN1_OBJECT *obj);
+
+/**
+ * Convert an OpenSSL ASN1_TIME to a time_t.
+ *
+ * @param time openssl ASN1_TIME
+ * @returns time_t, 0 on error
+ */
+time_t openssl_asn1_to_time(ASN1_TIME *time);
+
#endif /** OPENSSL_UTIL_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c
new file mode 100644
index 000000000..1c9bb699e
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_x509.c
@@ -0,0 +1,871 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2010 secunet Security Networks AG
+ * Copyright (C) 2010 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "openssl_x509.h"
+#include "openssl_util.h"
+
+#include <debug.h>
+#include <asn1/oid.h>
+#include <utils/linked_list.h>
+
+
+typedef struct private_openssl_x509_t private_openssl_x509_t;
+
+/**
+ * Private data of an openssl_x509_t object.
+ */
+struct private_openssl_x509_t {
+
+ /**
+ * Public openssl_x509_t interface.
+ */
+ openssl_x509_t public;
+
+ /**
+ * OpenSSL certificate representation
+ */
+ X509 *x509;
+
+ /**
+ * DER encoded certificate
+ */
+ chunk_t encoding;
+
+ /**
+ * SHA1 hash of the certificate
+ */
+ chunk_t hash;
+
+ /**
+ * X509 flags
+ */
+ x509_flag_t flags;
+
+ /**
+ * Pathlen constraint
+ */
+ int pathlen;
+
+ /**
+ * certificate subject
+ */
+ identification_t *subject;
+
+ /**
+ * certificate issuer
+ */
+ identification_t *issuer;
+
+ /**
+ * Certificates public key
+ */
+ public_key_t *pubkey;
+
+ /**
+ * subjectKeyIdentifier as read from cert
+ */
+ chunk_t subjectKeyIdentifier;
+
+ /**
+ * authorityKeyIdentifier as read from cert
+ */
+ chunk_t authKeyIdentifier;
+
+ /**
+ * Start time of certificate validity
+ */
+ time_t notBefore;
+
+ /**
+ * End time of certificate validity
+ */
+ time_t notAfter;
+
+ /**
+ * Signature scheme of the certificate
+ */
+ signature_scheme_t scheme;
+
+ /**
+ * subjectAltNames
+ */
+ linked_list_t *subjectAltNames;
+
+ /**
+ * issuerAltNames
+ */
+ linked_list_t *issuerAltNames;
+
+ /**
+ * List of CRL URIs
+ */
+ linked_list_t *crl_uris;
+
+ /**
+ * List of OCSP URIs
+ */
+ linked_list_t *ocsp_uris;
+
+ /**
+ * References to this cert
+ */
+ refcount_t ref;
+};
+
+/**
+ * Convert a GeneralName to an identification_t.
+ */
+static identification_t *general_name2id(GENERAL_NAME *name)
+{
+ if (!name)
+ {
+ return NULL;
+ }
+ switch (name->type)
+ {
+ case GEN_EMAIL:
+ return identification_create_from_encoding(ID_RFC822_ADDR,
+ openssl_asn1_str2chunk(name->d.rfc822Name));
+ case GEN_DNS:
+ return identification_create_from_encoding(ID_FQDN,
+ openssl_asn1_str2chunk(name->d.dNSName));
+ case GEN_URI:
+ return identification_create_from_encoding(ID_DER_ASN1_GN_URI,
+ openssl_asn1_str2chunk(name->d.uniformResourceIdentifier));
+ case GEN_IPADD:
+ {
+ chunk_t chunk = openssl_asn1_str2chunk(name->d.iPAddress);
+ if (chunk.len == 4)
+ {
+ return identification_create_from_encoding(ID_IPV4_ADDR, chunk);
+ }
+ if (chunk.len == 16)
+ {
+ return identification_create_from_encoding(ID_IPV6_ADDR, chunk);
+ }
+ return NULL;
+ }
+ case GEN_DIRNAME :
+ return openssl_x509_name2id(name->d.directoryName);
+ default:
+ return NULL;
+ }
+}
+
+METHOD(x509_t, get_flags, x509_flag_t,
+ private_openssl_x509_t *this)
+{
+ return this->flags;
+}
+
+METHOD(x509_t, get_serial, chunk_t,
+ private_openssl_x509_t *this)
+{
+ return openssl_asn1_str2chunk(X509_get_serialNumber(this->x509));
+}
+
+METHOD(x509_t, get_subjectKeyIdentifier, chunk_t,
+ private_openssl_x509_t *this)
+{
+ chunk_t fingerprint;
+
+ if (this->subjectKeyIdentifier.len)
+ {
+ return this->subjectKeyIdentifier;
+ }
+ if (this->pubkey->get_fingerprint(this->pubkey, KEYID_PUBKEY_SHA1,
+ &fingerprint))
+ {
+ return fingerprint;
+ }
+ return chunk_empty;
+}
+
+METHOD(x509_t, get_authKeyIdentifier, chunk_t,
+ private_openssl_x509_t *this)
+{
+ if (this->authKeyIdentifier.len)
+ {
+ return this->authKeyIdentifier;
+ }
+ return chunk_empty;
+}
+
+METHOD(x509_t, get_pathLenConstraint, int,
+ private_openssl_x509_t *this)
+{
+ return this->pathlen;
+}
+
+METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
+ private_openssl_x509_t *this)
+{
+ return this->subjectAltNames->create_enumerator(this->subjectAltNames);
+}
+
+METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
+ private_openssl_x509_t *this)
+{
+ return this->crl_uris->create_enumerator(this->crl_uris);
+}
+
+METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
+ private_openssl_x509_t *this)
+{
+ return this->ocsp_uris->create_enumerator(this->ocsp_uris);
+}
+
+METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
+ private_openssl_x509_t *this)
+{
+ /* TODO */
+ return enumerator_create_empty();
+}
+
+METHOD(certificate_t, get_type, certificate_type_t,
+ private_openssl_x509_t *this)
+{
+ return CERT_X509;
+}
+
+METHOD(certificate_t, get_subject, identification_t*,
+ private_openssl_x509_t *this)
+{
+ return this->subject;
+}
+
+METHOD(certificate_t, get_issuer, identification_t*,
+ private_openssl_x509_t *this)
+{
+ return this->issuer;
+}
+
+METHOD(certificate_t, has_subject, id_match_t,
+ private_openssl_x509_t *this, identification_t *subject)
+{
+ identification_t *current;
+ enumerator_t *enumerator;
+ id_match_t match, best;
+
+ if (subject->get_type(subject) == ID_KEY_ID)
+ {
+ if (chunk_equals(this->hash, subject->get_encoding(subject)))
+ {
+ return ID_MATCH_PERFECT;
+ }
+ }
+ best = this->subject->matches(this->subject, subject);
+ enumerator = create_subjectAltName_enumerator(this);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ match = current->matches(current, subject);
+ if (match > best)
+ {
+ best = match;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return best;
+}
+
+METHOD(certificate_t, has_issuer, id_match_t,
+ private_openssl_x509_t *this, identification_t *issuer)
+{
+ /* issuerAltNames currently not supported */
+ return this->issuer->matches(this->issuer, issuer);
+}
+
+METHOD(certificate_t, issued_by, bool,
+ private_openssl_x509_t *this, certificate_t *issuer)
+{
+ public_key_t *key;
+ bool valid;
+ x509_t *x509 = (x509_t*)issuer;
+ chunk_t tbs;
+
+ if (&this->public.x509.interface == issuer)
+ {
+ if (this->flags & X509_SELF_SIGNED)
+ {
+ return TRUE;
+ }
+ }
+ else
+ {
+ if (issuer->get_type(issuer) != CERT_X509)
+ {
+ return FALSE;
+ }
+ if (!(x509->get_flags(x509) & X509_CA))
+ {
+ return FALSE;
+ }
+ if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
+ {
+ return FALSE;
+ }
+ }
+ if (this->scheme == SIGN_UNKNOWN)
+ {
+ return FALSE;
+ }
+ key = issuer->get_public_key(issuer);
+ if (!key)
+ {
+ return FALSE;
+ }
+ tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
+ valid = key->verify(key, this->scheme, tbs,
+ openssl_asn1_str2chunk(this->x509->signature));
+ free(tbs.ptr);
+ key->destroy(key);
+ return valid;
+}
+
+METHOD(certificate_t, get_public_key, public_key_t*,
+ private_openssl_x509_t *this)
+{
+ return this->pubkey->get_ref(this->pubkey);
+}
+
+METHOD(certificate_t, get_validity, bool,
+ private_openssl_x509_t *this,
+ time_t *when, time_t *not_before, time_t *not_after)
+{
+ time_t t;
+
+ if (when)
+ {
+ t = *when;
+ }
+ else
+ {
+ t = time(NULL);
+ }
+ if (not_before)
+ {
+ *not_before = this->notBefore;
+ }
+ if (not_after)
+ {
+ *not_after = this->notAfter;
+ }
+ return (t >= this->notBefore && t <= this->notAfter);
+}
+
+METHOD(certificate_t, get_encoding, bool,
+ private_openssl_x509_t *this, cred_encoding_type_t type, chunk_t *encoding)
+{
+ if (type == CERT_ASN1_DER)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_X509_ASN1_DER, this->encoding, CRED_PART_END);
+}
+
+
+METHOD(certificate_t, equals, bool,
+ private_openssl_x509_t *this, certificate_t *other)
+{
+ chunk_t encoding;
+ bool equal;
+
+ if (this == (private_openssl_x509_t*)other)
+ {
+ return TRUE;
+ }
+ if (other->get_type(other) != CERT_X509)
+ {
+ return FALSE;
+ }
+ if (other->equals == (void*)equals)
+ { /* skip allocation if we have the same implementation */
+ encoding = ((private_openssl_x509_t*)other)->encoding;
+ return chunk_equals(this->encoding, encoding);
+ }
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
+ equal = chunk_equals(this->encoding, encoding);
+ free(encoding.ptr);
+ return equal;
+}
+
+METHOD(certificate_t, get_ref, certificate_t*,
+ private_openssl_x509_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.x509.interface;
+}
+
+METHOD(certificate_t, destroy, void,
+ private_openssl_x509_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ if (this->x509)
+ {
+ X509_free(this->x509);
+ }
+ DESTROY_IF(this->subject);
+ DESTROY_IF(this->issuer);
+ DESTROY_IF(this->pubkey);
+ free(this->subjectKeyIdentifier.ptr);
+ free(this->authKeyIdentifier.ptr);
+ free(this->encoding.ptr);
+ free(this->hash.ptr);
+ this->subjectAltNames->destroy_offset(this->subjectAltNames,
+ offsetof(identification_t, destroy));
+ this->issuerAltNames->destroy_offset(this->issuerAltNames,
+ offsetof(identification_t, destroy));
+ this->crl_uris->destroy_function(this->crl_uris, free);
+ this->ocsp_uris->destroy_function(this->ocsp_uris, free);
+ free(this);
+ }
+}
+
+/**
+ * Create an empty certificate
+ */
+static private_openssl_x509_t *create_empty()
+{
+ private_openssl_x509_t *this;
+
+ INIT(this,
+ .public = {
+ .x509 = {
+ .interface = {
+ .get_type = _get_type,
+ .get_subject = _get_subject,
+ .get_issuer = _get_issuer,
+ .has_subject = _has_subject,
+ .has_issuer = _has_issuer,
+ .issued_by = _issued_by,
+ .get_public_key = _get_public_key,
+ .get_validity = _get_validity,
+ .get_encoding = _get_encoding,
+ .equals = _equals,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_flags = _get_flags,
+ .get_serial = _get_serial,
+ .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
+ .get_authKeyIdentifier = _get_authKeyIdentifier,
+ .get_pathLenConstraint = _get_pathLenConstraint,
+ .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 = _create_ipAddrBlock_enumerator,
+ },
+ },
+ .subjectAltNames = linked_list_create(),
+ .issuerAltNames = linked_list_create(),
+ .crl_uris = linked_list_create(),
+ .ocsp_uris = linked_list_create(),
+ .pathlen = X509_NO_PATH_LEN_CONSTRAINT,
+ .ref = 1,
+ );
+
+ return this;
+}
+
+/**
+ * parse an extionsion containing GENERAL_NAMES into a list
+ */
+static bool parse_generalNames_ext(linked_list_t *list,
+ X509_EXTENSION *ext)
+{
+ GENERAL_NAMES *names;
+ GENERAL_NAME *name;
+ identification_t *id;
+ int i, num;
+
+ names = X509V3_EXT_d2i(ext);
+ if (!names)
+ {
+ return FALSE;
+ }
+
+ num = sk_GENERAL_NAME_num(names);
+ for (i = 0; i < num; i++)
+ {
+ name = sk_GENERAL_NAME_value(names, i);
+ id = general_name2id(name);
+ if (id)
+ {
+ list->insert_last(list, id);
+ }
+ GENERAL_NAME_free(name);
+ }
+ sk_GENERAL_NAME_free(names);
+ return TRUE;
+}
+
+/**
+ * parse basic constraints
+ */
+static bool parse_basicConstraints_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ BASIC_CONSTRAINTS *constraints;
+
+ constraints = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ext);
+ if (constraints)
+ {
+ if (constraints->ca)
+ {
+ this->flags |= X509_CA;
+ }
+ if (constraints->pathlen)
+ {
+ this->pathlen = ASN1_INTEGER_get(constraints->pathlen);
+ }
+ BASIC_CONSTRAINTS_free(constraints);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse CRL distribution points
+ */
+static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ CRL_DIST_POINTS *cdps;
+ DIST_POINT *cdp;
+ identification_t *id;
+ char *uri;
+ int i, j, point_num, name_num;
+
+ cdps = X509V3_EXT_d2i(ext);
+ if (!cdps)
+ {
+ return FALSE;
+ }
+ point_num = sk_DIST_POINT_num(cdps);
+ for (i = 0; i < point_num; i++)
+ {
+ cdp = sk_DIST_POINT_value(cdps, i);
+ if (cdp)
+ {
+ if (cdp->distpoint && cdp->distpoint->type == 0 &&
+ cdp->distpoint->name.fullname)
+ {
+ name_num = sk_GENERAL_NAME_num(cdp->distpoint->name.fullname);
+ for (j = 0; j < name_num; j++)
+ {
+ id = general_name2id(sk_GENERAL_NAME_value(
+ cdp->distpoint->name.fullname, j));
+ if (id)
+ {
+ if (asprintf(&uri, "%Y", id) > 0)
+ {
+ this->crl_uris->insert_first(this->crl_uris, uri);
+ }
+ id->destroy(id);
+ }
+ }
+ }
+ DIST_POINT_free(cdp);
+ }
+ }
+ sk_DIST_POINT_free(cdps);
+ return TRUE;
+}
+
+/**
+ * Parse authorityInfoAccess with OCSP URIs
+ */
+static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ AUTHORITY_INFO_ACCESS *infos;
+ ACCESS_DESCRIPTION *desc;
+ identification_t *id;
+ int i, num;
+ char *uri;
+
+ infos = X509V3_EXT_d2i(ext);
+ if (!infos)
+ {
+ return FALSE;
+ }
+ num = sk_ACCESS_DESCRIPTION_num(infos);
+ for (i = 0; i < num; i++)
+ {
+ desc = sk_ACCESS_DESCRIPTION_value(infos, i);
+ if (desc)
+ {
+ if (openssl_asn1_known_oid(desc->method) == OID_OCSP)
+ {
+ id = general_name2id(desc->location);
+ if (id)
+ {
+ if (asprintf(&uri, "%Y", id) > 0)
+ {
+ this->ocsp_uris->insert_first(this->ocsp_uris, uri);
+ }
+ id->destroy(id);
+ }
+ }
+ ACCESS_DESCRIPTION_free(desc);
+ }
+ }
+ sk_ACCESS_DESCRIPTION_free(infos);
+ return TRUE;
+}
+
+/**
+ * Parse authorityKeyIdentifier extension
+ */
+static bool parse_authKeyIdentifier_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ AUTHORITY_KEYID *keyid;
+
+ keyid = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
+ if (keyid)
+ {
+ free(this->authKeyIdentifier.ptr);
+ this->authKeyIdentifier = chunk_clone(
+ openssl_asn1_str2chunk(keyid->keyid));
+ AUTHORITY_KEYID_free(keyid);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse subjectKeyIdentifier extension
+ */
+static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ chunk_t ostr;
+
+ ostr = openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext));
+ /* quick and dirty unwrap of octet string */
+ if (ostr.len > 2 &&
+ ostr.ptr[0] == V_ASN1_OCTET_STRING && ostr.ptr[1] == ostr.len - 2)
+ {
+ free(this->subjectKeyIdentifier.ptr);
+ this->subjectKeyIdentifier = chunk_clone(chunk_skip(ostr, 2));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse X509 extensions we are interested in
+ */
+static bool parse_extensions(private_openssl_x509_t *this)
+{
+ STACK_OF(X509_EXTENSION) *extensions;
+ int i, num;
+
+ extensions = this->x509->cert_info->extensions;
+ if (extensions)
+ {
+ num = sk_X509_EXTENSION_num(extensions);
+
+ for (i = 0; i < num; i++)
+ {
+ X509_EXTENSION *ext;
+ bool ok;
+
+ ext = sk_X509_EXTENSION_value(extensions, i);
+ switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
+ {
+ case NID_info_access:
+ ok = parse_authorityInfoAccess_ext(this, ext);
+ break;
+ case NID_authority_key_identifier:
+ ok = parse_authKeyIdentifier_ext(this, ext);
+ break;
+ case NID_subject_key_identifier:
+ ok = parse_subjectKeyIdentifier_ext(this, ext);
+ break;
+ case NID_subject_alt_name:
+ ok = parse_generalNames_ext(this->subjectAltNames, ext);
+ break;
+ case NID_issuer_alt_name:
+ ok = parse_generalNames_ext(this->issuerAltNames, ext);
+ break;
+ case NID_basic_constraints:
+ ok = parse_basicConstraints_ext(this, ext);
+ break;
+ case NID_crl_distribution_points:
+ ok = parse_crlDistributionPoints_ext(this, ext);
+ break;
+ default:
+ ok = TRUE;
+ break;
+ }
+ if (!ok)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Parse a DER encoded x509 certificate
+ */
+static bool parse_certificate(private_openssl_x509_t *this)
+{
+ const unsigned char *ptr = this->encoding.ptr;
+ hasher_t *hasher;
+ chunk_t chunk;
+
+ this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
+ if (!this->x509)
+ {
+ return FALSE;
+ }
+ this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
+ this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
+
+ switch (openssl_asn1_known_oid(this->x509->cert_info->key->algor->algorithm))
+ {
+ case OID_RSA_ENCRYPTION:
+ this->pubkey = lib->creds->create(lib->creds,
+ CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_ASN1_DER,
+ openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509)),
+ BUILD_END);
+ break;
+ case OID_EC_PUBLICKEY:
+ /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
+ * the curve parameters. */
+ chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
+ this->pubkey = lib->creds->create(lib->creds,
+ CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
+ chunk, BUILD_END);
+ free(chunk.ptr);
+ break;
+ default:
+ DBG1(DBG_LIB, "unsupported public key algorithm");
+ break;
+ }
+ if (!this->subject || !this->issuer || !this->pubkey)
+ {
+ return FALSE;
+ }
+
+ this->notBefore = openssl_asn1_to_time(X509_get_notBefore(this->x509));
+ this->notAfter = openssl_asn1_to_time(X509_get_notAfter(this->x509));
+
+ if (!chunk_equals(
+ openssl_asn1_obj2chunk(this->x509->cert_info->signature->algorithm),
+ openssl_asn1_obj2chunk(this->x509->sig_alg->algorithm)))
+ {
+ return FALSE;
+ }
+ this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(
+ this->x509->sig_alg->algorithm));
+
+ if (!parse_extensions(this))
+ {
+ return TRUE;
+ }
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher)
+ {
+ return FALSE;
+ }
+ hasher->allocate_hash(hasher, this->encoding, &this->hash);
+ hasher->destroy(hasher);
+
+ if (issued_by(this, &this->public.x509.interface))
+ {
+ this->flags |= X509_SELF_SIGNED;
+ }
+ return TRUE;
+}
+
+openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args)
+{
+ chunk_t blob = chunk_empty;
+ x509_flag_t flags = 0;
+
+ while (TRUE)
+ {
+ switch (va_arg(args, builder_part_t))
+ {
+ case BUILD_BLOB_ASN1_DER:
+ blob = va_arg(args, chunk_t);
+ continue;
+ case BUILD_X509_FLAG:
+ flags |= va_arg(args, x509_flag_t);
+ continue;
+ case BUILD_END:
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ }
+
+ if (blob.ptr)
+ {
+ private_openssl_x509_t *this;
+
+ this = create_empty();
+ this->encoding = chunk_clone(blob);
+ this->flags |= flags;
+ if (parse_certificate(this))
+ {
+ return &this->public;
+ }
+ DBG1(DBG_LIB, "OpenSSL X.509 parsing failed");
+ destroy(this);
+ }
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.h b/src/libstrongswan/plugins/openssl/openssl_x509.h
new file mode 100644
index 000000000..52555925a
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_x509.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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_x509 openssl_x509
+ * @{ @ingroup openssl_p
+ */
+
+#ifndef OPENSSL_X509_H_
+#define OPENSSL_X509_H_
+
+#include <credentials/certificates/x509.h>
+
+typedef struct openssl_x509_t openssl_x509_t;
+
+/**
+ * X.509 certificate implementation using OpenSSL.
+ */
+struct openssl_x509_t {
+
+ /**
+ * Implements x509_t interface.
+ */
+ x509_t x509;
+};
+
+/**
+ * Load a X.509 certificate.
+ *
+ * This function takes a BUILD_BLOB_ASN1_DER.
+ *
+ * @param type certificate type, CERT_X509 only
+ * @param args builder_part_t argument list
+ * @return X.509 certificate, NULL on failure
+ */
+openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args);
+
+#endif /** OPENSSL_X509_H_ @}*/