]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
crypto: Support for QSKE mechanisms
authorAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 18 Jun 2018 15:43:11 +0000 (17:43 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 14 May 2019 08:44:18 +0000 (10:44 +0200)
A new transform type for Quantum-Safe Key Encapsulation (QSKE)
mechanisms is defined.

14 files changed:
src/libstrongswan/Android.mk
src/libstrongswan/Makefile.am
src/libstrongswan/crypto/crypto_factory.c
src/libstrongswan/crypto/crypto_factory.h
src/libstrongswan/crypto/crypto_tester.c
src/libstrongswan/crypto/crypto_tester.h
src/libstrongswan/crypto/proposal/proposal.c
src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
src/libstrongswan/crypto/qske_mechanism.c [new file with mode: 0644]
src/libstrongswan/crypto/qske_mechanism.h [new file with mode: 0644]
src/libstrongswan/crypto/transform.c
src/libstrongswan/crypto/transform.h
src/libstrongswan/plugins/plugin_feature.c
src/libstrongswan/plugins/plugin_feature.h

index fb7c62a8a8c595452950720e7a74dc6c0fe6367a..92324b43184ad7afd69f8be1109b14a4126907b9 100644 (file)
@@ -13,7 +13,7 @@ crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords_static.c \
 crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
 crypto/rngs/rng.c crypto/prf_plus.c crypto/signers/signer.c \
 crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
-crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
+crypto/diffie_hellman.c crypto/aead.c crypto/transform.c crypto/qske_mechanism.c \
 crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
 crypto/iv/iv_gen_null.c \
 crypto/xofs/xof.c crypto/xofs/xof_bitspender.c \
index 827e0adb27939b2923cd777694b0e42e7f446f24..4a416d2f579bb5d6795933e2a74a37882aba4230 100644 (file)
@@ -11,7 +11,7 @@ crypto/proposal/proposal_keywords.c crypto/proposal/proposal_keywords_static.c \
 crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
 crypto/rngs/rng.c crypto/prf_plus.c crypto/signers/signer.c \
 crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
-crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
+crypto/diffie_hellman.c crypto/aead.c crypto/transform.c crypto/qske_mechanism.c \
 crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
 crypto/iv/iv_gen_null.c \
 crypto/xofs/xof.c crypto/xofs/xof_bitspender.c \
@@ -68,7 +68,7 @@ library.h \
 asn1/asn1.h asn1/asn1_parser.h asn1/oid.h bio/bio_reader.h bio/bio_writer.h \
 collections/blocking_queue.h collections/enumerator.h collections/hashtable.h \
 collections/linked_list.h collections/array.h collections/dictionary.h \
-crypto/crypters/crypter.h crypto/hashers/hasher.h \
+crypto/crypters/crypter.h crypto/hashers/hasher.h crypto/qske_mechanism.h \
 crypto/hashers/hash_algorithm_set.h crypto/mac.h crypto/proposal/proposal.h \
 crypto/proposal/proposal_keywords.h crypto/proposal/proposal_keywords_static.h \
 crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/rngs/rng.h crypto/nonce_gen.h \
index 096bcbc9c6fa53385a5960eb22047e723226b8fc..e1f02d8854ef1fd1f4f8f0801991fdbbfabf92ac 100644 (file)
@@ -56,6 +56,7 @@ struct entry_t {
                rng_constructor_t create_rng;
                nonce_gen_constructor_t create_nonce_gen;
                dh_constructor_t create_dh;
+               qske_constructor_t create_qske;
                void *create;
        };
 };
@@ -117,6 +118,11 @@ struct private_crypto_factory_t {
         */
        linked_list_t *dhs;
 
+       /**
+        * registered QSKE mechanisms, as entry_t
+        */
+       linked_list_t *qskes;
+
        /**
         * test manager to test crypto algorithms
         */
@@ -438,6 +444,37 @@ METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
        return diffie_hellman;
 }
 
