Add key derivation service level tests

Adds end-to-end service tests for key derivation operations
provided by a crypto provider.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I1fa0f0f269d9f32fc05ee116edf0ccea618dd17f
diff --git a/components/service/crypto/client/cpp/crypto_client.h b/components/service/crypto/client/cpp/crypto_client.h
index eb30655..2a5e5b9 100644
--- a/components/service/crypto/client/cpp/crypto_client.h
+++ b/components/service/crypto/client/cpp/crypto_client.h
@@ -176,6 +176,51 @@
 	virtual psa_status_t mac_abort(
 		uint32_t op_handle) = 0;
 
+	/* Key derivation methods */
+	virtual psa_status_t key_derivation_setup(
+		uint32_t *op_handle,
+		psa_algorithm_t alg) = 0;
+
+	virtual psa_status_t key_derivation_get_capacity(
+		const uint32_t op_handle,
+		size_t *capacity) = 0;
+
+	virtual psa_status_t key_derivation_set_capacity(
+		uint32_t op_handle,
+		size_t capacity) = 0;
+
+	virtual psa_status_t key_derivation_input_bytes(
+		uint32_t op_handle,
+		psa_key_derivation_step_t step,
+		const uint8_t *data, size_t data_length) = 0;
+
+	virtual psa_status_t key_derivation_input_key(
+		uint32_t op_handle,
+		psa_key_derivation_step_t step,
+		psa_key_id_t key) = 0;
+
+	virtual psa_status_t key_derivation_output_bytes(
+		uint32_t op_handle,
+		uint8_t *output, size_t output_length) = 0;
+
+	virtual psa_status_t key_derivation_output_key(
+		const psa_key_attributes_t *attributes,
+		uint32_t op_handle,
+		psa_key_id_t *key) = 0;
+
+	virtual psa_status_t key_derivation_abort(
+		uint32_t op_handle) = 0;
+
+	virtual psa_status_t key_derivation_key_agreement(
+		uint32_t op_handle,
+		psa_key_derivation_step_t step,
+		psa_key_id_t private_key,
+		const uint8_t *peer_key, size_t peer_key_length) = 0;
+
+	virtual psa_status_t raw_key_agreement(psa_algorithm_t alg,
+		psa_key_id_t private_key,
+		const uint8_t *peer_key, size_t peer_key_length,
+		uint8_t *output, size_t output_size, size_t *output_length) = 0;
 
 protected:
 	crypto_client();
diff --git a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
index 694d9a0..4d9d8f4 100644
--- a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
+++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
@@ -310,3 +310,91 @@
 	return crypto_caller_mac_abort(&m_client,
 		op_handle);
 }
+
+/* Key derivation methods */
+psa_status_t packedc_crypto_client::key_derivation_setup(
+	uint32_t *op_handle,
+	psa_algorithm_t alg)
+{
+	return crypto_caller_key_derivation_setup(&m_client,
+		op_handle, alg);
+}
+
+psa_status_t packedc_crypto_client::key_derivation_get_capacity(
+	const uint32_t op_handle,
+	size_t *capacity)
+{
+	return crypto_caller_key_derivation_get_capacity(&m_client,
+		op_handle, capacity);
+}
+
+psa_status_t packedc_crypto_client::key_derivation_set_capacity(
+	uint32_t op_handle,
+	size_t capacity)
+{
+	return crypto_caller_key_derivation_set_capacity(&m_client,
+		op_handle, capacity);
+}
+
+psa_status_t packedc_crypto_client::key_derivation_input_bytes(
+	uint32_t op_handle,
+	psa_key_derivation_step_t step,
+	const uint8_t *data, size_t data_length)
+{
+	return crypto_caller_key_derivation_input_bytes(&m_client,
+		op_handle, step, data, data_length);
+}
+
+psa_status_t packedc_crypto_client::key_derivation_input_key(
+	uint32_t op_handle,
+	psa_key_derivation_step_t step,
+	psa_key_id_t key)
+{
+	return crypto_caller_key_derivation_input_key(&m_client,
+		op_handle, step, key);
+}
+
+psa_status_t packedc_crypto_client::key_derivation_output_bytes(
+	uint32_t op_handle,
+	uint8_t *output, size_t output_length)
+{
+	return crypto_caller_key_derivation_output_bytes(&m_client,
+		op_handle, output, output_length);
+}
+
+psa_status_t packedc_crypto_client::key_derivation_output_key(
+	const psa_key_attributes_t *attributes,
+	uint32_t op_handle,
+	psa_key_id_t *key)
+{
+	return crypto_caller_key_derivation_output_key(&m_client,
+		attributes, op_handle, key);
+}
+
+psa_status_t packedc_crypto_client::key_derivation_abort(
+	uint32_t op_handle)
+{
+	return crypto_caller_key_derivation_abort(&m_client,
+		op_handle);
+}
+
+psa_status_t packedc_crypto_client::key_derivation_key_agreement(
+	uint32_t op_handle,
+	psa_key_derivation_step_t step,
+	psa_key_id_t private_key,
+	const uint8_t *peer_key, size_t peer_key_length)
+{
+	return crypto_caller_key_derivation_key_agreement(&m_client,
+		op_handle, step, private_key,
+		peer_key, peer_key_length);
+}
+
+psa_status_t packedc_crypto_client::raw_key_agreement(psa_algorithm_t alg,
+	psa_key_id_t private_key,
+	const uint8_t *peer_key, size_t peer_key_length,
+	uint8_t *output, size_t output_size, size_t *output_length)
+{
+	return crypto_caller_raw_key_agreement(&m_client,
+		alg, private_key, peer_key, peer_key_length,
+		output, output_size, output_length);
+}
diff --git a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
index 32dbdc4..377b51d 100644
--- a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
+++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
@@ -173,6 +173,52 @@
 	psa_status_t mac_abort(
 		uint32_t op_handle);
 
