--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ @}*/
#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;
bool initiator;
/**
- * Inbound AEAD.
+ * AEAD implementation.
*/
- aead_t *aead_in;
-
- /**
- * Outbound AEAD.
- */
- aead_t *aead_out;
+ aead_t *aead;
/**
* ISA context id.
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)
{
{
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,
"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
{
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);
}
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) */
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,
}
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);
--- /dev/null
+#!/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
PKG = tkm-rpc
SRC = https://git.codelabs.ch/git/$(PKG).git
-REV = 1235905c5c6fad5df1eecb6ba0447d5722753203
+REV = a681aa8694412f16a44a7fba2eeb67cb3d43caf6
PREFIX = /usr/local/ada
PKG = tkm
SRC = https://git.codelabs.ch/git/$(PKG).git
-REV = b99aeb158b7701ea4a77184bff5ff38f8e26013a
+REV = fadff7fd8c454ae46177924fde56600081ddf4d5
export ADA_PROJECT_PATH=/usr/local/ada/lib/gnat