+METHOD(crypto_factory_t, create_qske, qske_t*,
+       private_crypto_factory_t *this, qske_mechanism_t mechanism)
+{
+       enumerator_t *enumerator;
+       entry_t *entry;
+       qske_t *qske = NULL;
+
+       this->lock->read_lock(this->lock);
+       enumerator = this->qskes->create_enumerator(this->qskes);
+       while (enumerator->enumerate(enumerator, &entry))
+       {
+               if (entry->algo == mechanism)
+               {
+                       if (this->test_on_create &&
+                               !this->tester->test_qske(this->tester, mechanism,
+                                                               entry->create_qske, NULL, default_plugin_name))
+                       {
+                               continue;
+                       }
+                       qske = entry->create_qske(mechanism);
+                       if (qske)
+                       {
+                               break;
+                       }
+               }
+       }
+       enumerator->destroy(enumerator);
+       this->lock->unlock(this->lock);
+       return qske;
+}
+
 /**
  * Insert an algorithm entry to a list
  *
@@ -811,6 +848,43 @@ METHOD(crypto_factory_t, remove_dh, void,
        this->lock->unlock(this->lock);
 }
 
+METHOD(crypto_factory_t, add_qske, bool,
+       private_crypto_factory_t *this, qske_mechanism_t mechanism,
+       const char *plugin_name, qske_constructor_t create)
+{
+       u_int speed = 0;
+
+       if (!this->test_on_add ||
+               this->tester->test_qske(this->tester, mechanism, create,
+                                                         this->bench ? &speed : NULL, plugin_name))
+       {
+               add_entry(this, this->qskes, mechanism, plugin_name, 0, create);
+               return TRUE;
+       }
+       this->test_failures++;
+       return FALSE;
+}
+
+METHOD(crypto_factory_t, remove_qske, void,
+       private_crypto_factory_t *this, qske_constructor_t create)
+{
+       entry_t *entry;
+       enumerator_t *enumerator;
+
+       this->lock->write_lock(this->lock);
+       enumerator = this->qskes->create_enumerator(this->qskes);
+       while (enumerator->enumerate(enumerator, &entry))
+       {
+               if (entry->create_qske == create)
+               {
+                       this->qskes->remove_at(this->qskes, enumerator);
+                       free(entry);
+               }
+       }
+       enumerator->destroy(enumerator);
+       this->lock->unlock(this->lock);
+}
+
 CALLBACK(entry_match, bool,
        entry_t *a, va_list args)
 {
@@ -1005,6 +1079,30 @@ METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*,
        return create_enumerator(this, this->dhs, dh_filter);
 }
 
+CALLBACK(qske_filter, bool,
+       void *n, enumerator_t *orig, va_list args)
+{
+       entry_t *entry;
+       qske_mechanism_t *algo;
+       const char **plugin_name;
+
+       VA_ARGS_VGET(args, algo, plugin_name);
+
+       if (orig->enumerate(orig, &entry))
+       {
+               *algo = entry->algo;
+               *plugin_name = entry->plugin_name;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+METHOD(crypto_factory_t, create_qske_enumerator, enumerator_t*,
+       private_crypto_factory_t *this)
+{
+       return create_enumerator(this, this->qskes, qske_filter);
+}
+
 CALLBACK(rng_filter, bool,
        void *n, enumerator_t *orig, va_list args)
 {
@@ -1072,6 +1170,8 @@ METHOD(crypto_factory_t, add_test_vector, void,
                        return this->tester->add_rng_vector(this->tester, vector);
                case DIFFIE_HELLMAN_GROUP:
                        return this->tester->add_dh_vector(this->tester, vector);
+               case QSKE_MECHANISM:
+                       return this->tester->add_qske_vector(this->tester, vector);
                default:
                        DBG1(DBG_LIB, "%N test vectors not supported, ignored",
                                 transform_type_names, type);
@@ -1137,6 +1237,10 @@ METHOD(enumerator_t, verify_enumerate, bool,
                        *valid = this->tester->test_dh(this->tester, entry->algo,
                                                        entry->create_dh, NULL, entry->plugin_name);
                        break;
+               case QSKE_MECHANISM:
+                       *valid = this->tester->test_qske(this->tester, entry->algo,
+                                                       entry->create_qske, NULL, entry->plugin_name);
+                       break;
                default:
                        return FALSE;
        }
@@ -1186,6 +1290,9 @@ METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*,
                case DIFFIE_HELLMAN_GROUP:
                        inner = this->dhs->create_enumerator(this->dhs);
                        break;
+               case QSKE_MECHANISM:
+                       inner = this->qskes->create_enumerator(this->qskes);
+                       break;
                default:
                        this->lock->unlock(this->lock);
                        return enumerator_create_empty();
@@ -1216,6 +1323,7 @@ METHOD(crypto_factory_t, destroy, void,
        this->rngs->destroy(this->rngs);
        this->nonce_gens->destroy(this->nonce_gens);
        this->dhs->destroy(this->dhs);
+       this->qskes->destroy(this->qskes);
        this->tester->destroy(this->tester);
        this->lock->destroy(this->lock);
        free(this);
@@ -1239,6 +1347,7 @@ crypto_factory_t *crypto_factory_create()
                        .create_rng = _create_rng,
                        .create_nonce_gen = _create_nonce_gen,
                        .create_dh = _create_dh,
+                       .create_qske = _create_qske,
                        .add_crypter = _add_crypter,
                        .remove_crypter = _remove_crypter,
                        .add_aead = _add_aead,
@@ -1257,6 +1366,8 @@ crypto_factory_t *crypto_factory_create()
                        .remove_nonce_gen = _remove_nonce_gen,
                        .add_dh = _add_dh,
                        .remove_dh = _remove_dh,
+                       .add_qske = _add_qske,
+                       .remove_qske = _remove_qske,
                        .create_crypter_enumerator = _create_crypter_enumerator,
                        .create_aead_enumerator = _create_aead_enumerator,
                        .create_signer_enumerator = _create_signer_enumerator,
@@ -1264,6 +1375,7 @@ crypto_factory_t *crypto_factory_create()
                        .create_prf_enumerator = _create_prf_enumerator,
                        .create_xof_enumerator = _create_xof_enumerator,
                        .create_dh_enumerator = _create_dh_enumerator,
+                       .create_qske_enumerator = _create_qske_enumerator,
                        .create_rng_enumerator = _create_rng_enumerator,
                        .create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
                        .add_test_vector = _add_test_vector,
@@ -1279,6 +1391,7 @@ crypto_factory_t *crypto_factory_create()
                .rngs = linked_list_create(),
                .nonce_gens = linked_list_create(),
                .dhs = linked_list_create(),
+               .qskes = linked_list_create(),
                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                .tester = crypto_tester_create(),
                .test_on_add = lib->settings->get_bool(lib->settings,
index 7f048c620f330876d338267d7d9e8e1a4cd01f50..b983fcab7637bef1fc822adf1f71e816a3780ee3 100644 (file)
@@ -35,6 +35,7 @@ typedef struct crypto_factory_t crypto_factory_t;
 #include <crypto/xofs/xof.h>
 #include <crypto/nonce_gen.h>
 #include <crypto/diffie_hellman.h>
+#include <crypto/qske_mechanism.h>
 #include <crypto/transform.h>
 
 #define CRYPTO_MAX_ALG_LINE          120   /* characters */