+	/* Key derivation methods */
+	psa_status_t key_derivation_setup(
+		uint32_t *op_handle,
+		psa_algorithm_t alg);
+
+	psa_status_t key_derivation_get_capacity(
+		const uint32_t op_handle,
+		size_t *capacity);
+
+	psa_status_t key_derivation_set_capacity(
+		uint32_t op_handle,
+		size_t capacity);
+
+	psa_status_t key_derivation_input_bytes(
+		uint32_t op_handle,
+		psa_key_derivation_step_t step,
+		const uint8_t *data, size_t data_length);
+
+	psa_status_t key_derivation_input_key(
+		uint32_t op_handle,
+		psa_key_derivation_step_t step,
+		psa_key_id_t key);
+
+	psa_status_t key_derivation_output_bytes(
+		uint32_t op_handle,
+		uint8_t *output, size_t output_length);
+
+	psa_status_t key_derivation_output_key(
+		const psa_key_attributes_t *attributes,
+		uint32_t op_handle,
+		psa_key_id_t *key);
+
+	psa_status_t key_derivation_abort(
+		uint32_t op_handle);
+
+	psa_status_t key_derivation_key_agreement(
+		uint32_t op_handle,
+		psa_key_derivation_step_t step,
+		psa_key_id_t private_key,
+		const uint8_t *peer_key, size_t peer_key_length);
+
+	psa_status_t raw_key_agreement(psa_algorithm_t alg,
+		psa_key_id_t private_key,
+		const uint8_t *peer_key, size_t peer_key_length,
+		uint8_t *output, size_t output_size, size_t *output_length);
+
 };
 
 #endif /* PACKEDC_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp
index 0941857..e53420f 100644
--- a/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp
+++ b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp
@@ -893,3 +893,79 @@
 {
 	return PSA_ERROR_NOT_SUPPORTED;
 }
