ARG_ENABL_SET([mgf1], [enable the MGF1 software implementation plugin.])
ARG_ENABL_SET([newhope], [enable NewHope crypto plugin.])
ARG_ENABL_SET([qske-newhope], [enable NewHope QSKE plugin.])
+ARG_ENABL_SET([oqs], [enable Open Quantum Safe (liboqs) plugin.])
ARG_DISBL_SET([nonce], [disable nonce generation plugin.])
ARG_ENABL_SET([ntru], [enables the NTRU crypto plugin.])
ARG_ENABL_SET([openssl], [enables the OpenSSL crypto plugin.])
AC_SUBST(botan_LIBS)
fi
+if test x$oqs = xtrue; then
+ saved_LIBS=$LIBS
+ LIBS="-lm"
+ AC_CHECK_LIB([oqs],[_init],,[AC_MSG_ERROR([Open Quantum-Safe library oqs not found])],[])
+ LIBS=$saved_LIBS
+ AC_CHECK_HEADER([oqs/oqs.h],,[AC_MSG_ERROR([Open Quantum-Safe header oqs/oqs.h not found!])])
+fi
+
if test x$uci = xtrue; then
AC_CHECK_LIB([uci],[uci_alloc_context],[LIBS="$LIBS"],[AC_MSG_ERROR([UCI library libuci not found])],[])
AC_CHECK_HEADER([uci.h],,[AC_MSG_ERROR([UCI header uci.h not found!])])
ADD_PLUGIN([ntru], [s charon scripts nm cmd])
ADD_PLUGIN([newhope], [s charon scripts nm cmd])
ADD_PLUGIN([qske-newhope], [s charon scripts nm cmd])
+ADD_PLUGIN([oqs], [s charon scripts nm cmd])
ADD_PLUGIN([bliss], [s charon pki scripts nm cmd])
ADD_PLUGIN([curl], [s charon scepclient pki scripts nm cmd])
ADD_PLUGIN([files], [s charon scepclient pki scripts nm cmd])
AM_CONDITIONAL(USE_NTRU, test x$ntru = xtrue)
AM_CONDITIONAL(USE_NEWHOPE, test x$newhope = xtrue)
AM_CONDITIONAL(USE_QSKE_NEWHOPE, test x$qske_newhope = xtrue)
+AM_CONDITIONAL(USE_OQS, test x$oqs = xtrue)
AM_CONDITIONAL(USE_BLISS, test x$bliss = xtrue)
# charon plugins
src/libstrongswan/plugins/newhope/tests/Makefile
src/libstrongswan/plugins/qske_newhope/Makefile
src/libstrongswan/plugins/qske_newhope/tests/Makefile
+ src/libstrongswan/plugins/oqs/Makefile
src/libstrongswan/plugins/test_vectors/Makefile
src/libstrongswan/tests/Makefile
src/libipsec/Makefile
--disable-soup --disable-unwind-backtraces
--disable-svc --disable-dbghelp-backtraces --disable-socket-win
--disable-kernel-wfp --disable-kernel-iph --disable-winhttp"
+ # liboqs would have to be installed manually
+ CONFIG="$CONFIG --disable-oqs"
# not enabled on the build server
CONFIG="$CONFIG --disable-af-alg"
if test "$TEST" != "coverage"; then
endif
endif
+if USE_OQS
+ SUBDIRS += plugins/oqs
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/oqs/libstrongswan-oqs.la
+endif
+endif
+
if USE_TEST_VECTORS
SUBDIRS += plugins/test_vectors
if MONOLITHIC
#include "qske_mechanism.h"
-ENUM(qske_mechanism_names, QSKE_NONE, QSKE_FRODO,
+ENUM(qske_mechanism_names, QSKE_NONE, QSKE_LIMA_SP_L5,
"QSKE_NONE",
"QSKE_NEWHOPE",
"QSKE_NEWHOPE_L1",
--- /dev/null
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+# these files are also used by the tests, we can't directly refer to them
+# because of the subdirectory, which would cause distclean to fail
+noinst_LTLIBRARIES = libqske-oqs.la
+libqske_oqs_la_SOURCES = \
+ oqs_qske.h oqs_qske.c
+
+libqske_oqs_la_LIBADD = \
+ -loqs -lcrypto -lm
+
+if MONOLITHIC
+noinst_LTLIBRARIES += libstrongswan-oqs.la
+else
+plugin_LTLIBRARIES = libstrongswan-oqs.la
+endif
+
+libstrongswan_oqs_la_SOURCES = \
+ oqs_plugin.h oqs_plugin.c
+
+libstrongswan_oqs_la_LDFLAGS = -module -avoid-version
+
+libstrongswan_oqs_la_LIBADD = libqske-oqs.la
--- /dev/null
+/*
+ * Copyright (C) 2018 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 "oqs_plugin.h"
+#include "oqs_qske.h"
+
+#include <library.h>
+
+typedef struct private_oqs_plugin_t private_oqs_plugin_t;
+
+/**
+ * private data of oqs_plugin
+ */
+struct private_oqs_plugin_t {
+
+ /**
+ * public functions
+ */
+ oqs_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_oqs_plugin_t *this)
+{
+ return "oqs";
+}
+
+METHOD(plugin_t, get_features, int,
+ private_oqs_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ /* QSKE groups */
+ PLUGIN_REGISTER(QSKE, oqs_qske_create),
+ PLUGIN_PROVIDE(QSKE, QSKE_NEWHOPE_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_NEWHOPE_L5),
+ PLUGIN_PROVIDE(QSKE, QSKE_FRODO_AES_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_FRODO_AES_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_FRODO_SHAKE_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_FRODO_SHAKE_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_KYBER_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_KYBER_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_KYBER_L5),
+ PLUGIN_PROVIDE(QSKE, QSKE_BIKE1_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_BIKE1_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_BIKE1_L5),
+ PLUGIN_PROVIDE(QSKE, QSKE_BIKE2_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_BIKE2_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_BIKE2_L5),
+ PLUGIN_PROVIDE(QSKE, QSKE_BIKE3_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_BIKE3_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_BIKE3_L5),
+ PLUGIN_PROVIDE(QSKE, QSKE_SIKE_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_SIKE_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_SABER_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_SABER_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_SABER_L5),
+ PLUGIN_PROVIDE(QSKE, QSKE_LIMA_2P_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_LIMA_2P_L5),
+ PLUGIN_PROVIDE(QSKE, QSKE_LIMA_SP_L1),
+ PLUGIN_PROVIDE(QSKE, QSKE_LIMA_SP_L2),
+ PLUGIN_PROVIDE(QSKE, QSKE_LIMA_SP_L3),
+ PLUGIN_PROVIDE(QSKE, QSKE_LIMA_SP_L5)
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_oqs_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *oqs_plugin_create()
+{
+ private_oqs_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) 2018 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 oqs_p oqs
+ * @ingroup plugins
+ *
+ * @defgroup oqs_plugin oqs_plugin
+ * @{ @ingroup oqs_p
+ */
+
+#ifndef OQS_PLUGIN_H_
+#define OQS_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct oqs_plugin_t oqs_plugin_t;
+
+/**
+ * Plugin implementing quantum-safe crypto algorithms using the OQS library.
+ */
+struct oqs_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** OQS_PLUGIN_H_ @}*/
--- /dev/null
+/*
+ * Copyright (C) 2018 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * Based on public domain code by Erdem Alkim, Léo Ducas, Thomas Pöppelmann,
+ * and Peter Schwabe.
+ *
+ * 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 "oqs_qske.h"
+
+#include <utils/debug.h>
+
+#include <oqs/oqs.h>
+
+typedef struct private_oqs_qske_t private_oqs_qske_t;
+
+/**
+ * Private data of an oqs_qske_t object.
+ */
+struct private_oqs_qske_t {
+
+ /**
+ * Public oqs_qske_t interface.
+ */
+ oqs_qske_t public;
+
+ /**
+ * QSKE_MECHANISM;
+ */
+ qske_mechanism_t qske_mechanism;
+
+ /**
+ * Internal OQS_KEM object
+ */
+ OQS_KEM *kem;
+
+ /**
+ * Public Key
+ */
+ uint8_t *public_key;
+
+ /**
+ * Secret Key
+ */
+ uint8_t *secret_key;
+
+ /**
+ * Ciphertext
+ */
+ uint8_t *ciphertext;
+
+ /**
+ * Shared secret
+ */
+ uint8_t *shared_secret;
+
+};
+
+
+METHOD(qske_t, get_public_key, bool,
+ private_oqs_qske_t *this, chunk_t *value)
+{
+ OQS_STATUS rc;
+
+ if (!this->public_key)
+ {
+ this->public_key = malloc(this->kem->length_public_key);
+ this->secret_key = malloc(this->kem->length_secret_key);
+ rc = OQS_KEM_keypair(this->kem, this->public_key, this->secret_key);
+ if (rc != OQS_SUCCESS)
+ {
+ DBG1(DBG_LIB, "%N keypair generation failed",
+ qske_mechanism_names, this->qske_mechanism);
+ return FALSE;
+ }
+ }
+ *value = chunk_clone(chunk_create(this->public_key,
+ this->kem->length_public_key));
+ return TRUE;
+}
+
+METHOD(qske_t, get_ciphertext, bool,
+ private_oqs_qske_t *this, chunk_t *value)
+{
+ OQS_STATUS rc;
+
+ if (!this->ciphertext)
+ {
+ if (!this->public_key)
+ {
+ DBG1(DBG_LIB, "no public key available for %N encapsulation",
+ qske_mechanism_names, this->qske_mechanism);
+ return FALSE;
+ }
+ this->ciphertext = malloc(this->kem->length_ciphertext);
+ this->shared_secret = malloc(this->kem->length_shared_secret);
+ memset(this->shared_secret, 0x00, this->kem->length_shared_secret);
+ rc = OQS_KEM_encaps(this->kem, this->ciphertext, this->shared_secret,
+ this->public_key);
+ if (rc != OQS_SUCCESS)
+ {
+ DBG1(DBG_LIB, "%N encapsulation failed",
+ qske_mechanism_names, this->qske_mechanism);
+ return FALSE;
+ }
+ }
+ *value = chunk_clone(chunk_create(this->ciphertext,
+ this->kem->length_ciphertext));
+ return TRUE;
+}
+
+METHOD(qske_t, get_shared_secret, bool,
+ private_oqs_qske_t *this, chunk_t *secret)
+{
+ if (!this->shared_secret)
+ {
+ return FALSE;
+ }
+ *secret = chunk_clone(chunk_create(this->shared_secret,
+ this->kem->length_shared_secret));
+ return TRUE;
+}
+
+METHOD(qske_t, set_public_key, bool,
+ private_oqs_qske_t *this, chunk_t value)
+{
+ if (value.len != this->kem->length_public_key)
+ {
+ DBG1(DBG_LIB, "wrong %N public key size of %u bytes, %u bytes expected",
+ qske_mechanism_names, this->qske_mechanism, value.len,
+ this->kem->length_public_key);
+ return FALSE;
+ }
+ if (!this->public_key)
+ {
+ this->public_key = malloc(this->kem->length_public_key);
+ }
+ memcpy(this->public_key, value.ptr, value.len);
+
+ return TRUE;
+}
+
+METHOD(qske_t, set_ciphertext, bool,
+ private_oqs_qske_t *this, chunk_t value)
+{
+ OQS_STATUS rc;
+
+ if (!this->public_key)
+ {
+ DBG1(DBG_LIB, "no secret key available for %N decapsulation",
+ qske_mechanism_names, this->qske_mechanism);
+ return FALSE;
+ }
+
+ if (value.len != this->kem->length_ciphertext)
+ {
+ DBG1(DBG_LIB, "wrong %N ciphertext size of %u bytes, %u bytes expected",
+ qske_mechanism_names, this->qske_mechanism, value.len,
+ this->kem->length_ciphertext);
+ return FALSE;
+ }
+
+ if (!this->shared_secret)
+ {
+ this->shared_secret = malloc(this->kem->length_shared_secret);
+ }
+
+ rc = OQS_KEM_decaps(this->kem, this->shared_secret, value.ptr,
+ this->secret_key);
+ if (rc != OQS_SUCCESS)
+ {
+ DBG1(DBG_LIB, "%N decapsulation failed",
+ qske_mechanism_names, this->qske_mechanism);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+METHOD(qske_t, get_qske_mechanism, qske_mechanism_t,
+ private_oqs_qske_t *this)
+{
+ return this->qske_mechanism;
+}
+
+METHOD(qske_t, set_nist_drbg_mode, bool,
+ private_oqs_qske_t *this, bool enable, chunk_t seed)
+{
+ OQS_STATUS rc;
+
+ if (enable)
+ {
+ if (seed.len < 48)
+ {
+ DBG1(DBG_LIB, "not enough entropy input for NIST DRBG");
+ return FALSE;
+ }
+
+ rc = OQS_randombytes_switch_algorithm(OQS_RAND_alg_nist_kat);
+ if (rc != OQS_SUCCESS)
+ {
+ return FALSE;
+ }
+ OQS_randombytes_nist_kat_init(seed.ptr, NULL, 256);
+ }
+ else
+ {
+ rc = OQS_randombytes_switch_algorithm(OQS_RAND_alg_openssl);
+ if (rc != OQS_SUCCESS)
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+METHOD(qske_t, destroy, void,
+ private_oqs_qske_t *this)
+{
+ if (this->secret_key)
+ {
+ memwipe(this->secret_key, this->kem->length_secret_key);
+ free(this->secret_key);
+ }
+ if (this->shared_secret)
+ {
+ memwipe(this->shared_secret, this->kem->length_shared_secret);
+ free(this->shared_secret);
+ }
+ OQS_KEM_free(this->kem);
+ free(this->public_key);
+ free(this->ciphertext);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+oqs_qske_t *oqs_qske_create(qske_mechanism_t mechanism)
+{
+ private_oqs_qske_t *this;
+ char *kem_alg = NULL;
+ OQS_KEM *kem;
+
+ switch (mechanism)
+ {
+ case QSKE_NEWHOPE_L1:
+ kem_alg = OQS_KEM_alg_newhope_512_cca_kem;
+ break;
+ case QSKE_NEWHOPE_L5:
+ kem_alg = OQS_KEM_alg_newhope_1024_cca_kem;
+ break;
+ case QSKE_FRODO_AES_L1:
+ kem_alg = OQS_KEM_alg_frodokem_640_aes;
+ break;
+ case QSKE_FRODO_AES_L3:
+ kem_alg = OQS_KEM_alg_frodokem_976_aes;
+ break;
+ case QSKE_FRODO_SHAKE_L1:
+ kem_alg = OQS_KEM_alg_frodokem_640_cshake;
+ break;
+ case QSKE_FRODO_SHAKE_L3:
+ kem_alg = OQS_KEM_alg_frodokem_976_cshake;
+ break;
+ case QSKE_KYBER_L1:
+ kem_alg = OQS_KEM_alg_kyber512;
+ break;
+ case QSKE_KYBER_L3:
+ kem_alg = OQS_KEM_alg_kyber768;
+ break;
+ case QSKE_KYBER_L5:
+ kem_alg = OQS_KEM_alg_kyber1024;
+ break;
+ case QSKE_BIKE1_L1:
+ kem_alg = OQS_KEM_alg_bike1_l1;
+ break;
+ case QSKE_BIKE1_L3:
+ kem_alg = OQS_KEM_alg_bike1_l3;
+ break;
+ case QSKE_BIKE1_L5:
+ kem_alg = OQS_KEM_alg_bike1_l5;
+ break;
+ case QSKE_BIKE2_L1:
+ kem_alg = OQS_KEM_alg_bike2_l1;
+ break;
+ case QSKE_BIKE2_L3:
+ kem_alg = OQS_KEM_alg_bike2_l3;
+ break;
+ case QSKE_BIKE2_L5:
+ kem_alg = OQS_KEM_alg_bike2_l5;
+ break;
+ case QSKE_BIKE3_L1:
+ kem_alg = OQS_KEM_alg_bike3_l1;
+ break;
+ case QSKE_BIKE3_L3:
+ kem_alg = OQS_KEM_alg_bike3_l3;
+ break;
+ case QSKE_BIKE3_L5:
+ kem_alg = OQS_KEM_alg_bike3_l5;
+ break;
+ case QSKE_SIKE_L1:
+ kem_alg = OQS_KEM_alg_sike_p503;
+ break;
+ case QSKE_SIKE_L3:
+ kem_alg = OQS_KEM_alg_sike_p751;
+ break;
+ case QSKE_SABER_L1:
+ kem_alg = OQS_KEM_alg_saber_light_saber_kem;
+ break;
+ case QSKE_SABER_L3:
+ kem_alg = OQS_KEM_alg_saber_saber_kem;
+ break;
+ case QSKE_SABER_L5:
+ kem_alg = OQS_KEM_alg_saber_fire_saber_kem;
+ break;
+ case QSKE_LIMA_2P_L3:
+ kem_alg = OQS_KEM_alg_lima_2p_1024_cca_kem;
+ break;
+ case QSKE_LIMA_2P_L5:
+ kem_alg = OQS_KEM_alg_lima_2p_2048_cca_kem;
+ break;
+ case QSKE_LIMA_SP_L1:
+ kem_alg = OQS_KEM_alg_lima_sp_1018_cca_kem;
+ break;
+ case QSKE_LIMA_SP_L2:
+ kem_alg = OQS_KEM_alg_lima_sp_1306_cca_kem;
+ break;
+ case QSKE_LIMA_SP_L3:
+ kem_alg = OQS_KEM_alg_lima_sp_1822_cca_kem;
+ break;
+ case QSKE_LIMA_SP_L5:
+ kem_alg = OQS_KEM_alg_lima_sp_2062_cca_kem;
+ break;
+ default:
+ return NULL;
+ }
+
+ kem = OQS_KEM_new(kem_alg);
+ if (!kem)
+ {
+ DBG1(DBG_LIB, "OQS KEM '%s' not available", kem_alg);
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .qske = {
+ .get_qske_mechanism = _get_qske_mechanism,
+ .get_public_key = _get_public_key,
+ .set_public_key = _set_public_key,
+ .get_ciphertext = _get_ciphertext,
+ .set_ciphertext = _set_ciphertext,
+ .get_shared_secret = _get_shared_secret,
+ .set_nist_drbg_mode = _set_nist_drbg_mode,
+ .destroy = _destroy,
+ },
+ },
+ .qske_mechanism = mechanism,
+ .kem = kem,
+ );
+
+ return &this->public;
+}
--- /dev/null
+/*
+ * Copyright (C) 2018 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 oqs_qske oqs_qske
+ * @{ @ingroup oqs_p
+ */
+
+#ifndef OQS_QSKE_H_
+#define OQS_QSKE_H_
+
+typedef struct oqs_qske_t oqs_qske_t;
+
+#include <library.h>
+
+/**
+ * Quantum-safe key encapsulation implementation using the OQS_QSKE library
+ */
+struct oqs_qske_t {
+
+ /**
+ * Implements qske_t interface.
+ */
+ qske_t qske;
+};
+
+/**
+ * Creates a new oqs_qske_t object.
+ *
+ * @param mechanism QSKE mechanism number
+ * @return oqs_qske_t object, NULL if not supported
+ */
+oqs_qske_t *oqs_qske_create(qske_mechanism_t mechanism);
+
+#endif /** OQS_QSKE_H_ @}*/
+