]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
charon-tkm: Delegate encryption/decryption of IKE traffic to TKM
authorStefan Berghofer <stefan.berghofer@secunet.com>
Tue, 23 Jul 2019 10:42:26 +0000 (12:42 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 17 Jun 2021 07:53:51 +0000 (09:53 +0200)
Co-authored-by: Tobias Brunner <tobias@strongswan.org>
src/charon-tkm/src/tkm/tkm_aead.c [new file with mode: 0644]
src/charon-tkm/src/tkm/tkm_aead.h [new file with mode: 0644]
src/charon-tkm/src/tkm/tkm_keymat.c
testing/scripts/recipes/004_spark-crypto.mk [new file with mode: 0644]
testing/scripts/recipes/006_tkm-rpc.mk
testing/scripts/recipes/010_tkm.mk

diff --git a/src/charon-tkm/src/tkm/tkm_aead.c b/src/charon-tkm/src/tkm/tkm_aead.c
new file mode 100644 (file)
index 0000000..f89d290
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2020 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * Copyright (C) 2020 secunet Security Networks AG
+ * Copyright (C) 2020 Stefan Berghofer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <errno.h>
+
+#include <crypto/iv/iv_gen.h>
+#include <tkm/constants.h>
+#include <tkm/client.h>
+
+#include "tkm_aead.h"
+#include "tkm_utils.h"
+
+typedef struct private_aead_t private_aead_t;
+
+/**
+ * AEAD implementation using TKM
+ */
+struct private_aead_t {
+
+       /**
+        * Public interface
+        * */
+       aead_t public;
+
+       /**
+        * Internal IV generator for TKM
+        */
+       iv_gen_t iv_gen;
+
+       /**
+        * ISA context id
+        */
+       isa_id_type isa_ctx_id;
+
+       /**
+        * Block length of encryption algorithm
+        */
+       block_len_type block_len;
+
+       /**
+        * Length of integrity check value
+        */
+       icv_len_type icv_len;
+
+       /**
+        * Length of initialization vector
+        */
+       iv_len_type iv_len;
+};
+
+METHOD(iv_gen_t, get_iv, bool,
+       iv_gen_t *this, uint64_t seq, size_t size, uint8_t *buffer)
+{
+       return TRUE;
+}
+
+METHOD(iv_gen_t, allocate_iv, bool,
+       iv_gen_t *this, uint64_t seq, size_t size, chunk_t *chunk)
+{
+       *chunk = chunk_alloc(size);
+       return get_iv(this, seq, chunk->len, chunk->ptr);
+}
+
+METHOD(aead_t, encrypt, bool,
+       private_aead_t *this, chunk_t plain, chunk_t assoc,
+       chunk_t iv, chunk_t *encrypted)
+{
+       aad_plain_type aad_plain;
+       iv_encrypted_icv_type iv_encrypted_icv;
+       result_type res;
+
+       aad_plain = (aad_plain_type){
+               .size = assoc.len + plain.len,
+       };
+       if (aad_plain.size > sizeof(aad_plain.data))
+       {
+               DBG1(DBG_IKE, "%u exceeds buffer size %u, encryption failed (isa: "
+                        "%llu)", aad_plain.size, sizeof(aad_plain.data), this->isa_ctx_id);
+               return FALSE;
+       }
+       memcpy(aad_plain.data, assoc.ptr, assoc.len);
+       memcpy(aad_plain.data + assoc.len, plain.ptr, plain.len);
+
+       res = ike_isa_encrypt(this->isa_ctx_id, assoc.len, aad_plain,
+                                                 &iv_encrypted_icv);
+       if (res != TKM_OK)
+       {
+               DBG1(DBG_IKE, "encryption failed (isa: %llu)", this->isa_ctx_id);
+               return FALSE;
+       }
+
+       if (encrypted)
+       {
+               sequence_to_chunk(iv_encrypted_icv.data, iv_encrypted_icv.size,
+                                                 encrypted);
+       }
+       else
+       {
+               memcpy(plain.ptr, iv_encrypted_icv.data + iv.len,
+                          iv_encrypted_icv.size - iv.len);
+       }
+       memcpy(iv.ptr, iv_encrypted_icv.data, iv.len);
+       return TRUE;
+}
+
+METHOD(aead_t, decrypt, bool,
+       private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
+       chunk_t *plain)
+{
+       aad_iv_encrypted_icv_type aad_iv_encrypted_icv;
+       decrypted_type decrypted;
+       result_type res;
+
+       aad_iv_encrypted_icv = (aad_iv_encrypted_icv_type){
+               .size = assoc.len + iv.len + encrypted.len,
+       };
+       if (aad_iv_encrypted_icv.size > sizeof(aad_iv_encrypted_icv.data))
+       {
+               DBG1(DBG_IKE, "%u exceeds buffer size %u, decryption failed (isa: "
+                        "%llu)", aad_iv_encrypted_icv.size,
+                        sizeof(aad_iv_encrypted_icv.data), this->isa_ctx_id);
+               return FALSE;
+       }
+       memcpy(aad_iv_encrypted_icv.data, assoc.ptr, assoc.len);
+       memcpy(aad_iv_encrypted_icv.data + assoc.len, iv.ptr, iv.len);
+       memcpy(aad_iv_encrypted_icv.data + assoc.len + iv.len, encrypted.ptr,
+                  encrypted.len);
+
+       res = ike_isa_decrypt(this->isa_ctx_id, assoc.len, aad_iv_encrypted_icv,
+                                                 &decrypted);
+       if (res != TKM_OK)
+       {
+               DBG1(DBG_IKE, "decryption failed (isa: %llu)", this->isa_ctx_id);
+               return FALSE;
+       }
+
+       if (plain)
+       {
+               sequence_to_chunk(decrypted.data, decrypted.size, plain);
+       }
+       else
+       {
+               memcpy(encrypted.ptr, decrypted.data, decrypted.size);
+       }
+       return TRUE;
+}
+
+METHOD(aead_t, get_block_size, size_t,
+       private_aead_t *this)
+{
+       return this->block_len;
+}
+
+METHOD(aead_t, get_icv_size, size_t,
+       private_aead_t *this)
+{
+       return this->icv_len;
+}
+
+METHOD(aead_t, get_iv_size, size_t,
+       private_aead_t *this)
+{
+       return this->iv_len;
+}
+
+METHOD(aead_t, get_iv_gen, iv_gen_t*,
+       private_aead_t *this)
+{
+       return &this->iv_gen;
+}
+
+METHOD(aead_t, get_key_size, size_t,
+       private_aead_t *this)
+{
+       return 1;
+}
+
+METHOD(aead_t, set_key, bool,
+       private_aead_t *this, chunk_t key)
+{
+       return TRUE;
+}
+
+METHOD(aead_t, destroy, void,
+       private_aead_t *this)
+{
+       free(this);
+}
+
+/*
+ * Described in header
+ */
+aead_t *tkm_aead_create(isa_id_type isa_ctx_id, block_len_type block_len,
+                                               icv_len_type icv_len, iv_len_type iv_len)
+{
+       private_aead_t *aead;
+
+       INIT(aead,
+               .public = {
+                       .encrypt = _encrypt,
+                       .decrypt = _decrypt,
+                       .get_block_size = _get_block_size,
+                       .get_icv_size = _get_icv_size,
+                       .get_iv_size = _get_iv_size,
+                       .get_iv_gen = _get_iv_gen,
+                       .get_key_size = _get_key_size,
+                       .set_key = _set_key,
+                       .destroy = _destroy,
+               },
+               .iv_gen = {
+                       .get_iv = _get_iv,
+                       .allocate_iv = _allocate_iv,
+                       .destroy = (void *)nop,
+               },
+               .isa_ctx_id = isa_ctx_id,
+               .block_len = block_len,
+               .icv_len = icv_len,
+               .iv_len = iv_len,
+       );
+
+       return &aead->public;
+}
diff --git a/src/charon-tkm/src/tkm/tkm_aead.h b/src/charon-tkm/src/tkm/tkm_aead.h
new file mode 100644 (file)
index 0000000..61aec90
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 secunet Security Networks AG
+ * Copyright (C) 2020 Stefan Berghofer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @defgroup tkm-aead aead
+ * @{ @ingroup tkm
+ */
+
+#ifndef TKM_AEAD_H_
+#define TKM_AEAD_H_
+
+typedef struct tkm_aead_t tkm_aead_t;
+
+#include <crypto/aead.h>
+#include <tkm/types.h>
+
+/**
+ * Create an AEAD implementation providing encryption and integrity protection
+ * using TKM.
+ *
+ * @param isa_ctx_id           id of ISA context to use for encryption/decryption
+ * @param block_len                    block length of encryption algorithm
+ * @param icv_len                      length of integrity check value
+ * @param iv_len                       length of initialization vector
+ * @return                                     created aead_t object
+ */
+aead_t *tkm_aead_create(isa_id_type isa_ctx_id, block_len_type block_len,
+                                               icv_len_type icv_len, iv_len_type iv_len);
+
+#endif /** TKM_AEAD_H_ @}*/
index 1107c2219ddd13da790e044ccfe5297326cc8dd5..75fb904ae872a8e5bab703e6d06444832c47560f 100644 (file)
@@ -25,6 +25,7 @@
 #include "tkm_utils.h"
 #include "tkm_diffie_hellman.h"
 #include "tkm_keymat.h"
+#include "tkm_aead.h"
 
 typedef struct private_tkm_keymat_t private_tkm_keymat_t;
 
@@ -44,14 +45,9 @@ struct private_tkm_keymat_t {
        bool initiator;
 
        /**
-        * Inbound AEAD.
+        * AEAD implementation.
         */
-       aead_t *aead_in;
-
-       /**
-        * Outbound AEAD.
-        */
-       aead_t *aead_out;
+       aead_t *aead;
 
        /**
         * ISA context id.
@@ -79,91 +75,6 @@ struct private_tkm_keymat_t {
        hash_algorithm_set_t *hash_algorithms;
 };
 
-/**
- * Create AEAD transforms from given key chunks.
- *
- * @param in                   inbound AEAD transform to allocate, NULL if failed
- * @param out                  outbound AEAD transform to allocate, NULL if failed
- * @param sk_ai                        SK_ai key chunk
- * @param sk_ar                        SK_ar key chunk
- * @param sk_ei                        SK_ei key chunk
- * @param sk_er                        SK_er key chunk
- * @param enc_alg              encryption algorithm to use
- * @param int_alg              integrity algorithm to use
- * @param key_size             encryption key size in bytes
- * @param initiator            TRUE if initiator
- */
-static void aead_create_from_keys(aead_t **in, aead_t **out,
-          const chunk_t * const sk_ai, const chunk_t * const sk_ar,
-          const chunk_t * const sk_ei, const chunk_t * const sk_er,
-          const uint16_t enc_alg, const uint16_t int_alg,
-          const uint16_t key_size, bool initiator)
-{
-       *in = *out = NULL;
-       signer_t *signer_i, *signer_r;
-       crypter_t *crypter_i, *crypter_r;
-       iv_gen_t *ivg_i, *ivg_r;
-
-       signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
-       signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
-       if (signer_i == NULL || signer_r == NULL)
-       {
-               DBG1(DBG_IKE, "%N %N not supported!",
-                        transform_type_names, INTEGRITY_ALGORITHM,
-                        integrity_algorithm_names, int_alg);
-               return;
-       }
-       crypter_i = lib->crypto->create_crypter(lib->crypto, enc_alg, key_size);
-       crypter_r = lib->crypto->create_crypter(lib->crypto, enc_alg, key_size);
-       if (crypter_i == NULL || crypter_r == NULL)
-       {
-               signer_i->destroy(signer_i);
-               signer_r->destroy(signer_r);
-               DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
-                        transform_type_names, ENCRYPTION_ALGORITHM,
-                        encryption_algorithm_names, enc_alg, key_size);
-               return;
-       }
-
-       DBG4(DBG_IKE, "Sk_ai %B", sk_ai);
-       if (!signer_i->set_key(signer_i, *sk_ai))
-       {
-               return;
-       }
-       DBG4(DBG_IKE, "Sk_ar %B", sk_ar);
-       if (!signer_r->set_key(signer_r, *sk_ar))
-       {
-               return;
-       }
-       DBG4(DBG_IKE, "Sk_ei %B", sk_ei);
-       if (!crypter_i->set_key(crypter_i, *sk_ei))
-       {
-               return;
-       }
-       DBG4(DBG_IKE, "Sk_er %B", sk_er);
-       if (!crypter_r->set_key(crypter_r, *sk_er))
-       {
-               return;
-       }
-
-       ivg_i = iv_gen_create_for_alg(enc_alg);
-       ivg_r = iv_gen_create_for_alg(enc_alg);
-       if (!ivg_i || !ivg_r)
-       {
-               return;
-       }
-       if (initiator)
-       {
-               *in = aead_create(crypter_r, signer_r, ivg_r);
-               *out = aead_create(crypter_i, signer_i, ivg_i);
-       }
-       else
-       {
-               *in = aead_create(crypter_i, signer_i, ivg_i);
-               *out = aead_create(crypter_r, signer_r, ivg_r);
-       }
-}
-
 METHOD(keymat_t, get_version, ike_version_t,
        private_tkm_keymat_t *this)
 {
@@ -189,12 +100,14 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
 {
        uint16_t enc_alg, int_alg, key_size;
        uint64_t nc_id, spi_loc, spi_rem;
-       chunk_t *nonce, c_ai, c_ar, c_ei, c_er;
+       chunk_t *nonce;
        tkm_diffie_hellman_t *tkm_dh;
        dh_id_type dh_id;
        nonce_type nonce_rem;
        result_type res;
-       key_type sk_ai, sk_ar, sk_ei, sk_er;
+       block_len_type block_len;
+       icv_len_type icv_len;
+       iv_len_type iv_len;
 
        /* Check encryption and integrity algorithms */
        if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg,
@@ -266,7 +179,7 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
                         "spi_rem: %llx)", nc_id, dh_id, spi_loc, spi_rem);
                res = ike_isa_create(this->isa_ctx_id, this->ae_ctx_id, 1, dh_id, nc_id,
                                                         nonce_rem, this->initiator, spi_loc, spi_rem,
-                                                        &sk_ai, &sk_ar, &sk_ei, &sk_er);
+                                                        &block_len, &icv_len, &iv_len);
        }
        else
        {
@@ -291,8 +204,8 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
                this->ae_ctx_id = isa_info.ae_id;
                res = ike_isa_create_child(this->isa_ctx_id, isa_info.parent_isa_id, 1,
                                                                   dh_id, nc_id, nonce_rem, this->initiator,
-                                                                  spi_loc, spi_rem, &sk_ai, &sk_ar, &sk_ei,
-                                                                  &sk_er);
+                                                                  spi_loc, spi_rem, &block_len, &icv_len,
+                                                                  &iv_len);
                chunk_free(&rekey_skd);
        }
 