+
+/* Key derivation methods */
+psa_status_t protobuf_crypto_client::key_derivation_setup(
+	uint32_t *op_handle,
+	psa_algorithm_t alg)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::key_derivation_get_capacity(
+	const uint32_t op_handle,
+	size_t *capacity)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::key_derivation_set_capacity(
+	uint32_t op_handle,
+	size_t capacity)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::key_derivation_input_bytes(
+	uint32_t op_handle,
+	psa_key_derivation_step_t step,
+	const uint8_t *data, size_t data_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::key_derivation_input_key(
+	uint32_t op_handle,
+	psa_key_derivation_step_t step,
+	psa_key_id_t key)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::key_derivation_output_bytes(
+	uint32_t op_handle,
+	uint8_t *output, size_t output_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::key_derivation_output_key(
+	const psa_key_attributes_t *attributes,
+	uint32_t op_handle,
+	psa_key_id_t *key)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::key_derivation_abort(
+	uint32_t op_handle)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::key_derivation_key_agreement(
+	uint32_t op_handle,
+	psa_key_derivation_step_t step,
+	psa_key_id_t private_key,
+	const uint8_t *peer_key, size_t peer_key_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::raw_key_agreement(psa_algorithm_t alg,
+	psa_key_id_t private_key,
+	const uint8_t *peer_key, size_t peer_key_length,
+	uint8_t *output, size_t output_size, size_t *output_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
diff --git a/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.h b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.h
index e9be6ea..085d9cf 100644
--- a/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.h
+++ b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.h
@@ -173,6 +173,51 @@
 	psa_status_t mac_abort(
 		uint32_t op_handle);
 
+	/* Key derivation methods */
+	psa_status_t key_derivation_setup(
+		uint32_t *op_handle,
+		psa_algorithm_t alg);
+
+	psa_status_t key_derivation_get_capacity(
+		const uint32_t op_handle,
+		size_t *capacity);
+
+	psa_status_t key_derivation_set_capacity(
+		uint32_t op_handle,
+		size_t capacity);
+
+	psa_status_t key_derivation_input_bytes(
+		uint32_t op_handle,
+		psa_key_derivation_step_t step,
+		const uint8_t *data, size_t data_length);
+
+	psa_status_t key_derivation_input_key(
+		uint32_t op_handle,
+		psa_key_derivation_step_t step,
+		psa_key_id_t key);
+
+	psa_status_t key_derivation_output_bytes(
+		uint32_t op_handle,
+		uint8_t *output, size_t output_length);
+
+	psa_status_t key_derivation_output_key(
+		const psa_key_attributes_t *attributes,
+		uint32_t op_handle,
+		psa_key_id_t *key);
+
+	psa_status_t key_derivation_abort(
+		uint32_t op_handle);
+
+	psa_status_t key_derivation_key_agreement(
+		uint32_t op_handle,
+		psa_key_derivation_step_t step,
+		psa_key_id_t private_key,
+		const uint8_t *peer_key, size_t peer_key_length);
+
+	psa_status_t raw_key_agreement(psa_algorithm_t alg,
+		psa_key_id_t private_key,
+		const uint8_t *peer_key, size_t peer_key_length,
+		uint8_t *output, size_t output_size, size_t *output_length);
 
 private:
 
diff --git a/components/service/crypto/test/service/extension/key_derivation/component.cmake b/components/service/crypto/test/service/extension/key_derivation/component.cmake
new file mode 100644
index 0000000..2d251aa
--- /dev/null
+++ b/components/service/crypto/test/service/extension/key_derivation/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/key_derivation_service_scenarios.cpp"
+	)
diff --git a/components/service/crypto/test/service/extension/key_derivation/key_derivation_service_scenarios.cpp b/components/service/crypto/test/service/extension/key_derivation/key_derivation_service_scenarios.cpp
new file mode 100644
index 0000000..66dc268
--- /dev/null
+++ b/components/service/crypto/test/service/extension/key_derivation/key_derivation_service_scenarios.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cstring>
+#include <cstdint>
+#include <CppUTest/TestHarness.h>
+#include "key_derivation_service_scenarios.h"
+
+
+key_derivation_service_scenarios::key_derivation_service_scenarios(crypto_client *crypto_client) :
+	m_crypto_client(crypto_client),
+	m_secret_keyid(0)
+{
+
+}
+
+key_derivation_service_scenarios::~key_derivation_service_scenarios()
+{
+	destroySecretKey();
+
+	delete m_crypto_client;
+	m_crypto_client = NULL;
+}
+
+psa_status_t key_derivation_service_scenarios::generateSecretKey()
+{
+	destroySecretKey();
+
+	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+	psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
+	psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
+	psa_set_key_algorithm(&attributes, PSA_ALG_HKDF(PSA_ALG_SHA_256));
+	psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
+	psa_set_key_bits(&attributes, 256);
+
+	psa_status_t status = m_crypto_client->generate_key(&attributes, &m_secret_keyid);
+
+	psa_reset_key_attributes(&attributes);
+
+	return status;
+}
+
+void key_derivation_service_scenarios::destroySecretKey()
+{
+	if (m_secret_keyid) {
+
+		m_crypto_client->destroy_key(m_secret_keyid);
+		m_secret_keyid = 0;
+	}
+}
+
+void key_derivation_service_scenarios::hkdfDeriveKey()
+{
+	psa_status_t status;
+	uint32_t op_handle = 0;
+
+	status = generateSecretKey();
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->key_derivation_setup(&op_handle, PSA_ALG_HKDF(PSA_ALG_SHA_256));
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	static const uint8_t salt[] = {0,1,2,3,4,5,6,7,8,9};
+	status = m_crypto_client->key_derivation_input_bytes(op_handle,
+		PSA_KEY_DERIVATION_INPUT_SALT, salt, sizeof(salt));
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->key_derivation_input_key(op_handle,
+		PSA_KEY_DERIVATION_INPUT_SECRET, m_secret_keyid);
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	static const uint8_t info[] = {50,51,52,53,54,55,56,57,58};
+	status = m_crypto_client->key_derivation_input_bytes(op_handle,
+		PSA_KEY_DERIVATION_INPUT_INFO, info, sizeof(info));
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	/* Derive a key that could be used for symmetric encryption */
+	psa_key_id_t derived_keyid;
+	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+	psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
+	psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
+	psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
+	psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
+	psa_set_key_bits(&attributes, 256);
+
+	status = m_crypto_client->key_derivation_output_key(&attributes, op_handle, &derived_keyid);
+	psa_reset_key_attributes(&attributes);
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->key_derivation_abort(op_handle);
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->destroy_key(derived_keyid);
+	CHECK_EQUAL(PSA_SUCCESS, status);
+}
+
+void key_derivation_service_scenarios::hkdfDeriveBytes()
+{
+	psa_status_t status;
+	uint32_t op_handle = 0;
+
+	status = generateSecretKey();
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->key_derivation_setup(&op_handle, PSA_ALG_HKDF(PSA_ALG_SHA_256));
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->key_derivation_input_key(op_handle,
+		PSA_KEY_DERIVATION_INPUT_SECRET, m_secret_keyid);
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	static const uint8_t info[] = {50,51,52,53,54,55,56,57,58};
+	status = m_crypto_client->key_derivation_input_bytes(op_handle,
+		PSA_KEY_DERIVATION_INPUT_INFO, info, sizeof(info));
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	/* Derive some output bytes */
+	uint8_t derived_bytes[99];
+	status = m_crypto_client->key_derivation_output_bytes(op_handle,
+		derived_bytes, sizeof(derived_bytes));
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->key_derivation_abort(op_handle);
+	CHECK_EQUAL(PSA_SUCCESS, status);
+}
+
+void key_derivation_service_scenarios::deriveAbort()
+{
+	psa_status_t status;
+	uint32_t op_handle = 0;
+
+	status = generateSecretKey();
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->key_derivation_setup(&op_handle, PSA_ALG_HKDF(PSA_ALG_SHA_256));
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->key_derivation_input_key(op_handle,
+		PSA_KEY_DERIVATION_INPUT_SECRET, m_secret_keyid);
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	status = m_crypto_client->key_derivation_abort(op_handle);
+	CHECK_EQUAL(PSA_SUCCESS, status);
+
+	/* Expect operation to have been aborted */
+	status = m_crypto_client->key_derivation_set_capacity(op_handle, 100);
+	CHECK_EQUAL(PSA_ERROR_BAD_STATE, status);
+}
diff --git a/components/service/crypto/test/service/extension/key_derivation/key_derivation_service_scenarios.h b/components/service/crypto/test/service/extension/key_derivation/key_derivation_service_scenarios.h
new file mode 100644
index 0000000..794311a
--- /dev/null
+++ b/components/service/crypto/test/service/extension/key_derivation/key_derivation_service_scenarios.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef KEY_DERIVATION_SERVICE_SCENARIOS_H
+#define KEY_DERIVATION_SERVICE_SCENARIOS_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <service/crypto/client/cpp/crypto_client.h>
+
+/*
+ * Service-level test scenarios for the key_derivation extension to the
+ * crypto service that may be reused using different concrete
+ * crypto_clients to check end-to-end operation using different protocol
+ * serialization schemes.
+ */
+class key_derivation_service_scenarios
+{
+public:
+	key_derivation_service_scenarios(crypto_client *crypto_client);
+	~key_derivation_service_scenarios();
+
+	void hkdfDeriveKey();
+	void hkdfDeriveBytes();
+	void deriveAbort();
+
+private:
+
+	psa_status_t generateSecretKey();
+	void destroySecretKey();
+
+	crypto_client *m_crypto_client;
+	psa_key_id_t m_secret_keyid;
+};
+
+#endif /* KEY_DERIVATION_SERVICE_SCENARIOS_H */
diff --git a/components/service/crypto/test/service/extension/key_derivation/packed-c/component.cmake b/components/service/crypto/test/service/extension/key_derivation/packed-c/component.cmake
new file mode 100644
index 0000000..35615f0
--- /dev/null
+++ b/components/service/crypto/test/service/extension/key_derivation/packed-c/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/key_derivation_service_packedc_tests.cpp"
+	)
diff --git a/components/service/crypto/test/service/extension/key_derivation/packed-c/key_derivation_service_packedc_tests.cpp b/components/service/crypto/test/service/extension/key_derivation/packed-c/key_derivation_service_packedc_tests.cpp
new file mode 100644
index 0000000..261bf98
--- /dev/null
+++ b/components/service/crypto/test/service/extension/key_derivation/packed-c/key_derivation_service_packedc_tests.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h>
+#include <service/crypto/test/service/extension/key_derivation/key_derivation_service_scenarios.h>
+#include <protocols/rpc/common/packed-c/encoding.h>
+#include <service_locator.h>
+#include <CppUTest/TestHarness.h>
+
+/*
+ * Service-level key derivation tests that use the packed-c access protocol serialization
+ */
+TEST_GROUP(CryptoKeyDerivationServicePackedcTests)
+{
+	void setup()
+	{
+		struct rpc_caller *caller;
+		int status;
+
+		m_rpc_session_handle = NULL;
+		m_crypto_service_context = NULL;
+		m_scenarios = NULL;
+
+		service_locator_init();
+
+		m_crypto_service_context = service_locator_query("sn:trustedfirmware.org:crypto:0", &status);
+		CHECK_TRUE(m_crypto_service_context);
+
+		m_rpc_session_handle = service_context_open(m_crypto_service_context, TS_RPC_ENCODING_PACKED_C, &caller);
+		CHECK_TRUE(m_rpc_session_handle);
+
+		m_scenarios = new key_derivation_service_scenarios(new packedc_crypto_client(caller));
+	}
+
+	void teardown()
+	{
+		delete m_scenarios;
+		m_scenarios = NULL;
+
+		service_context_close(m_crypto_service_context, m_rpc_session_handle);
+		m_rpc_session_handle = NULL;
+
+		service_context_relinquish(m_crypto_service_context);
+		m_crypto_service_context = NULL;
+	}
+
+	rpc_session_handle m_rpc_session_handle;
+	struct service_context *m_crypto_service_context;
+	key_derivation_service_scenarios *m_scenarios;
+};
+
+TEST(CryptoKeyDerivationServicePackedcTests, hkdfDeriveKey)
+{
+	m_scenarios->hkdfDeriveKey();
+}
+
+TEST(CryptoKeyDerivationServicePackedcTests, hkdfDeriveBytes)
+{
+	m_scenarios->hkdfDeriveBytes();
+}
+
+TEST(CryptoKeyDerivationServicePackedcTests, deriveAbort)
+{
+	m_scenarios->deriveAbort();
+}
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index ad04fba..d89443f 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -96,6 +96,8 @@
 		"components/service/crypto/test/service/extension/cipher/packed-c"
 		"components/service/crypto/test/service/extension/mac"
 		"components/service/crypto/test/service/extension/mac/packed-c"
+		"components/service/crypto/test/service/extension/key_derivation"
+		"components/service/crypto/test/service/extension/key_derivation/packed-c"
 		"components/service/crypto/test/protocol"
 		"components/service/secure_storage/include"
 		"components/service/secure_storage/frontend/psa/its"
diff --git a/deployments/ts-service-test/ts-service-test.cmake b/deployments/ts-service-test/ts-service-test.cmake
index fedb821..4a8c59c 100644
--- a/deployments/ts-service-test/ts-service-test.cmake
+++ b/deployments/ts-service-test/ts-service-test.cmake
@@ -42,6 +42,8 @@
 		"components/service/crypto/test/service/extension/cipher/packed-c"
 		"components/service/crypto/test/service/extension/mac"
 		"components/service/crypto/test/service/extension/mac/packed-c"
+		"components/service/crypto/test/service/extension/key_derivation"
+		"components/service/crypto/test/service/extension/key_derivation/packed-c"
 		"components/service/crypto/client/psa"
 		"components/service/crypto/client/cpp"
 		"components/service/crypto/client/cpp/protocol/protobuf"