@@ -87,6 +88,11 @@ typedef nonce_gen_t* (*nonce_gen_constructor_t)();
  */
 typedef diffie_hellman_t* (*dh_constructor_t)(diffie_hellman_group_t group, ...);
 
+/**
+ * Constructor function for QSKE mechanisms
+ */
+typedef qske_t* (*qske_constructor_t)();
+
 /**
  * Handles crypto modules and creates instances.
  */
@@ -173,6 +179,14 @@ struct crypto_factory_t {
        diffie_hellman_t* (*create_dh)(crypto_factory_t *this,
                                                                   diffie_hellman_group_t group, ...);
 
+       /**
+        * Create a QSKE instance.
+        *
+        * @param mechanism             QSKE mechanism
+        * @return                              qske_t instance, NULL if not supported
+        */
+       qske_t* (*create_qske)(crypto_factory_t *this, qske_mechanism_t mechanism);
+
        /**
         * Register a crypter constructor.
         *
@@ -339,6 +353,24 @@ struct crypto_factory_t {
         */
        void (*remove_dh)(crypto_factory_t *this, dh_constructor_t create);
 
+       /**
+        * Register a QSKE constructor.
+        *
+        * @param mechanism             QSKE mechanism to constructor
+        * @param plugin_name   plugin that registered this algorithm
+        * @param create                constructor function for that algorithm
+        * @return                              TRUE if registered, FALSE if test vector failed
+        */
+       bool (*add_qske)(crypto_factory_t *this, qske_mechanism_t mechanism,
+                                  const char *plugin_name, qske_constructor_t create);
+
+       /**
+        * Unregister a QSKE constructor.
+        *
+        * @param create                constructor function to unregister
+        */
+       void (*remove_qske)(crypto_factory_t *this, qske_constructor_t create);
+
        /**
         * Create an enumerator over all registered crypter algorithms.
         *
@@ -388,6 +420,13 @@ struct crypto_factory_t {
         */
        enumerator_t* (*create_dh_enumerator)(crypto_factory_t *this);
 
+       /**
+        * Create an enumerator over all registered QSKE mechanisms
+        *
+        * @return                              enumerator over qske_mechamism_t, plugin
+        */
+       enumerator_t* (*create_qske_enumerator)(crypto_factory_t *this);
+
        /**
         * Create an enumerator over all registered random generators.
         *
index f0f64ce42ab23a097b7b918f2a866d2d79beb15f..8a5fb68ac6b24d26b6847da38982cc5671ebf31b 100644 (file)
@@ -77,6 +77,11 @@ struct private_crypto_tester_t {
         */
        linked_list_t *dh;
 
+       /**
+        * List of Quantum-Safe Key Encapsulation test vectors
+        */
+       linked_list_t *qske;
+
        /**
         * Is a test vector required to pass a test?
         */
@@ -1453,6 +1458,148 @@ failure:
        return !failed;
 }
 
