Improve reuse of crypto client components

Now that the crypto service provider may be extended to support
the entire set of PSA crypto operations, reuse of client side
components between different types of client has become much
more important.  This change introduces the crypto caller
component that may be specialized to support different
calling conventions and serializations.  A packed-c
specialization is implemented that provides code that
may be reused by any client taht needs to use the
packed-c serialization to talk to a crypto service instance.
To allow multiple crypto callers to co-exist within
the same build, the crypto caller is implemented as
a header file library with static inline functions.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: Iac791829470a834f1a29ef59d4442bda93220f91
diff --git a/components/service/crypto/client/cpp/crypto_client.h b/components/service/crypto/client/cpp/crypto_client.h
index d996380..42085be 100644
--- a/components/service/crypto/client/cpp/crypto_client.h
+++ b/components/service/crypto/client/cpp/crypto_client.h
@@ -18,60 +18,95 @@
 class crypto_client
 {
 public:
-    virtual ~crypto_client();
+	virtual ~crypto_client();
 
-    int err_rpc_status() const;
+	int err_rpc_status() const;
 
-    /* Key lifecycle methods */
-    virtual psa_status_t generate_key(const psa_key_attributes_t *attributes,
-                            psa_key_id_t *id) = 0;
-    virtual psa_status_t destroy_key(psa_key_id_t id) = 0;
-    virtual psa_status_t import_key(const psa_key_attributes_t *attributes,
-                            const uint8_t *data, size_t data_length, psa_key_id_t *id) = 0;
+	/* Key lifecycle methods */
+	virtual psa_status_t generate_key(
+		const psa_key_attributes_t *attributes,
+		psa_key_id_t *id) = 0;
 
-    /* Key export methods */
-    virtual psa_status_t export_key(psa_key_id_t id,
-                            uint8_t *data, size_t data_size,
-                            size_t *data_length) = 0;
-    virtual psa_status_t export_public_key(psa_key_id_t id,
-                            uint8_t *data, size_t data_size, size_t *data_length) = 0;
+	virtual psa_status_t destroy_key(
+		psa_key_id_t id) = 0;
 
-    /* Sign/verify methods */
-    virtual psa_status_t sign_hash(psa_key_id_t id, psa_algorithm_t alg,
-                            const uint8_t *hash, size_t hash_length,
-                            uint8_t *signature, size_t signature_size,
-                            size_t *signature_length) = 0;
-    virtual psa_status_t verify_hash(psa_key_id_t id, psa_algorithm_t alg,
-                            const uint8_t *hash, size_t hash_length,
-                            const uint8_t *signature, size_t signature_length) = 0;
+	virtual psa_status_t import_key(
+		const psa_key_attributes_t *attributes,
+		const uint8_t *data, size_t data_length,
+		psa_key_id_t *id) = 0;
 
-    /* Asymmetric encrypt/decrypt */
-    virtual psa_status_t asymmetric_encrypt(psa_key_id_t id, psa_algorithm_t alg,
-                            const uint8_t *input, size_t input_length,
-                            const uint8_t *salt, size_t salt_length,
-                            uint8_t *output, size_t output_size, size_t *output_length) = 0;
-    virtual psa_status_t asymmetric_decrypt(psa_key_id_t id, psa_algorithm_t alg,
-                            const uint8_t *input, size_t input_length,
-                            const uint8_t *salt, size_t salt_length,
-                            uint8_t *output, size_t output_size, size_t *output_length) = 0;
+	virtual psa_status_t copy_key(
+		psa_key_id_t source_key,
+		const psa_key_attributes_t *attributes,
+		psa_key_id_t *target_key) = 0;
 
-    /* Random number generation */
-    virtual psa_status_t generate_random(uint8_t *output, size_t output_size) = 0;
+	virtual psa_status_t purge_key(
+		psa_key_id_t id) = 0;
 
-    /* Hash methods */
-    virtual psa_status_t hash_setup(uint32_t *op_handle,
-                            psa_algorithm_t alg) = 0;
-    virtual psa_status_t hash_update(uint32_t op_handle,
-                            const uint8_t *input, size_t input_length) = 0;
-    virtual psa_status_t hash_finish(uint32_t op_handle,
-                            uint8_t *hash, size_t hash_size, size_t *hash_length) = 0;
+	virtual psa_status_t get_key_attributes(
+		psa_key_id_t id,
+		psa_key_attributes_t *attributes) = 0;
+
+	/* Key export methods */
+	virtual psa_status_t export_key(
+		psa_key_id_t id,
+		uint8_t *data, size_t data_size, size_t *data_length) = 0;
+
+	virtual psa_status_t export_public_key(
+		psa_key_id_t id,
+		uint8_t *data, size_t data_size, size_t *data_length) = 0;
+
+	/* Sign/verify methods */
+	virtual psa_status_t sign_hash(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *hash, size_t hash_length,
+		uint8_t *signature, size_t signature_size, size_t *signature_length) = 0;
+
+	virtual psa_status_t verify_hash(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *hash, size_t hash_length,
+		const uint8_t *signature, size_t signature_length) = 0;
+
+	/* Asymmetric encrypt/decrypt */
+	virtual psa_status_t asymmetric_encrypt(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *input, size_t input_length,
+		const uint8_t *salt, size_t salt_length,
+		uint8_t *output, size_t output_size, size_t *output_length) = 0;
+
+	virtual psa_status_t asymmetric_decrypt(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *input, size_t input_length,
+		const uint8_t *salt, size_t salt_length,
+		uint8_t *output, size_t output_size, size_t *output_length) = 0;
+
+	/* Random number generation */
+	virtual psa_status_t generate_random(
+		uint8_t *output, size_t output_size) = 0;
+
+	/* Hash methods */
+	virtual psa_status_t hash_setup(
+		uint32_t *op_handle,
+		psa_algorithm_t alg) = 0;
+
+	virtual psa_status_t hash_update(
+		uint32_t op_handle,
+		const uint8_t *input, size_t input_length) = 0;
+
+	virtual psa_status_t hash_finish(
+		uint32_t op_handle,
+		uint8_t *hash, size_t hash_size, size_t *hash_length) = 0;
 
 protected:
-    crypto_client();
-    crypto_client(struct rpc_caller *caller);
-    void set_caller(struct rpc_caller *caller);
+	crypto_client();
+	crypto_client(struct rpc_caller *caller);
+	void set_caller(struct rpc_caller *caller);
 
-    struct service_client m_client;
+	struct service_client m_client;
 };
 
 #endif /* CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.cpp b/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.cpp