@@ -302,25 +215,7 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
                return FALSE;
        }
 
-       sequence_to_chunk(sk_ai.data, sk_ai.size, &c_ai);
-       sequence_to_chunk(sk_ar.data, sk_ar.size, &c_ar);
-       sequence_to_chunk(sk_ei.data, sk_ei.size, &c_ei);
-       sequence_to_chunk(sk_er.data, sk_er.size, &c_er);
-
-       aead_create_from_keys(&this->aead_in, &this->aead_out, &c_ai, &c_ar, &c_ei,
-                                                 &c_er, enc_alg, int_alg, key_size / 8,
-                                                 this->initiator);
-
-       chunk_clear(&c_ai);
-       chunk_clear(&c_ar);
-       chunk_clear(&c_ei);
-       chunk_clear(&c_er);
-
-       if (!this->aead_in || !this->aead_out)
-       {
-               DBG1(DBG_IKE, "could not initialize AEAD transforms");
-               return FALSE;
-       }
+       this->aead = tkm_aead_create(this->isa_ctx_id, block_len, icv_len, iv_len);
 
        /* TODO: Add failure handler (see keymat_v2.c) */
 
@@ -380,7 +275,7 @@ METHOD(keymat_v2_t, derive_child_keys, bool,
 METHOD(keymat_t, get_aead, aead_t*,
        private_tkm_keymat_t *this, bool in)
 {
-       return in ? this->aead_in : this->aead_out;
+       return this->aead;
 }
 
 METHOD(keymat_v2_t, get_auth_octets, bool,
@@ -474,8 +369,7 @@ METHOD(keymat_t, destroy, void,
        }
 
        DESTROY_IF(this->hash_algorithms);
-       DESTROY_IF(this->aead_in);
-       DESTROY_IF(this->aead_out);
+       DESTROY_IF(this->aead);
        chunk_free(&this->auth_payload);
        chunk_free(&this->other_init_msg);
        free(this);
diff --git a/testing/scripts/recipes/004_spark-crypto.mk b/testing/scripts/recipes/004_spark-crypto.mk
new file mode 100644 (file)
index 0000000..00965a5
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/make
+
+PKG = spark-crypto
+SRC = https://git.codelabs.ch/spark-crypto.git
+REV = c97939b6cdd5e5f19847cf8d1abb7575e1c01df7
+
+DESTDIR = /usr/local/ada/lib/gnat
+
+all: install
+
+.$(PKG)-cloned:
+       [ -d $(PKG) ] || git clone $(SRC) $(PKG)
+       @touch $@
+
+.$(PKG)-checkout-$(REV): .$(PKG)-cloned
+       cd $(PKG) && git fetch && git checkout $(REV)
+       @rm -f .$(PKG)-checkout-* && touch $@
+
+.$(PKG)-built-$(REV): .$(PKG)-checkout-$(REV)
+       cd $(PKG) && make NO_SPARK=1 NO_TESTS=1 NO_APIDOC=1
+       @rm -f .$(PKG)-built-* && touch $@
+
+install: .$(PKG)-built-$(REV)
+       cd $(PKG) && make NO_SPARK=1 NO_TESTS=1 NO_APIDOC=1 DESTDIR=$(DESTDIR) install
index ece3baa5ec465c7de087ca5112c28f611552ed20..75da7153f8ab98f8a6b15e94d387f5a4d3a81d22 100644 (file)
@@ -2,7 +2,7 @@
 
 PKG = tkm-rpc
 SRC = https://git.codelabs.ch/git/$(PKG).git
-REV = 1235905c5c6fad5df1eecb6ba0447d5722753203
+REV = a681aa8694412f16a44a7fba2eeb67cb3d43caf6
 
 PREFIX = /usr/local/ada
 
index 3505504204c3ef984662a301e7cd624929e519d4..a9e658cd810316a6f5ffa000104c3fdfc7e4c494 100644 (file)
@@ -2,7 +2,7 @@
 
 PKG = tkm
 SRC = https://git.codelabs.ch/git/$(PKG).git
-REV = b99aeb158b7701ea4a77184bff5ff38f8e26013a
+REV = fadff7fd8c454ae46177924fde56600081ddf4d5
 
 export ADA_PROJECT_PATH=/usr/local/ada/lib/gnat