+/**
+ * Benchmark a QSKE backend
+ */
+static u_int bench_qske(private_crypto_tester_t *this,
+                                               qske_mechanism_t mechanism, qske_constructor_t create)
+{
+       qske_t *a, *b;
+       struct timespec start;
+       chunk_t pk, ct, a_ss, b_ss;
+       u_int runs;
+
+       runs = 0;
+       start_timing(&start);
+       while (end_timing(&start) < this->bench_time)
+       {
+               a = create(mechanism);
+               b = create(mechanism);
+               if (!a || !b)
+                                       {
+                       DESTROY_IF(a);
+                       DESTROY_IF(b);
+                       return 0;
+               }
+               if (a->get_public_key(a, &pk)      &&
+                       b->set_public_key(b, pk)       &&
+                       b->get_ciphertext(b, &ct)      &&
+                       b->get_shared_secret(b, &b_ss) &&
+                       a->set_ciphertext(a, ct)       &&
+                       a->get_shared_secret(b, &a_ss) &&
+                       chunk_equals(a_ss, b_ss))
+               {
+                       runs++;
+               }
+               chunk_free(&pk);
+               chunk_free(&ct);
+               chunk_free(&a_ss);
+               chunk_free(&b_ss);
+               a->destroy(a);
+               b->destroy(b);
+       }
+       return runs;
+}
+
+METHOD(crypto_tester_t, test_qske, bool,
+       private_crypto_tester_t *this, qske_mechanism_t mechanism,
+       qske_constructor_t create, u_int *speed, const char *plugin_name)
+{
+       enumerator_t *enumerator;
+       chunk_t pk, ct, a_ss, b_ss;
+       qske_test_vector_t *v;
+       bool failed = FALSE;
+       u_int tested = 0;
+
+       enumerator = this->qske->create_enumerator(this->qske);
+       while (enumerator->enumerate(enumerator, &v))
+       {
+               qske_t *a, *b;
+
+               if (v->mechanism != mechanism)
+               {
+                       continue;
+               }
+
+               a = create(mechanism);
+               b = create(mechanism);
+               if (!a || !b)
+               {
+                       DESTROY_IF(a);
+                       DESTROY_IF(b);
+                       failed = TRUE;
+                       tested++;
+                       DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
+                                qske_mechanism_names, mechanism, plugin_name);
+                       break;
+               }
+               failed = TRUE;
+               tested++;
+
+               if (!a->set_nist_drbg_mode(a, TRUE, v->seed))
+               {
+                       goto failure;
+               }
+               if (!a->get_public_key(a, &pk) || !chunk_equals(pk, v->pk))
+               {
+                       goto failure;
+               }
+               if (!b->set_public_key(b, pk) || !b->get_ciphertext(b, &ct) ||
+                       !chunk_equals(ct, v->ct))
+               {
+                       goto failure;
+               }
+               if (!a->set_ciphertext(a, ct) || !a->get_shared_secret(a, &a_ss) ||
+                       !chunk_equals(a_ss, v->ss))
+               {
+                       goto failure;
+               }
+               if (!b->get_shared_secret(b, &b_ss) || !chunk_equals(b_ss, v->ss))
+               {
+                       goto failure;
+               }
+               failed = FALSE;
+
+failure:
+               a->set_nist_drbg_mode(a, FALSE, chunk_empty);
+               a->destroy(a);
+               b->destroy(b);
+               chunk_free(&pk);
+               chunk_free(&ct);
+               chunk_free(&a_ss);
+               chunk_free(&b_ss);
+               if (failed)
+               {
+                       DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
+                                qske_mechanism_names, mechanism, plugin_name, get_name(v));
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+       if (!tested)
+       {
+               DBG1(DBG_LIB, "%s %N[%s]: no test vectors found / untestable",
+                        this->required ? "disabled" : "enabled ",
+                        qske_mechanism_names, mechanism, plugin_name);
+               return !this->required;
+       }
+       if (!failed)
+       {
+               if (speed)
+               {
+                       *speed = bench_qske(this, mechanism, create);
+                       DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
+                                qske_mechanism_names, mechanism, plugin_name, tested, *speed);
+               }
+               else
+               {
+                       DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
+                                qske_mechanism_names, mechanism, plugin_name, tested);
+               }
+       }
+       return !failed;
+}
+
 METHOD(crypto_tester_t, add_crypter_vector, void,
        private_crypto_tester_t *this, crypter_test_vector_t *vector)
 {
@@ -1501,6 +1648,12 @@ METHOD(crypto_tester_t, add_dh_vector, void,
        this->dh->insert_last(this->dh, vector);
 }
 
+METHOD(crypto_tester_t, add_qske_vector, void,
+       private_crypto_tester_t *this, qske_test_vector_t *vector)
+{
+       this->qske->insert_last(this->qske, vector);
+}
+
 METHOD(crypto_tester_t, destroy, void,
        private_crypto_tester_t *this)
 {
@@ -1512,6 +1665,7 @@ METHOD(crypto_tester_t, destroy, void,
        this->xof->destroy(this->xof);
        this->rng->destroy(this->rng);
        this->dh->destroy(this->dh);
+       this->qske->destroy(this->qske);
        free(this);
 }
 
@@ -1532,6 +1686,7 @@ crypto_tester_t *crypto_tester_create()
                        .test_xof = _test_xof,
                        .test_rng = _test_rng,
                        .test_dh = _test_dh,
+                       .test_qske = _test_qske,
                        .add_crypter_vector = _add_crypter_vector,
                        .add_aead_vector = _add_aead_vector,
                        .add_signer_vector = _add_signer_vector,
@@ -1540,6 +1695,7 @@ crypto_tester_t *crypto_tester_create()
                        .add_xof_vector = _add_xof_vector,
                        .add_rng_vector = _add_rng_vector,
                        .add_dh_vector = _add_dh_vector,
+                       .add_qske_vector = _add_qske_vector,
                        .destroy = _destroy,
                },
                .crypter = linked_list_create(),
@@ -1550,6 +1706,7 @@ crypto_tester_t *crypto_tester_create()
                .xof = linked_list_create(),
                .rng = linked_list_create(),
                .dh = linked_list_create(),
+               .qske = linked_list_create(),
 
                .required = lib->settings->get_bool(lib->settings,
                                                                "%s.crypto_test.required", FALSE, lib->ns),
index 4309295952f5f8b908582dd6f42bff358e813fa5..adb53f84d47af4e158b6cfe6fd43792f03606bcb 100644 (file)
@@ -33,6 +33,7 @@ typedef struct prf_test_vector_t prf_test_vector_t;
 typedef struct xof_test_vector_t xof_test_vector_t;
 typedef struct rng_test_vector_t rng_test_vector_t;
 typedef struct dh_test_vector_t dh_test_vector_t;
+typedef struct qske_test_vector_t qske_test_vector_t;
 
 struct crypter_test_vector_t {
        /** encryption algorithm this vector tests */
@@ -165,6 +166,21 @@ struct dh_test_vector_t {
        size_t shared_len;
 };
 
+struct qske_test_vector_t {
+       /** QSKE mechanism to test */
+       qske_mechanism_t mechanism;
+       /** test vector number */
+       int count;
+       /** seed for NIST DRBG */
+       chunk_t seed;
+       /** public key */
+       chunk_t pk;
+       /** ciphertext */
+       chunk_t ct;
+       /*s* shared secret */
+       chunk_t ss;
+};
+
 /**
  * Cryptographic primitive testing framework.
  */
@@ -263,7 +279,17 @@ struct crypto_tester_t {
        bool (*test_dh)(crypto_tester_t *this, diffie_hellman_group_t group,
                                        dh_constructor_t create,
                                        u_int *speed, const char *plugin_name);
-
+       /**
+        * Test a Quantum-Safe Key Encapsulation implementation.
+        *
+        * @param mechanism             mechanism to test
+        * @param create                constructor function for the QSKE backend
+        * @param speed                 speeed test result, NULL to omit
+        * @return                              TRUE if test passed
+        */
+       bool (*test_qske)(crypto_tester_t *this, qske_mechanism_t mechanism,
+                                       qske_constructor_t create,
+                                       u_int *speed, const char *plugin_name);
        /**
         * Add a test vector to test a crypter.
         *
@@ -320,6 +346,13 @@ struct crypto_tester_t {
         */
        void (*add_dh_vector)(crypto_tester_t *this, dh_test_vector_t *vector);
 
+       /**
+        * Add a test vector to test a QSKE backend.
+        *
+        * @param vector                pointer to test vector
+        */
+       void (*add_qske_vector)(crypto_tester_t *this, qske_test_vector_t *vector);
+
        /**
         * Destroy a crypto_tester_t.
         */
index 952608997485a2e3435d8246fcc5430178918072..3ca78c92f5d247fafcd31c0ff6c2d885402f19fa 100644 (file)
@@ -984,6 +984,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
        integrity_algorithm_t integrity;
        pseudo_random_function_t prf;
        diffie_hellman_group_t group;
+       qske_mechanism_t mechanism;
        const char *plugin_name;
 
        if (aead)
@@ -1237,6 +1238,50 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
        }
        enumerator->destroy(enumerator);
 
+       /* Round 1 adds QSKE mechanisms with at least 128 bit security strength */
+       enumerator = lib->crypto->create_qske_enumerator(lib->crypto);
+       while (enumerator->enumerate(enumerator, &mechanism, &plugin_name))
+       {
+               switch (mechanism)
+               {
+                       case QSKE_NEWHOPE:
+                       case QSKE_NEWHOPE_L1:
+                       case QSKE_NEWHOPE_L5:
+                       case QSKE_FRODO_AES_L1:
+                       case QSKE_FRODO_AES_L3:
+                       case QSKE_FRODO_SHAKE_L1:
+                       case QSKE_FRODO_SHAKE_L3:
+                       case QSKE_KYBER_L1:
+                       case QSKE_KYBER_L3:
+                       case QSKE_KYBER_L5:
+                       case QSKE_BIKE1_L1:
+                       case QSKE_BIKE1_L3:
+                       case QSKE_BIKE1_L5:
+                       case QSKE_BIKE2_L1:
+                       case QSKE_BIKE2_L3:
+                       case QSKE_BIKE2_L5:
+                       case QSKE_BIKE3_L1:
+                       case QSKE_BIKE3_L3:
+                       case QSKE_BIKE3_L5:
+                       case QSKE_SIKE_L1:
+                       case QSKE_SIKE_L3:
+                       case QSKE_SABER_L1:
+                       case QSKE_SABER_L3:
+                       case QSKE_SABER_L5:
+                       case QSKE_LIMA_2P_L3:
+                       case QSKE_LIMA_2P_L5:
+                       case QSKE_LIMA_SP_L1:
+                       case QSKE_LIMA_SP_L2:
+                       case QSKE_LIMA_SP_L3:
+                       case QSKE_LIMA_SP_L5:
+                               add_algorithm(this, QSKE_MECHANISM, mechanism, 0);
+                               break;
+                       default:
+                               break;
+               }
+       }
+       enumerator->destroy(enumerator);
+
        return TRUE;
 }
 
index b214a9edf5c0abde4589c17bc25960e9f8b0be7f..38b25994a42937e85360f92e6cac8947ff4f4aed 100644 (file)
@@ -20,6 +20,7 @@
 #include <crypto/crypters/crypter.h>
 #include <crypto/signers/signer.h>
 #include <crypto/diffie_hellman.h>
+#include <crypto/qske_mechanism.h>
 
 %}
 struct proposal_token {
@@ -173,3 +174,33 @@ ntru256,          DIFFIE_HELLMAN_GROUP, NTRU_256_BIT,              0
 newhope128,       DIFFIE_HELLMAN_GROUP, NH_128_BIT,                0
 noesn,            EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS,   0
 esn,              EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS,      0
+qskenewhope,      QSKE_MECHANISM, QSKE_NEWHOPE,                    0
+qskenewhope1,     QSKE_MECHANISM, QSKE_NEWHOPE_L1,                 0
+qskenewhope5,     QSKE_MECHANISM, QSKE_NEWHOPE_L5,                 0
+qskefrodoa1,      QSKE_MECHANISM, QSKE_FRODO_AES_L1,               0
+qskefrodoa3,      QSKE_MECHANISM, QSKE_FRODO_AES_L3,               0
+qskefrodos1,      QSKE_MECHANISM, QSKE_FRODO_SHAKE_L1,             0
+qskefrodos3,      QSKE_MECHANISM, QSKE_FRODO_SHAKE_L3,             0
+qskekyber1,       QSKE_MECHANISM, QSKE_KYBER_L1,                   0
+qskekyber3,       QSKE_MECHANISM, QSKE_KYBER_L3,                   0
+qskekyber5,       QSKE_MECHANISM, QSKE_KYBER_L5,                   0
+qskebike11,       QSKE_MECHANISM, QSKE_BIKE1_L1,                   0
+qskebike13,       QSKE_MECHANISM, QSKE_BIKE1_L3,                   0
+qskebike15,       QSKE_MECHANISM, QSKE_BIKE1_L5,                   0
+qskebike21,       QSKE_MECHANISM, QSKE_BIKE2_L1,                   0
+qskebike23,       QSKE_MECHANISM, QSKE_BIKE2_L3,                   0
+qskebike25,       QSKE_MECHANISM, QSKE_BIKE2_L5,                   0
+qskebike31,       QSKE_MECHANISM, QSKE_BIKE3_L1,                   0
+qskebike33,       QSKE_MECHANISM, QSKE_BIKE3_L3,                   0
+qskebike35,       QSKE_MECHANISM, QSKE_BIKE3_L5,                   0
+qskesike1,        QSKE_MECHANISM, QSKE_SIKE_L1,                    0
+qskesike3,        QSKE_MECHANISM, QSKE_SIKE_L3,                    0
+qskesaber1,       QSKE_MECHANISM, QSKE_SABER_L1,                   0
+qskesaber3,       QSKE_MECHANISM, QSKE_SABER_L3,                   0
+qskesaber5,       QSKE_MECHANISM, QSKE_SABER_L5,                   0
+qskelima2p3,      QSKE_MECHANISM, QSKE_LIMA_2P_L3,                 0
+qskelima2p5,      QSKE_MECHANISM, QSKE_LIMA_2P_L5,                 0
+qskelimasp1,      QSKE_MECHANISM, QSKE_LIMA_SP_L1,                 0
+qskelimasp2,      QSKE_MECHANISM, QSKE_LIMA_SP_L2,                 0
+qskelimasp3,      QSKE_MECHANISM, QSKE_LIMA_SP_L3,                 0
+qskelimasp5,      QSKE_MECHANISM, QSKE_LIMA_SP_L5,                 0
diff --git a/src/libstrongswan/crypto/qske_mechanism.c b/src/libstrongswan/crypto/qske_mechanism.c
new file mode 100644 (file)
index 0000000..b3ef470
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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 "qske_mechanism.h"
+
+ENUM(qske_mechanism_names, QSKE_NONE, QSKE_FRODO,
+       "QSKE_NONE",
+       "QSKE_NEWHOPE",
+       "QSKE_NEWHOPE_L1",
+       "QSKE_NEWHOPE_L5",
+       "QSKE_FRODO_AES_L1",
+       "QSKE_FRODO_AES_L3",
+       "QSKE_FRODO_SHAKE_L1",
+       "QSKE_FRODO_SHAKE_L3",
+       "QSKE_KYBER_L1",
+       "QSKE_KYBER_L3",
+       "QSKE_KYBER_L5",
+       "QSKE_BIKE1_L1",
+       "QSKE_BIKE1_L3",
+       "QSKE_BIKE1_L5",
+       "QSKE_BIKE2_L1",
+       "QSKE_BIKE2_L3",
+       "QSKE_BIKE2_L5",
+       "QSKE_BIKE3_L1",
+       "QSKE_BIKE3_L3",
+       "QSKE_BIKE3_L5",
+       "QSKE_SIKE_L1",
+       "QSKE_SIKE_L3",
+       "QSKE_SABER_L1",
+       "QSKE_SABER_L3",
+       "QSKE_SABER_L5",
+       "QSKE_LIMA_2P_L3",
+       "QSKE_LIMA_2P_L5",
+       "QSKE_LIMA_SP_L1",
+       "QSKE_LIMA_SP_L2",
+       "QSKE_LIMA_SP_L3",
+       "QSKE_LIMA_SP_L5"
+);
diff --git a/src/libstrongswan/crypto/qske_mechanism.h b/src/libstrongswan/crypto/qske_mechanism.h
new file mode 100644 (file)
index 0000000..e4d556c
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2018 Tobias Brunner
+ * 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 qske_mechanism qske_mechanism
+ * @{ @ingroup crypto
+ */
+
+#ifndef QSKE_MECHANISM_H_
+#define QSKE_MECHANISM_H_
+
+typedef enum qske_mechanism_t qske_mechanism_t;
+typedef struct qske_t qske_t;
+typedef struct qske_params_t qske_params_t;
+
+#include <library.h>
+
+/**
+ * Quantum-Safe Key Encapsulation Mechanism
+ *
+ * KEM Candidates from the NIST Post-Quantum Cryptograpy Round 1 Submissions
+ */
+enum qske_mechanism_t {
+       QSKE_NONE            =  0,
+       QSKE_NEWHOPE         =  1,
+       QSKE_NEWHOPE_L1      =  2,
+       QSKE_NEWHOPE_L5      =  3,
+       QSKE_FRODO_AES_L1    =  4,
+       QSKE_FRODO_AES_L3    =  5,
+       QSKE_FRODO_SHAKE_L1  =  6,
+       QSKE_FRODO_SHAKE_L3  =  7,
+       QSKE_KYBER_L1        =  8,
+       QSKE_KYBER_L3        =  9,
+       QSKE_KYBER_L5        = 10,
+       QSKE_BIKE1_L1        = 11,
+       QSKE_BIKE1_L3        = 12,
+       QSKE_BIKE1_L5        = 13,
+       QSKE_BIKE2_L1        = 14,
+       QSKE_BIKE2_L3        = 15,
+       QSKE_BIKE2_L5        = 16,
+       QSKE_BIKE3_L1        = 17,
+       QSKE_BIKE3_L3        = 18,
+       QSKE_BIKE3_L5        = 19,
+       QSKE_SIKE_L1         = 20,
+       QSKE_SIKE_L3         = 21,
+       QSKE_SABER_L1        = 22,
+       QSKE_SABER_L3        = 23,
+       QSKE_SABER_L5        = 24,
+       QSKE_LIMA_2P_L3      = 25,
+       QSKE_LIMA_2P_L5      = 26,
+       QSKE_LIMA_SP_L1      = 27,
+       QSKE_LIMA_SP_L2      = 28,
+       QSKE_LIMA_SP_L3      = 29,
+       QSKE_LIMA_SP_L5      = 30
+};
+
+/**
+ * enum name for qske_mechanism_t.
+ */
+extern enum_name_t *qske_mechanism_names;
+
+/**
+ * Implementation of a Quantum-Safe Key Encapsulation Mechanism
+ */
+struct qske_t {
+
+       /**
+        * Get the QSKE mechanism used.
+        *
+        * @return                      QSKE mechanism
+        */
+       qske_mechanism_t (*get_qske_mechanism) (qske_t *this);
+
+       /**
+        * Get the transport-encpded QSKE public key.
+        *
+        * @param value                 Transport-encoded QSKE public key (allocated)
+        * @return                              TRUE if encoding successful
+        */
+       bool (*get_public_key) (qske_t *this, chunk_t *value)
+               __attribute__((warn_unused_result));
+
+       /**
+        * Set the transport-encoded QSKE public key
+        *
+        * @param value                 Transport-encoded QSKE public key
+        * @return                              TRUE if decoding successful
+        */
+       bool (*set_public_key) (qske_t *this, chunk_t value)
+               __attribute__((warn_unused_result));
+
+       /**
+        * Get the transport-encoded encrypted shared secret
+        *
+        * @param value                 Transport-encode encrypted shared secret (allocated)
+        * @return                              TRUE if shared secret successfully encrypted
+        */
+       bool (*get_ciphertext) (qske_t *this, chunk_t *value)
+               __attribute__((warn_unused_result));
+
+       /**
+        * Set the transport-encoded encrypted shared secret and decrypt it
+        *
+        * @param value                 Transport-encoded encrypted shared secret
+        * @return                              TRUE if shared secret successfully decrypted
+        */
+       bool (*set_ciphertext) (qske_t *this, chunk_t value)
+               __attribute__((warn_unused_result));
+
+       /**
+        * Get the shared secret
+        *
+        * @param secret                Shared secret (allocated)
+        * @return                              TRUE if shared secret successfully retrieved
+        */
+       bool (*get_shared_secret) (qske_t *this, chunk_t *secret)
+               __attribute__((warn_unused_result));
+
+       /**
+        * Set the internal RNG to deterministic NIST DRGB test mode
+        * Use for testing purposes only!
+        *
+        * @param enable                if TRUE enable NIST DRBG mode, else revert to RNG
+        * @param seed                  Seed for initializing NIST DRBG
+        * @return                              TRUE if NIST DRBG test mode available
+        */
+       bool (*set_nist_drbg_mode) (qske_t *this, bool enable, chunk_t seed);
+
+       /**
+        * Destroys a qske_t object.
+        */
+       void (*destroy) (qske_t *this);
+};
+
+#endif /** QSKE_MECHANISM_H_ @}*/
index 77a57f52708207aa7f5ec017ba50bc973e0c9a2d..84fb4508f5e05310aeaa02329bac0e3eb327d85c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006-2009 Martin Willi
+ * Copyright (C) 2018 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -16,6 +17,7 @@
 #include <crypto/transform.h>
 #include <crypto/hashers/hasher.h>
 #include <crypto/rngs/rng.h>
+#include <crypto/qske_mechanism.h>
 
 ENUM_BEGIN(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS,
        "ENCRYPTION_ALGORITHM",
@@ -23,8 +25,9 @@ ENUM_BEGIN(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS
        "INTEGRITY_ALGORITHM",
        "DIFFIE_HELLMAN_GROUP",
        "EXTENDED_SEQUENCE_NUMBERS");
-ENUM_NEXT(transform_type_names, HASH_ALGORITHM, EXTENDED_OUTPUT_FUNCTION,
-                 EXTENDED_SEQUENCE_NUMBERS,
+ENUM_NEXT(transform_type_names, QSKE_MECHANISM,
+                 EXTENDED_OUTPUT_FUNCTION, EXTENDED_SEQUENCE_NUMBERS,
+       "QSKE_MECHANISM",
        "HASH_ALGORITHM",
        "RANDOM_NUMBER_GENERATOR",
        "AEAD_ALGORITHM",
@@ -65,6 +68,8 @@ enum_name_t* transform_get_enum_names(transform_type_t type)
                        return ext_out_function_names;
                case COMPRESSION_ALGORITHM:
                        break;
+               case QSKE_MECHANISM:
+                       return qske_mechanism_names;
        }
        return NULL;
 }
index 63881b3730158c9b2b4bd4e07e19c2e6868c0f58..b8dface297e837df867070d9369b6cd3a0d3b311 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006-2009 Martin Willi
+ * Copyright (C) 2018 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -34,6 +35,7 @@ enum transform_type_t {
        INTEGRITY_ALGORITHM = 3,
        DIFFIE_HELLMAN_GROUP = 4,
        EXTENDED_SEQUENCE_NUMBERS = 5,
+       QSKE_MECHANISM = 255,
        HASH_ALGORITHM = 256,
        RANDOM_NUMBER_GENERATOR = 257,
        AEAD_ALGORITHM = 258,
index 844698bd251ff6937db2245839cfd8a99d1855dd..18aee68cce2c660106c2ecf0257a144c803a8e0a 100644 (file)
@@ -32,6 +32,7 @@ ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM,
        "PRF",
        "XOF",
        "DH",
+       "QSKE"
        "RNG",
        "NONCE_GEN",
        "PRIVKEY",
@@ -94,6 +95,9 @@ uint32_t plugin_feature_hash(plugin_feature_t *feature)
                case FEATURE_DH:
                        data = chunk_from_thing(feature->arg.dh_group);
                        break;
+               case FEATURE_QSKE:
+                       data = chunk_from_thing(feature->arg.qske_mechanism);
+                       break;
                case FEATURE_PRIVKEY:
                        data = chunk_from_thing(feature->arg.privkey);
                        break;
@@ -168,6 +172,8 @@ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
                                return a->arg.xof == b->arg.xof;
                        case FEATURE_DH:
                                return a->arg.dh_group == b->arg.dh_group;
+                       case FEATURE_QSKE:
+                               return a->arg.qske_mechanism == b->arg.qske_mechanism;
                        case FEATURE_RNG:
                                return a->arg.rng_quality <= b->arg.rng_quality;
                        case FEATURE_NONCE_GEN:
@@ -226,6 +232,7 @@ bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b)
                        case FEATURE_PRF:
                        case FEATURE_XOF:
                        case FEATURE_DH:
+                       case FEATURE_QSKE:
                        case FEATURE_NONCE_GEN:
                        case FEATURE_RESOLVER:
                        case FEATURE_PRIVKEY:
@@ -326,6 +333,13 @@ char* plugin_feature_get_string(plugin_feature_t *feature)
                                return str;
                        }
                        break;
+               case FEATURE_QSKE:
+                       if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
+                                       qske_mechanism_names, feature->arg.qske_mechanism) > 0)
+                       {
+                               return str;
+                       }
+                       break;
                case FEATURE_RNG:
                        if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
                                        rng_quality_names, feature->arg.rng_quality) > 0)