deleted file mode 100644
index 43b2a66..0000000
--- a/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.cpp
+++ /dev/null
@@ -1,842 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <cstring>
-#include <cstdlib>
-#include "packedc_crypto_client.h"
-#include <protocols/rpc/common/packed-c/status.h>
-#include <protocols/service/crypto/packed-c/opcodes.h>
-#include <protocols/service/crypto/packed-c/key_attributes.h>
-#include <protocols/service/crypto/packed-c/asymmetric_decrypt.h>
-#include <protocols/service/crypto/packed-c/asymmetric_encrypt.h>
-#include <protocols/service/crypto/packed-c/destroy_key.h>
-#include <protocols/service/crypto/packed-c/export_key.h>
-#include <protocols/service/crypto/packed-c/export_public_key.h>
-#include <protocols/service/crypto/packed-c/generate_key.h>
-#include <protocols/service/crypto/packed-c/generate_random.h>
-#include <protocols/service/crypto/packed-c/import_key.h>
-#include <protocols/service/crypto/packed-c/sign_hash.h>
-#include <protocols/service/crypto/packed-c/verify_hash.h>
-#include <protocols/service/crypto/packed-c/hash.h>
-#include <common/tlv/tlv.h>
-#include <rpc_caller.h>
-
-
-packedc_crypto_client::packedc_crypto_client() :
-	crypto_client()
-{
-
-}
-
-packedc_crypto_client::packedc_crypto_client(struct rpc_caller *caller) :
-	crypto_client(caller)
-{
-
-}
-
-packedc_crypto_client::~packedc_crypto_client()
-{
-
-}
-
-psa_status_t packedc_crypto_client::generate_key(const psa_key_attributes_t *attributes,
-											psa_key_id_t *id)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_generate_key_in req_msg;
-	size_t req_len = sizeof(ts_crypto_generate_key_in);
-
-	translate_key_attributes(req_msg.attributes, *attributes);
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-
-		memcpy(req_buf, &req_msg, req_len);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-			TS_CRYPTO_OPCODE_GENERATE_KEY, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				if (resp_len >= sizeof(ts_crypto_generate_key_out)) {
-
-					struct ts_crypto_generate_key_out resp_msg;
-					memcpy(&resp_msg, resp_buf, sizeof(ts_crypto_generate_key_out));
-					*id = resp_msg.id;
-				}
-				else {
-					/* Failed to decode response message */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::destroy_key(psa_key_id_t id)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_destroy_key_in req_msg;
-	size_t req_len = sizeof(ts_crypto_destroy_key_in);
-
-	req_msg.id = id;
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-
-		memcpy(req_buf, &req_msg, req_len);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-			TS_CRYPTO_OPCODE_DESTROY_KEY, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::import_key(const psa_key_attributes_t *attributes,
-						const uint8_t *data, size_t data_length, psa_key_id_t *id)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_import_key_in req_msg;
-	size_t req_fixed_len = sizeof(ts_crypto_import_key_in);
-	size_t req_len = req_fixed_len + tlv_required_space(data_length);
-
-	translate_key_attributes(req_msg.attributes, *attributes);
-
-	struct tlv_record key_record;
-	key_record.tag = TS_CRYPTO_IMPORT_KEY_IN_TAG_DATA;
-	key_record.length = data_length;
-	key_record.value = data;
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-		struct tlv_iterator req_iter;
-
-		memcpy(req_buf, &req_msg, req_fixed_len);
-
-		tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len);
-		tlv_encode(&req_iter, &key_record);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-			TS_CRYPTO_OPCODE_IMPORT_KEY, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				if (resp_len >= sizeof(ts_crypto_import_key_out)) {
-
-					struct ts_crypto_import_key_out resp_msg;
-					memcpy(&resp_msg, resp_buf, sizeof(ts_crypto_import_key_out));
-					*id = resp_msg.id;
-				}
-				else {
-					/* Failed to decode response message */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::export_key(psa_key_id_t id,
-						uint8_t *data, size_t data_size,
-						size_t *data_length)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_export_key_in req_msg;
-	size_t req_len = sizeof(ts_crypto_export_key_in);
-
-	req_msg.id = id;
-
-	*data_length = 0; /* For failure case */
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-
-		memcpy(req_buf, &req_msg, req_len);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-			TS_CRYPTO_OPCODE_EXPORT_KEY, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				struct tlv_const_iterator resp_iter;
-				struct tlv_record decoded_record;
-				tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
-
-				if (tlv_find_decode(&resp_iter,
-					TS_CRYPTO_EXPORT_KEY_OUT_TAG_DATA, &decoded_record)) {
-
-					if (decoded_record.length <= data_size) {
-
-						memcpy(data, decoded_record.value, decoded_record.length);
-						*data_length = decoded_record.length;
-					}
-					else {
-						/* Provided buffer is too small */
-						psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
-					}
-				}
-				else {
-					/* Mandatory response parameter missing */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::export_public_key(psa_key_id_t id,
-								uint8_t *data, size_t data_size, size_t *data_length)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_export_public_key_in req_msg;
-	size_t req_len = sizeof(ts_crypto_export_public_key_in);
-
-	req_msg.id = id;
-
-	*data_length = 0; /* For failure case */
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-
-		memcpy(req_buf, &req_msg, req_len);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-			TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				struct tlv_const_iterator resp_iter;
-				struct tlv_record decoded_record;
-				tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
-
-				if (tlv_find_decode(&resp_iter,
-					TS_CRYPTO_EXPORT_PUBLIC_KEY_OUT_TAG_DATA, &decoded_record)) {
-
-					if (decoded_record.length <= data_size) {
-
-						memcpy(data, decoded_record.value, decoded_record.length);
-						*data_length = decoded_record.length;
-					}
-					else {
-						/* Provided buffer is too small */
-						psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
-					}
-				}
-				else {
-					/* Mandatory response parameter missing */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::sign_hash(psa_key_id_t id, psa_algorithm_t alg,
-							const uint8_t *hash, size_t hash_length,
-							uint8_t *signature, size_t signature_size, size_t *signature_length)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_sign_hash_in req_msg;
-	size_t req_fixed_len = sizeof(ts_crypto_sign_hash_in);
-	size_t req_len = req_fixed_len + tlv_required_space(hash_length);
-
-	*signature_length = 0;  /* For failure case */
-
-	req_msg.id = id;
-	req_msg.alg = alg;
-
-	struct tlv_record hash_record;
-	hash_record.tag = TS_CRYPTO_SIGN_HASH_IN_TAG_HASH;
-	hash_record.length = hash_length;
-	hash_record.value = hash;
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-		struct tlv_iterator req_iter;
-
-		memcpy(req_buf, &req_msg, req_fixed_len);
-
-		tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len);
-		tlv_encode(&req_iter, &hash_record);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-					TS_CRYPTO_OPCODE_SIGN_HASH, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				struct tlv_const_iterator resp_iter;
-				struct tlv_record decoded_record;
-				tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
-
-				if (tlv_find_decode(&resp_iter,
-					TS_CRYPTO_SIGN_HASH_OUT_TAG_SIGNATURE, &decoded_record)) {
-
-					if (decoded_record.length <= signature_size) {
-
-						memcpy(signature, decoded_record.value, decoded_record.length);
-						*signature_length = decoded_record.length;
-					}
-					else {
-						/* Provided buffer is too small */
-						psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
-					}
-				}
-				else {
-					/* Mandatory response parameter missing */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-
-psa_status_t packedc_crypto_client::verify_hash(psa_key_id_t id, psa_algorithm_t alg,
-						const uint8_t *hash, size_t hash_length,
-						const uint8_t *signature, size_t signature_length)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_verify_hash_in req_msg;
-	size_t req_fixed_len = sizeof(ts_crypto_verify_hash_in);
-	size_t req_len = req_fixed_len +
-		tlv_required_space(hash_length) + tlv_required_space(signature_length);
-
-	req_msg.id = id;
-	req_msg.alg = alg;
-
-	struct tlv_record hash_record;
-	hash_record.tag = TS_CRYPTO_VERIFY_HASH_IN_TAG_HASH;
-	hash_record.length = hash_length;
-	hash_record.value = hash;
-
-	struct tlv_record sig_record;
-	sig_record.tag = TS_CRYPTO_VERIFY_HASH_IN_TAG_SIGNATURE;
-	sig_record.length = signature_length;
-	sig_record.value = signature;
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-		struct tlv_iterator req_iter;
-
-		memcpy(req_buf, &req_msg, req_fixed_len);
-
-		tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len);
-		tlv_encode(&req_iter, &hash_record);
-		tlv_encode(&req_iter, &sig_record);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-					TS_CRYPTO_OPCODE_VERIFY_HASH, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::asymmetric_encrypt(psa_key_id_t id, psa_algorithm_t alg,
-						const uint8_t *input, size_t input_length,
-						const uint8_t *salt, size_t salt_length,
-						uint8_t *output, size_t output_size, size_t *output_length)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_asymmetric_encrypt_in req_msg;
-	size_t req_fixed_len = sizeof(ts_crypto_asymmetric_encrypt_in);
-	size_t req_len = req_fixed_len;
-
-	*output_length = 0;  /* For failure case */
-
-	req_msg.id = id;
-	req_msg.alg = alg;
-
-	/* Mandatory parameter */
-	struct tlv_record plaintext_record;
-	plaintext_record.tag = TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_PLAINTEXT;
-	plaintext_record.length = input_length;
-	plaintext_record.value = input;
-	req_len += tlv_required_space(plaintext_record.length);
-
-	/* Optional parameter */
-	struct tlv_record salt_record;
-	salt_record.tag = TS_CRYPTO_ASYMMETRIC_ENCRYPT_IN_TAG_SALT;
-	salt_record.length = (salt) ? salt_length : 0;
-	salt_record.value = salt;
-	if (salt) req_len += tlv_required_space(salt_record.length);
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus = PSA_ERROR_GENERIC_ERROR;
-		struct tlv_iterator req_iter;
-
-		memcpy(req_buf, &req_msg, req_fixed_len);
-
-		tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len);
-		tlv_encode(&req_iter, &plaintext_record);
-		if (salt) tlv_encode(&req_iter, &salt_record);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-					TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				struct tlv_const_iterator resp_iter;
-				struct tlv_record decoded_record;
-				tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
-
-				if (tlv_find_decode(&resp_iter,
-					TS_CRYPTO_ASYMMETRIC_ENCRYPT_OUT_TAG_CIPHERTEXT, &decoded_record)) {
-
-					if (decoded_record.length <= output_size) {
-
-						memcpy(output, decoded_record.value, decoded_record.length);
-						*output_length = decoded_record.length;
-					}
-					else {
-						/* Provided buffer is too small */
-						psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
-					}
-				}
-				else {
-					/* Mandatory response parameter missing */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::asymmetric_decrypt(psa_key_id_t id, psa_algorithm_t alg,
-						const uint8_t *input, size_t input_length,
-						const uint8_t *salt, size_t salt_length,
-						uint8_t *output, size_t output_size, size_t *output_length)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_asymmetric_decrypt_in req_msg;
-	size_t req_fixed_len = sizeof(ts_crypto_asymmetric_decrypt_in);
-	size_t req_len = req_fixed_len;
-
-	*output_length = 0;  /* For failure case */
-
-	req_msg.id = id;
-	req_msg.alg = alg;
-
-	/* Mandatory parameter */
-	struct tlv_record ciphertext_record;
-	ciphertext_record.tag = TS_CRYPTO_ASYMMETRIC_DECRYPT_IN_TAG_CIPHERTEXT;
-	ciphertext_record.length = input_length;
-	ciphertext_record.value = input;
-	req_len += tlv_required_space(ciphertext_record.length);
-
-	/* Optional parameter */
-	struct tlv_record salt_record;
-	salt_record.tag = TS_CRYPTO_ASYMMETRIC_DECRYPT_IN_TAG_SALT;
-	salt_record.length = (salt) ? salt_length : 0;
-	salt_record.value = salt;
-	if (salt) req_len += tlv_required_space(salt_record.length);
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-		struct tlv_iterator req_iter;
-
-		memcpy(req_buf, &req_msg, req_fixed_len);
-
-		tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len);
-		tlv_encode(&req_iter, &ciphertext_record);
-		if (salt) tlv_encode(&req_iter, &salt_record);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-					TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				struct tlv_const_iterator resp_iter;
-				struct tlv_record decoded_record;
-				tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
-
-				if (tlv_find_decode(&resp_iter,
-					TS_CRYPTO_ASYMMETRIC_DECRYPT_OUT_TAG_PLAINTEXT, &decoded_record)) {
-
-					if (decoded_record.length <= output_size) {
-
-						memcpy(output, decoded_record.value, decoded_record.length);
-						*output_length = decoded_record.length;
-					}
-					else {
-						/* Provided buffer is too small */
-						psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
-					}
-				}
-				else {
-					/* Mandatory response parameter missing */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::generate_random(uint8_t *output, size_t output_size)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_generate_random_in req_msg;
-	size_t req_len = sizeof(ts_crypto_generate_random_in);
-
-	req_msg.size = output_size;
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-
-		memcpy(req_buf, &req_msg, req_len);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-				TS_CRYPTO_OPCODE_GENERATE_RANDOM, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				struct tlv_const_iterator resp_iter;
-				struct tlv_record decoded_record;
-				tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
-
-				if (tlv_find_decode(&resp_iter,
-					TS_CRYPTO_GENERATE_RANDOM_OUT_TAG_RANDOM_BYTES, &decoded_record)) {
-
-					if (decoded_record.length <= output_size) {
-
-						memcpy(output, decoded_record.value, decoded_record.length);
-					}
-					else {
-						/* Provided buffer is too small */
-						psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
-					}
-				}
-				else {
-					/* Mandatory response parameter missing */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::hash_setup(uint32_t *op_handle,
-	psa_algorithm_t alg)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_hash_setup_in req_msg;
-	size_t req_len = sizeof(ts_crypto_hash_setup_in);
-
-	req_msg.alg = alg;
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-
-		memcpy(req_buf, &req_msg, req_len);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-			TS_CRYPTO_OPCODE_HASH_SETUP, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				if (resp_len >= sizeof(ts_crypto_hash_setup_out)) {
-
-					struct ts_crypto_hash_setup_out resp_msg;
-					memcpy(&resp_msg, resp_buf, sizeof(ts_crypto_hash_setup_out));
-					*op_handle = resp_msg.op_handle;
-				}
-				else {
-					/* Failed to decode response message */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::hash_update(uint32_t op_handle,
-	const uint8_t *input, size_t input_length)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_hash_update_in req_msg;
-	size_t req_fixed_len = sizeof(ts_crypto_hash_update_in);
-	size_t req_len = req_fixed_len;
-
-	req_msg.op_handle = op_handle;
-
-	/* Mandatory input data parameter */
-	struct tlv_record data_record;
-	data_record.tag = TS_CRYPTO_HASH_UPDATE_IN_TAG_DATA;
-	data_record.length = input_length;
-	data_record.value = input;
-	req_len += tlv_required_space(data_record.length);
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-		struct tlv_iterator req_iter;
-
-		memcpy(req_buf, &req_msg, req_fixed_len);
-
-		tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len);
-		tlv_encode(&req_iter, &data_record);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-					TS_CRYPTO_OPCODE_HASH_UPDATE, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-psa_status_t packedc_crypto_client::hash_finish(uint32_t op_handle,
-							uint8_t *hash, size_t hash_size, size_t *hash_length)
-{
-	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
-	struct ts_crypto_hash_finish_in req_msg;
-	size_t req_fixed_len = sizeof(ts_crypto_hash_finish_in);
-	size_t req_len = req_fixed_len;
-
-	*hash_length = 0;
-	req_msg.op_handle = op_handle;
-
-	rpc_call_handle call_handle;
-	uint8_t *req_buf;
-
-	call_handle = rpc_caller_begin(m_client.caller, &req_buf, req_len);
-
-	if (call_handle) {
-
-		uint8_t *resp_buf;
-		size_t resp_len;
-		int opstatus;
-
-		memcpy(req_buf, &req_msg, req_fixed_len);
-
-		m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
-					TS_CRYPTO_OPCODE_HASH_FINISH, &opstatus, &resp_buf, &resp_len);
-
-		if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
-
-			psa_status = opstatus;
-
-			if (psa_status == PSA_SUCCESS) {
-
-				struct tlv_const_iterator resp_iter;
-				struct tlv_record decoded_record;
-				tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);
-
-				if (tlv_find_decode(&resp_iter,
-					TS_CRYPTO_HASH_FINISH_OUT_TAG_HASH, &decoded_record)) {
-
-					if (decoded_record.length <= hash_size) {
-
-						memcpy(hash, decoded_record.value, decoded_record.length);
-						*hash_length = decoded_record.length;
-					}
-					else {
-						/* Provided buffer is too small */
-						psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
-					}
-				}
-				else {
-					/* Mandatory response parameter missing */
-					psa_status = PSA_ERROR_GENERIC_ERROR;
-				}
-			}
-		}
-
-		rpc_caller_end(m_client.caller, call_handle);
-	}
-
-	return psa_status;
-}
-
-void packedc_crypto_client::translate_key_attributes(
-	struct ts_crypto_key_attributes &proto_attributes,
-	const psa_key_attributes_t &psa_attributes)
-{
-	proto_attributes.type = psa_get_key_type(&psa_attributes);
-	proto_attributes.key_bits = psa_get_key_bits(&psa_attributes);
-	proto_attributes.lifetime = psa_get_key_lifetime(&psa_attributes);
-	proto_attributes.id = psa_get_key_id(&psa_attributes);
-
-	proto_attributes.policy.usage = psa_get_key_usage_flags(&psa_attributes);
-	proto_attributes.policy.alg = psa_get_key_algorithm(&psa_attributes);
- }
diff --git a/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.h b/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.h
deleted file mode 100644
index be4bb66..0000000
--- a/components/service/crypto/client/cpp/packed-c/packedc_crypto_client.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PACKEDC_CRYPTO_CLIENT_H
-#define PACKEDC_CRYPTO_CLIENT_H
-
-#include <service/crypto/client/cpp/crypto_client.h>
-#include <protocols/service/crypto/packed-c/key_attributes.h>
-
-/*
- * A concrete crypto_client that uses the packed-c based crypto access protocol
- */
-class packedc_crypto_client : public crypto_client
-{
-public:
-	packedc_crypto_client();
-	packedc_crypto_client(struct rpc_caller *caller);
-	virtual ~packedc_crypto_client();
-
-	/* Key lifecycle methods */
-	psa_status_t generate_key(const psa_key_attributes_t *attributes, psa_key_id_t *id);
-	psa_status_t destroy_key(psa_key_id_t id);
-	psa_status_t import_key(const psa_key_attributes_t *attributes,
-							const uint8_t *data, size_t data_length, psa_key_id_t *id);
-
-	/* Key export methods */
-	psa_status_t export_key(psa_key_id_t id,
-							uint8_t *data, size_t data_size,
-							size_t *data_length);
-	psa_status_t export_public_key(psa_key_id_t id,
-							uint8_t *data, size_t data_size, size_t *data_length);
-
-	/* Sign/verify methods */
-	psa_status_t sign_hash(psa_key_id_t id, psa_algorithm_t alg,
-							const uint8_t *hash, size_t hash_length,
-							uint8_t *signature, size_t signature_size, size_t *signature_length);
-	psa_status_t verify_hash(psa_key_id_t id, psa_algorithm_t alg,
-							const uint8_t *hash, size_t hash_length,
-							const uint8_t *signature, size_t signature_length);
-
-	/* Asymmetric encrypt/decrypt */
-	psa_status_t asymmetric_encrypt(psa_key_id_t id, psa_algorithm_t alg,
-							const uint8_t *input, size_t input_length,
-							const uint8_t *salt, size_t salt_length,
-							uint8_t *output, size_t output_size, size_t *output_length);
-	psa_status_t asymmetric_decrypt(psa_key_id_t id, psa_algorithm_t alg,
-							const uint8_t *input, size_t input_length,
-							const uint8_t *salt, size_t salt_length,
-							uint8_t *output, size_t output_size, size_t *output_length);
-
-	/* Random number generation */
-	psa_status_t generate_random(uint8_t *output, size_t output_size);
-
-	/* Hash methods */
-	psa_status_t hash_setup(uint32_t *op_handle,
-							psa_algorithm_t alg);
-	psa_status_t hash_update(uint32_t op_handle,
-							const uint8_t *input, size_t input_length);
-	psa_status_t hash_finish(uint32_t op_handle,
-							uint8_t *hash, size_t hash_size, size_t *hash_length);
-
-private:
-
-	void translate_key_attributes(struct ts_crypto_key_attributes &proto_attributes,
-							const psa_key_attributes_t &psa_attributes);
-};
-
-#endif /* PACKEDC_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.h b/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.h
deleted file mode 100644
index bc407d1..0000000
--- a/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PROTOBUF_CRYPTO_CLIENT_H
-#define PROTOBUF_CRYPTO_CLIENT_H
-
-#include <service/crypto/client/cpp/crypto_client.h>
-#include <service/crypto/protobuf/key_attributes.pb.h>
-
-/*
- * A concrete crypto_client that uses the protobuf based crypto access protocol
- */
-class protobuf_crypto_client : public crypto_client
-{
-public:
-	protobuf_crypto_client();
-	protobuf_crypto_client(struct rpc_caller *caller);
-	virtual ~protobuf_crypto_client();
-
-	/* Key lifecycle methods */
-	psa_status_t generate_key(const psa_key_attributes_t *attributes, psa_key_id_t *id);
-	psa_status_t destroy_key(psa_key_id_t id);
-	psa_status_t import_key(const psa_key_attributes_t *attributes,
-							const uint8_t *data, size_t data_length, psa_key_id_t *id);
-
-	/* Key export methods */
-	psa_status_t export_key(psa_key_id_t id,
-							uint8_t *data, size_t data_size,
-							size_t *data_length);
-	psa_status_t export_public_key(psa_key_id_t id,
-							uint8_t *data, size_t data_size, size_t *data_length);
-
-	/* Sign/verify methods */
-	psa_status_t sign_hash(psa_key_id_t id, psa_algorithm_t alg,
-							const uint8_t *hash, size_t hash_length,
-							uint8_t *signature, size_t signature_size, size_t *signature_length);
-	psa_status_t verify_hash(psa_key_id_t id, psa_algorithm_t alg,
-							const uint8_t *hash, size_t hash_length,
-							const uint8_t *signature, size_t signature_length);
-
-	/* Asymmetric encrypt/decrypt */
-	psa_status_t asymmetric_encrypt(psa_key_id_t id, psa_algorithm_t alg,
-							const uint8_t *input, size_t input_length,
-							const uint8_t *salt, size_t salt_length,
-							uint8_t *output, size_t output_size, size_t *output_length);
-	psa_status_t asymmetric_decrypt(psa_key_id_t id, psa_algorithm_t alg,
-							const uint8_t *input, size_t input_length,
-							const uint8_t *salt, size_t salt_length,
-							uint8_t *output, size_t output_size, size_t *output_length);
-
-	/* Random number generation */
-	psa_status_t generate_random(uint8_t *output, size_t output_size);
-
-	/* Hash methods */
-	psa_status_t hash_setup(uint32_t *op_handle,
-							psa_algorithm_t alg);
-	psa_status_t hash_update(uint32_t op_handle,
-							const uint8_t *input, size_t input_length);
-	psa_status_t hash_finish(uint32_t op_handle,
-							uint8_t *hash, size_t hash_size, size_t *hash_length);
-
-private:
-
-	void translate_key_attributes(ts_crypto_KeyAttributes &proto_attributes,
-							const psa_key_attributes_t &psa_attributes);
-};
-
-#endif /* PROTOBUF_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/cpp/packed-c/component.cmake b/components/service/crypto/client/cpp/protocol/packed-c/component.cmake
similarity index 100%
rename from components/service/crypto/client/cpp/packed-c/component.cmake
rename to components/service/crypto/client/cpp/protocol/packed-c/component.cmake
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
new file mode 100644
index 0000000..74c07db
--- /dev/null
+++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "packedc_crypto_client.h"
+#include <service/crypto/client/caller/packed-c/crypto_caller.h>
+#include <rpc_caller.h>
+
+
+packedc_crypto_client::packedc_crypto_client() :
+	crypto_client()
+{
+
+}
+
+packedc_crypto_client::packedc_crypto_client(struct rpc_caller *caller) :
+	crypto_client(caller)
+{
+
+}
+
+packedc_crypto_client::~packedc_crypto_client()
+{
+
+}
+
+psa_status_t packedc_crypto_client::generate_key(
+	const psa_key_attributes_t *attributes,
+	psa_key_id_t *id)
+{
+	return crypto_caller_generate_key(&m_client, attributes, id);
+}
+
+psa_status_t packedc_crypto_client::destroy_key(
+	psa_key_id_t id)
+{
+	return crypto_caller_destroy_key(&m_client, id);
+}
+
+psa_status_t packedc_crypto_client::copy_key(
+	psa_key_id_t source_key,
+	const psa_key_attributes_t *attributes,
+	psa_key_id_t *target_key)
+{
+	return crypto_caller_copy_key(&m_client, source_key, attributes, target_key);
+}
+
+psa_status_t packedc_crypto_client::purge_key(
+	psa_key_id_t id)
+{
+	return crypto_caller_purge_key(&m_client, id);
+}
+
+psa_status_t packedc_crypto_client::get_key_attributes(
+	psa_key_id_t id,
+	psa_key_attributes_t *attributes)
+{
+	return crypto_caller_get_key_attributes(&m_client, id, attributes);
+}
+
+psa_status_t packedc_crypto_client::import_key(
+	const psa_key_attributes_t *attributes,
+	const uint8_t *data, size_t data_length,
+	psa_key_id_t *id)
+{
+	return crypto_caller_import_key(&m_client, attributes,
+		data, data_length, id);
+}
+
+psa_status_t packedc_crypto_client::export_key(
+	psa_key_id_t id,
+	uint8_t *data, size_t data_size,
+	size_t *data_length)
+{
+	return crypto_caller_export_key(&m_client, id,
+		data, data_size, data_length);
+}
+
+psa_status_t packedc_crypto_client::export_public_key(
+	psa_key_id_t id,
+	uint8_t *data, size_t data_size, size_t *data_length)
+{
+	return crypto_caller_export_public_key(&m_client, id,
+		data, data_size, data_length);
+}
+
+psa_status_t packedc_crypto_client::sign_hash(
+	psa_key_id_t id, psa_algorithm_t alg,
+	const uint8_t *hash, size_t hash_length,
+	uint8_t *signature, size_t signature_size, size_t *signature_length)
+{
+	return crypto_caller_sign_hash(&m_client, id, alg,
+		hash, hash_length,
+		signature, signature_size, signature_length);
+}
+
+psa_status_t packedc_crypto_client::verify_hash(
+	psa_key_id_t id, psa_algorithm_t alg,
+	const uint8_t *hash, size_t hash_length,
+	const uint8_t *signature, size_t signature_length)
+{
+	return crypto_caller_verify_hash(&m_client, id, alg,
+		hash, hash_length,
+		signature, signature_length);
+}
+
+psa_status_t packedc_crypto_client::asymmetric_encrypt(
+	psa_key_id_t id, psa_algorithm_t alg,
+	const uint8_t *input, size_t input_length,
+	const uint8_t *salt, size_t salt_length,
+	uint8_t *output, size_t output_size, size_t *output_length)
+{
+	return crypto_caller_asymmetric_encrypt(&m_client, id, alg,
+		input, input_length,
+		salt, salt_length,
+		output, output_size, output_length);
+}
+
+psa_status_t packedc_crypto_client::asymmetric_decrypt(
+	psa_key_id_t id, psa_algorithm_t alg,
+	const uint8_t *input, size_t input_length,
+	const uint8_t *salt, size_t salt_length,
+	uint8_t *output, size_t output_size, size_t *output_length)
+{
+	return crypto_caller_asymmetric_decrypt(&m_client, id, alg,
+		input, input_length,
+		salt, salt_length,
+		output, output_size, output_length);
+}
+
+psa_status_t packedc_crypto_client::generate_random(
+	uint8_t *output, size_t output_size)
+{
+	return crypto_caller_generate_random(&m_client,
+		output, output_size);
+}
+
+psa_status_t packedc_crypto_client::hash_setup(
+	uint32_t *op_handle,
+	psa_algorithm_t alg)
+{
+	return crypto_caller_hash_setup(&m_client,
+		op_handle, alg);
+}
+
+psa_status_t packedc_crypto_client::hash_update(
+	uint32_t op_handle,
+	const uint8_t *input, size_t input_length)
+{
+	return crypto_caller_hash_update(&m_client,
+		op_handle, input, input_length);
+}
+
+psa_status_t packedc_crypto_client::hash_finish(
+	uint32_t op_handle,
+	uint8_t *hash, size_t hash_size, size_t *hash_length)
+{
+	return crypto_caller_hash_finish(&m_client,
+		op_handle, hash, hash_size, hash_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
new file mode 100644
index 0000000..0cbc666
--- /dev/null
+++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PACKEDC_CRYPTO_CLIENT_H
+#define PACKEDC_CRYPTO_CLIENT_H
+
+#include <service/crypto/client/cpp/crypto_client.h>
+#include <protocols/service/crypto/packed-c/key_attributes.h>
+
+/*
+ * A concrete crypto_client that uses the packed-c based crypto access protocol
+ */
+class packedc_crypto_client : public crypto_client
+{
+public:
+	packedc_crypto_client();
+	packedc_crypto_client(struct rpc_caller *caller);
+	virtual ~packedc_crypto_client();
+
+	/* Key lifecycle methods */
+	psa_status_t generate_key(
+		const psa_key_attributes_t *attributes,
+		psa_key_id_t *id);
+
+	psa_status_t destroy_key(
+		psa_key_id_t id);
+
+	psa_status_t import_key(
+		const psa_key_attributes_t *attributes,
+		const uint8_t *data, size_t data_length,
+		psa_key_id_t *id);
+
+	psa_status_t copy_key(
+		psa_key_id_t source_key,
+		const psa_key_attributes_t *attributes,
+		psa_key_id_t *target_key);
+
+	psa_status_t purge_key(
+		psa_key_id_t id);
+
+	psa_status_t get_key_attributes(
+		psa_key_id_t id,
+		psa_key_attributes_t *attributes);
+
+	/* Key export methods */
+	psa_status_t export_key(
+		psa_key_id_t id,
+		uint8_t *data, size_t data_size, size_t *data_length);
+
+	psa_status_t export_public_key(
+		psa_key_id_t id,
+		uint8_t *data, size_t data_size, size_t *data_length);
+
+	/* Sign/verify methods */
+	psa_status_t sign_hash(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *hash, size_t hash_length,
+		uint8_t *signature, size_t signature_size, size_t *signature_length);
+
+	psa_status_t verify_hash(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *hash, size_t hash_length,
+		const uint8_t *signature, size_t signature_length);
+
+	/* Asymmetric encrypt/decrypt */
+	psa_status_t asymmetric_encrypt(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *input, size_t input_length,
+		const uint8_t *salt, size_t salt_length,
+		uint8_t *output, size_t output_size, size_t *output_length);
+
+	psa_status_t asymmetric_decrypt(psa_key_id_t id, psa_algorithm_t alg,
+							const uint8_t *input, size_t input_length,
+							const uint8_t *salt, size_t salt_length,
+							uint8_t *output, size_t output_size, size_t *output_length);
+
+	/* Random number generation */
+	psa_status_t generate_random(uint8_t *output, size_t output_size);
+
+	/* Hash methods */
+	psa_status_t hash_setup(uint32_t *op_handle,
+							psa_algorithm_t alg);
+	psa_status_t hash_update(uint32_t op_handle,
+							const uint8_t *input, size_t input_length);
+	psa_status_t hash_finish(uint32_t op_handle,
+							uint8_t *hash, size_t hash_size, size_t *hash_length);
+
+};
+
+#endif /* PACKEDC_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/cpp/protobuf/component.cmake b/components/service/crypto/client/cpp/protocol/protobuf/component.cmake
similarity index 100%
rename from components/service/crypto/client/cpp/protobuf/component.cmake
rename to components/service/crypto/client/cpp/protocol/protobuf/component.cmake
diff --git a/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.cpp b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp
similarity index 97%
rename from components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.cpp
rename to components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp
index 1823a4a..7629f7d 100644
--- a/components/service/crypto/client/cpp/protobuf/protobuf_crypto_client.cpp
+++ b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp
@@ -194,6 +194,28 @@
 	return psa_status;
 }
 
+psa_status_t protobuf_crypto_client::copy_key(
+	psa_key_id_t source_key,
+	const psa_key_attributes_t *attributes,
+	psa_key_id_t *target_key)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::purge_key(
+	psa_key_id_t id)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t protobuf_crypto_client::get_key_attributes(
+	psa_key_id_t id,
+	psa_key_attributes_t *attributes)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+
 psa_status_t protobuf_crypto_client::export_key(psa_key_id_t id,
 						uint8_t *data, size_t data_size,
 						size_t *data_length)
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
new file mode 100644
index 0000000..c04d82d
--- /dev/null
+++ b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PROTOBUF_CRYPTO_CLIENT_H
+#define PROTOBUF_CRYPTO_CLIENT_H
+
+#include <service/crypto/client/cpp/crypto_client.h>
+#include <service/crypto/protobuf/key_attributes.pb.h>
+
+/*
+ * A concrete crypto_client that uses the protobuf based crypto access protocol
+ */
+class protobuf_crypto_client : public crypto_client
+{
+public:
+	protobuf_crypto_client();
+	protobuf_crypto_client(struct rpc_caller *caller);
+	virtual ~protobuf_crypto_client();
+
+	/* Key lifecycle methods */
+	psa_status_t generate_key(
+		const psa_key_attributes_t *attributes,
+		psa_key_id_t *id);
+
+	psa_status_t destroy_key(
+		psa_key_id_t id);
+
+	psa_status_t import_key(
+		const psa_key_attributes_t *attributes,
+		const uint8_t *data, size_t data_length, psa_key_id_t *id);
+
+	psa_status_t copy_key(
+		psa_key_id_t source_key,
+		const psa_key_attributes_t *attributes,
+		psa_key_id_t *target_key);
+
+	psa_status_t purge_key(
+		psa_key_id_t id);
+
+	psa_status_t get_key_attributes(
+		psa_key_id_t id,
+		psa_key_attributes_t *attributes);
+
+	/* Key export methods */
+	psa_status_t export_key(
+		psa_key_id_t id,
+		uint8_t *data, size_t data_size,
+		size_t *data_length);
+
+	psa_status_t export_public_key(
+		psa_key_id_t id,
+		uint8_t *data, size_t data_size, size_t *data_length);
+
+	/* Sign/verify methods */
+	psa_status_t sign_hash(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *hash, size_t hash_length,
+		uint8_t *signature, size_t signature_size, size_t *signature_length);
+
+	psa_status_t verify_hash(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *hash, size_t hash_length,
+		const uint8_t *signature, size_t signature_length);
+
+	/* Asymmetric encrypt/decrypt */
+	psa_status_t asymmetric_encrypt(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *input, size_t input_length,
+		const uint8_t *salt, size_t salt_length,
+		uint8_t *output, size_t output_size, size_t *output_length);
+
+	psa_status_t asymmetric_decrypt(
+		psa_key_id_t id,
+		psa_algorithm_t alg,
+		const uint8_t *input, size_t input_length,
+		const uint8_t *salt, size_t salt_length,
+		uint8_t *output, size_t output_size, size_t *output_length);
+
+	/* Random number generation */
+	psa_status_t generate_random(
+		uint8_t *output, size_t output_size);
+
+	/* Hash methods */
+	psa_status_t hash_setup(
+		uint32_t *op_handle,
+		psa_algorithm_t alg);
+
+	psa_status_t hash_update(
+		uint32_t op_handle,
+		const uint8_t *input, size_t input_length);
+
+	psa_status_t hash_finish(
+		uint32_t op_handle,
+		uint8_t *hash, size_t hash_size, size_t *hash_length);
+
+private:
+
+	void translate_key_attributes(
+		ts_crypto_KeyAttributes &proto_attributes,
+		const psa_key_attributes_t &psa_attributes);
+};
+
+#endif /* PROTOBUF_CRYPTO_CLIENT_H */