plugins/lookip.opt \
plugins/ntru.opt \
plugins/openssl.opt \
+ plugins/openxpki.opt \
plugins/osx-attr.opt \
plugins/p-cscf.opt \
plugins/pkcs11.opt \
--- /dev/null
+charon.plugins.openxpki.database =
+ Database URI connecting to the OpenXPKI **certificate** database. If it
+ contains a password, make sure to adjust the permissions of the config
+ file accordingly.
ARG_DISBL_SET([pubkey], [disable RAW public key support plugin.])
ARG_DISBL_SET([sshkey], [disable SSH key decoding plugin.])
ARG_DISBL_SET([x509], [disable X509 certificate implementation plugin.])
+ARG_ENABL_SET([openxpki], [enable OCSP responder accessing OpenXPKI certificate database.])
# fetcher/resolver plugins
ARG_ENABL_SET([curl], [enable CURL fetcher plugin to fetch files via libcurl. Requires libcurl.])
ARG_ENABL_SET([files], [enable simple file:// URI fetcher.])
ADD_PLUGIN([files], [s charon pki scripts nm cmd])
ADD_PLUGIN([winhttp], [s charon pki scripts])
ADD_PLUGIN([soup], [s charon pki scripts nm cmd])
-ADD_PLUGIN([mysql], [s charon pool manager medsrv attest])
-ADD_PLUGIN([sqlite], [s charon pool manager medsrv attest])
+ADD_PLUGIN([mysql], [s charon pki pool manager medsrv attest])
+ADD_PLUGIN([sqlite], [s charon pki pool manager medsrv attest])
+ADD_PLUGIN([openxpki], [s pki])
ADD_PLUGIN([attr], [c charon])
ADD_PLUGIN([attr-sql], [c charon])
ADD_PLUGIN([load-tester], [c charon])
AM_CONDITIONAL(USE_PKCS7, test x$pkcs7 = xtrue)
AM_CONDITIONAL(USE_PKCS8, test x$pkcs8 = xtrue)
AM_CONDITIONAL(USE_PKCS12, test x$pkcs12 = xtrue)
+AM_CONDITIONAL(USE_OPENXPKI, test x$openxpki = xtrue)
AM_CONDITIONAL(USE_PGP, test x$pgp = xtrue)
AM_CONDITIONAL(USE_DNSKEY, test x$dnskey = xtrue)
AM_CONDITIONAL(USE_SSHKEY, test x$sshkey = xtrue)
src/libstrongswan/plugins/pkcs7/Makefile
src/libstrongswan/plugins/pkcs8/Makefile
src/libstrongswan/plugins/pkcs12/Makefile
+ src/libstrongswan/plugins/openxpki/Makefile
src/libstrongswan/plugins/pgp/Makefile
src/libstrongswan/plugins/dnskey/Makefile
src/libstrongswan/plugins/sshkey/Makefile
credentials/certificates/ac.h credentials/certificates/crl.h \
credentials/certificates/pkcs10.h credentials/certificates/ocsp_request.h \
credentials/certificates/ocsp_response.h \
+credentials/certificates/ocsp_responder.h \
credentials/certificates/pgp_certificate.h \
credentials/certificates/certificate_printer.h \
credentials/containers/container.h credentials/containers/pkcs7.h \
endif
endif
+if USE_OPENXPKI
+ SUBDIRS += plugins/openxpki
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/openxpki/libstrongswan-openxpki.la
+endif
+endif
+
if USE_PGP
SUBDIRS += plugins/pgp
if MONOLITHIC
--- /dev/null
+/*
+ * Copyright (C) 2023 Andreas Steffen, strongSec GmbH
+ *
+ * Copyright (C) secunet Security Networks 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 ocsp_responder ocsp_responder
+ * @{ @ingroup certificates
+ */
+
+#ifndef OCSP_RESPONDER_H_
+#define OCSP_RESPONDER_H_
+
+#include <credentials/certificates/crl.h>
+
+typedef struct ocsp_responder_t ocsp_responder_t;
+
+/**
+ * OCSP responder object.
+ */
+struct ocsp_responder_t {
+
+ /**
+ * Check the status of a certificate given by its serial number
+ *
+ * @param cacert X.509 certificate of issuer CA
+ * @param serial_number serial number of the certificate to be checked
+ * @param revocation_time receives time of revocation, if revoked
+ * @param reason receives reason of revocation, if revoked
+ * @return certificate validation status
+ */
+ cert_validation_t (*get_status)(ocsp_responder_t *this,
+ certificate_t *cacert,
+ chunk_t serial_number,
+ time_t *revocation_time,
+ crl_reason_t *revocation_reason);
+
+ /**
+ * Destroy an ocsp_responder_t object.
+ */
+ void (*destroy)(ocsp_responder_t *this);
+
+};
+
+#endif /** OCSP_RESPONDER_H_ @}*/
--- /dev/null
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-openxpki.la
+else
+plugin_LTLIBRARIES = libstrongswan-openxpki.la
+endif
+
+libstrongswan_openxpki_la_SOURCES = \
+ openxpki_plugin.h openxpki_plugin.c \
+ openxpki_ocsp_responder.h openxpki_ocsp_responder.c
+
+libstrongswan_openxpki_la_LDFLAGS = -module -avoid-version
--- /dev/null
+/*
+ * Copyright (C) 2023 Andreas Steffen, strongSec GmbH
+ *
+ * Copyright (C) secunet Security Networks 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.
+ */
+
+#include <library.h>
+#include <utils/debug.h>
+
+#include "openxpki_ocsp_responder.h"
+
+typedef struct private_openxpki_ocsp_responder_t private_openxpki_ocsp_responder_t;
+
+/**
+ * Private Data of a openxpki_ocsp_responder_t object.
+ */
+struct private_openxpki_ocsp_responder_t {
+
+ /**
+ * Public data
+ */
+ openxpki_ocsp_responder_t public;
+
+ /**
+ * OpenXPKI certificate database
+ */
+ database_t *db;
+};
+
+METHOD(ocsp_responder_t, get_status, cert_validation_t,
+ private_openxpki_ocsp_responder_t *this, certificate_t *cacert,
+ chunk_t serial_number, time_t *revocation_time, crl_reason_t *reason)
+{
+ cert_validation_t validation = VALIDATION_FAILED;
+ int rev_time;
+ const int max_decimals = 49;
+ const int max_bytes = max_decimals / 2.4083;
+ char serial[max_decimals + 1], authKeyId[60];
+ char *status, *reason_code;
+ chunk_t subjectKeyId;
+ public_key_t *public;
+ enumerator_t *e;
+ bool success;
+
+ /* convert serialNumber from binary to decimal as required for the DB query.
+ * check for a potential overflow since the database table field supports
+ * up to 49 decimal digits, only.
+ */
+ if (serial_number.len > max_bytes)
+ {
+ DBG1(DBG_LIB, "serialNumber conversion exceeds %d decimals", max_decimals);
+ return VALIDATION_FAILED;
+
+ }
+ chunk_to_dec(serial_number, serial);
+
+ /* additionally use the subjectyKeyId of the issuing CA for the DB query */
+ public = cacert->get_public_key(cacert);
+ success = public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &subjectKeyId);
+ public->destroy(public);
+
+ if (!success)
+ {
+ DBG1(DBG_LIB, "failed to extract subjectKeyId from CA certificate");
+ return VALIDATION_FAILED;
+ }
+
+ /* the authKeyId of the certificate is the subjectKeyId of the issuing CA */
+ snprintf(authKeyId, sizeof(authKeyId), "%#B", &subjectKeyId);
+
+ /* query the OpenXPKI certificate database */
+ e = this->db->query(this->db, "SELECT status, reason_code, revocation_time "
+ "FROM certificate WHERE cert_key = ? "
+ "AND authority_key_identifier = ?", DB_TEXT, serial,
+ DB_TEXT, authKeyId, DB_TEXT, DB_TEXT, DB_INT);
+ if (e && e->enumerate(e, &status, &reason_code, &rev_time))
+ {
+ if (streq(status, "ISSUED") || streq(status, "ISSUANCE_PENDING"))
+ {
+ validation = VALIDATION_GOOD;
+ }
+ else if (streq(status, "UNKNOWN"))
+ {
+ validation = VALIDATION_FAILED;
+ }
+ else if (streq(status, "REVOKED") || streq(status, "HOLD") ||
+ streq(status, "CRL_ISSUANCE_PENDING"))
+ {
+ validation = VALIDATION_REVOKED;
+
+ if (revocation_time)
+ {
+ *revocation_time = rev_time;
+ }
+ if (reason)
+ {
+ if (streq(reason_code, "unspecified"))
+ {
+ *reason = CRL_REASON_UNSPECIFIED;
+ }
+ else if (streq(reason_code, "keyCompromise"))
+ {
+ *reason = CRL_REASON_KEY_COMPROMISE;
+ }
+ else if (streq(reason_code, "CACompromise"))
+ {
+ *reason = CRL_REASON_CA_COMPROMISE;
+ }
+ else if (streq(reason_code, "affiliationChanged"))
+ {
+ *reason = CRL_REASON_AFFILIATION_CHANGED;
+ }
+ else if (streq(reason_code, "superseded"))
+ {
+ *reason = CRL_REASON_SUPERSEDED;
+ }
+ else if (streq(reason_code, "cessationOfOperation"))
+ {
+ *reason = CRL_REASON_CESSATION_OF_OPERATION;
+ }
+ else if (streq(reason_code, "certificateHold"))
+ {
+ *reason = CRL_REASON_CERTIFICATE_HOLD;
+ validation = VALIDATION_ON_HOLD;
+ }
+ else if (streq(reason_code, "removeFromCRL"))
+ {
+ *reason = CRL_REASON_REMOVE_FROM_CRL;
+ }
+ else
+ {
+ *reason = CRL_REASON_UNSPECIFIED;
+ }
+ }
+ }
+ }
+ DESTROY_IF(e);
+
+ return validation;
+}
+
+METHOD(ocsp_responder_t, destroy, void,
+ private_openxpki_ocsp_responder_t *this)
+{
+ this->db->destroy(this->db);
+ free(this);
+}
+
+/*
+ * See header
+ */
+ocsp_responder_t *openxpki_ocsp_responder_create()
+{
+ private_openxpki_ocsp_responder_t *this;
+ database_t *db;
+ char *uri;
+
+ uri = lib->settings->get_str(lib->settings,
+ "%s.plugins.openxpki.database", NULL, lib->ns);
+ if (!uri)
+ {
+ DBG1(DBG_CFG, "openxpki database URI missing");
+ return NULL;
+ }
+ db = lib->db->create(lib->db, uri);
+ if (!db)
+ {
+ DBG1(DBG_CFG, "opening openxpki database failed");
+ return NULL;
+ }
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_status = _get_status,
+ .destroy = _destroy,
+ },
+ },
+ .db = db,
+ );
+
+ return &this->public.interface;
+}
--- /dev/null
+/*
+ * Copyright (C) 2023 Andreas Steffen, strongSec GmbH
+ *
+ * Copyright (C) secunet Security Networks 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 openxpki_ocsp_responder openxpki_ocsp_responder
+ * @{ @ingroup openxpki_p
+ */
+
+#ifndef OPENXPKI_OCSP_RESPONDER_H_
+#define OPENXPKI_OCSP_RESPONDER_H_
+
+typedef struct openxpki_ocsp_responder_t openxpki_ocsp_responder_t;
+
+#include <credentials/certificates/ocsp_responder.h>
+
+/**
+ * OCSP responder implementation using OpenXPKI.
+ */
+struct openxpki_ocsp_responder_t {
+
+ /**
+ * Implements ocsp_responder interface
+ */
+ ocsp_responder_t interface;
+};
+
+/**
+ * Create a openxpki_ocsp_responder instance.
+ */
+ocsp_responder_t *openxpki_ocsp_responder_create();
+
+#endif /** OPENXPKI_OCSP_RESPONDER_H_ @}*/
--- /dev/null
+/*
+ * Copyright (C) 2023 Andreas Steffen, strongSec GmbH
+ *
+ * Copyright (C) secunet Security Networks 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.
+ */
+
+#include "openxpki_plugin.h"
+
+#include "openxpki_ocsp_responder.h"
+
+typedef struct private_openxpki_plugin_t private_openxpki_plugin_t;
+
+/**
+ * Private data of an openxpki_plugin_t object.
+ */
+struct private_openxpki_plugin_t {
+
+ /**
+ * Public interface.
+ */
+ openxpki_plugin_t public;
+
+ /**
+ * OCSP responder
+ */
+ ocsp_responder_t *ocsp_responder;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_openxpki_plugin_t *this)
+{
+ return "openxpki";
+}
+
+static bool plugin_cb(private_openxpki_plugin_t *this,
+ plugin_feature_t *feature, bool reg, void *cb_data)
+{
+ if (reg)
+ {
+ /* Is there already a registered OCSP responder? */
+ if (!lib->get(lib, "ocsp-responder"))
+ {
+ this->ocsp_responder = openxpki_ocsp_responder_create();
+ lib->set(lib, "ocsp-responder", this->ocsp_responder);
+ }
+ }
+ else
+ {
+ if (this->ocsp_responder)
+ {
+ lib->set(lib, "ocsp-responder", NULL);
+ this->ocsp_responder->destroy(this->ocsp_responder);
+ }
+ }
+ return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+ private_openxpki_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
+ PLUGIN_PROVIDE(CUSTOM, "ocsp-responder"),
+ PLUGIN_DEPENDS(DATABASE, DB_MYSQL),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_openxpki_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *openxpki_plugin_create()
+{
+ private_openxpki_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
--- /dev/null
+/*
+ * Copyright (C) 2023 Andreas Steffen, strongSec GmbH
+ *
+ * Copyright (C) secunet Security Networks 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 openxpki_p openxpki
+ * @ingroup plugins
+ *
+ * @defgroup openxpki_plugin openxpki_plugin
+ * @{ @ingroup openxpki_p
+ */
+
+#ifndef OPENXPKI_PLUGIN_H_
+#define OPENXPKI_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct openxpki_plugin_t openxpki_plugin_t;
+
+/**
+ * Plugin implementing an OCSP responder based on OpenXPKI.
+ */
+struct openxpki_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** OPENXPKI_PLUGIN_H_ @}*/