@@ -487,6 +501,10 @@ bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
                        lib->crypto->add_dh(lib->crypto, feature->arg.dh_group,
                                                                name, reg->arg.reg.f);
                        break;
+               case FEATURE_QSKE:
+                       lib->crypto->add_qske(lib->crypto, feature->arg.qske_mechanism,
+                                                               name, reg->arg.reg.f);
+                       break;
                case FEATURE_RNG:
                        lib->crypto->add_rng(lib->crypto, feature->arg.rng_quality,
                                                                name, reg->arg.reg.f);
@@ -576,6 +594,9 @@ bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature,
                case FEATURE_DH:
                        lib->crypto->remove_dh(lib->crypto, reg->arg.reg.f);
                        break;
+               case FEATURE_QSKE:
+                       lib->crypto->remove_qske(lib->crypto, reg->arg.reg.f);
+                       break;
                case FEATURE_RNG:
                        lib->crypto->remove_rng(lib->crypto, reg->arg.reg.f);
                        break;
index d3c2df7f768e33a128f85c734238cabb305712f6..76ef675d535bd5182c1ec50a332e5ffc61aed0f7 100644 (file)
@@ -114,6 +114,8 @@ struct plugin_feature_t {
                FEATURE_XOF,
                /** diffie_hellman_t */
                FEATURE_DH,
+               /** qske_t */
+               FEATURE_QSKE,
                /** rng_t */
                FEATURE_RNG,
                /** nonce_gen_t */
@@ -179,6 +181,8 @@ struct plugin_feature_t {
                hash_algorithm_t hasher;
                /** FEATURE_DH */
                diffie_hellman_group_t dh_group;
+               /** FEATURE_QSKE */
+               qske_mechanism_t qske_mechanism;
                /** FEATURE_RNG */
                rng_quality_t rng_quality;
                /** FEATURE_PRIVKEY */
@@ -284,6 +288,7 @@ struct plugin_feature_t {
 #define _PLUGIN_FEATURE_PRF(kind, alg)                                         __PLUGIN_FEATURE(kind, PRF, .prf = alg)
 #define _PLUGIN_FEATURE_XOF(kind, alg)                                         __PLUGIN_FEATURE(kind, XOF, .xof = alg)
 #define _PLUGIN_FEATURE_DH(kind, group)                                                __PLUGIN_FEATURE(kind, DH, .dh_group = group)
+#define _PLUGIN_FEATURE_QSKE(kind, mechanism)                          __PLUGIN_FEATURE(kind, QSKE, .qske_mechanism = mechanism)
 #define _PLUGIN_FEATURE_RNG(kind, quality)                                     __PLUGIN_FEATURE(kind, RNG, .rng_quality = quality)
 #define _PLUGIN_FEATURE_NONCE_GEN(kind, ...)                           __PLUGIN_FEATURE(kind, NONCE_GEN, .custom = NULL)
 #define _PLUGIN_FEATURE_PRIVKEY(kind, type)                                    __PLUGIN_FEATURE(kind, PRIVKEY, .privkey = type)
@@ -317,6 +322,7 @@ struct plugin_feature_t {
 #define _PLUGIN_FEATURE_REGISTER_PRF(type, f)                          __PLUGIN_FEATURE_REGISTER(type, f)
 #define _PLUGIN_FEATURE_REGISTER_XOF(type, f)                          __PLUGIN_FEATURE_REGISTER(type, f)
 #define _PLUGIN_FEATURE_REGISTER_DH(type, f)                           __PLUGIN_FEATURE_REGISTER(type, f)
+#define _PLUGIN_FEATURE_REGISTER_QSKE(type, f)                         __PLUGIN_FEATURE_REGISTER(type, f)
 #define _PLUGIN_FEATURE_REGISTER_RNG(type, f)                          __PLUGIN_FEATURE_REGISTER(type, f)
 #define _PLUGIN_FEATURE_REGISTER_NONCE_GEN(type, f)                    __PLUGIN_FEATURE_REGISTER(type, f)
 #define _PLUGIN_FEATURE_REGISTER_PRIVKEY(type, f, final)       __PLUGIN_FEATURE_REGISTER_BUILDER(type, f, final)