]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
oqs: Created QSKE plugin based on OQS library
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 27 Jun 2018 11:22:58 +0000 (13:22 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 14 May 2019 08:44:18 +0000 (10:44 +0200)
configure.ac
scripts/test.sh
src/libstrongswan/Makefile.am
src/libstrongswan/crypto/qske_mechanism.c
src/libstrongswan/plugins/oqs/Makefile.am [new file with mode: 0644]
src/libstrongswan/plugins/oqs/oqs_plugin.c [new file with mode: 0644]
src/libstrongswan/plugins/oqs/oqs_plugin.h [new file with mode: 0644]
src/libstrongswan/plugins/oqs/oqs_qske.c [new file with mode: 0644]
src/libstrongswan/plugins/oqs/oqs_qske.h [new file with mode: 0644]

index d8f2b37db623ad642d0b59260eaf9bfa8c91e4d1..97664df26c950afb1c28b94714682f21ad9b3065 100644 (file)
@@ -143,6 +143,7 @@ ARG_DISBL_SET([md5],            [disable MD5 software implementation plugin.])
 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.])
@@ -1166,6 +1167,14 @@ if test x$botan = xtrue; then
        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!])])
@@ -1437,6 +1446,7 @@ ADD_PLUGIN([gcm],                  [s charon scripts nm cmd])
 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])
@@ -1605,6 +1615,7 @@ AM_CONDITIONAL(USE_AF_ALG, test x$af_alg = xtrue)
 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
@@ -1889,6 +1900,7 @@ AC_CONFIG_FILES([
        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
index ba5fd6da8ef19187aba27cb4fa440cac627c7c0a..90d2a5fd66dd3d8980b50e859109a582b21ce818 100755 (executable)
@@ -186,6 +186,8 @@ all|coverage|sonarcloud)
                        --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
index 3d351efb0768636f2b6e1634fb4be43a5c306dc2..d44e02ffbe72c0c45fa63c4046a0732cb5c5bafd 100644 (file)
@@ -670,6 +670,13 @@ if MONOLITHIC
 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
index b3ef47041326a308a968f03f0cc311e6b7974614..5e28a558074cc8e3bee4b7870c814aa6c72ae97a 100644 (file)
@@ -15,7 +15,7 @@
 
 #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",
diff --git a/src/libstrongswan/plugins/oqs/Makefile.am b/src/libstrongswan/plugins/oqs/Makefile.am
new file mode 100644 (file)
index 0000000..3e377f4
--- /dev/null
@@ -0,0 +1,27 @@
+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
diff --git a/src/libstrongswan/plugins/oqs/oqs_plugin.c b/src/libstrongswan/plugins/oqs/oqs_plugin.c
new file mode 100644 (file)
index 0000000..4b38ab4
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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;
+}
+
diff --git a/src/libstrongswan/plugins/oqs/oqs_plugin.h b/src/libstrongswan/plugins/oqs/oqs_plugin.h
new file mode 100644 (file)
index 0000000..88c3677
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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_ @}*/
diff --git a/src/libstrongswan/plugins/oqs/oqs_qske.c b/src/libstrongswan/plugins/oqs/oqs_qske.c
new file mode 100644 (file)
index 0000000..725630b
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * 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;
+}
diff --git a/src/libstrongswan/plugins/oqs/oqs_qske.h b/src/libstrongswan/plugins/oqs/oqs_qske.h
new file mode 100644 (file)
index 0000000..5479b78
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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_ @}*/
+