Add CBOR serializer/deserializer components

Adds components to serialize/deserialize crypto messages using CBOR.
Uses the auto-generated code from ZCBOR processing of the CDDL
interface definition.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I4e16a542ee4c29967fe88817f3a33d9309fdb540
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller.c
new file mode 100644
index 0000000..a154e10
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include "cbor_crypto_caller.h"
+
+#define MAX_REQ_LEN		(1000)
+
+psa_status_t cbor_crypto_caller_invoke(struct service_client *context,
+	uint32_t opcode,
+	struct crypto_proto_req *req_msg,
+	struct crypto_proto_resp *resp_msg,
+	rpc_call_handle *call_handle)
+{
+	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+	uint_fast8_t zcbor_status;
+	size_t serialized_msg_len = 0;
+	uint8_t serialize_buf[MAX_REQ_LEN];
+
+	*call_handle = 0;
+	req_msg->_crypto_proto_req_union_choice = opcode;
+
+	zcbor_status = cbor_encode_crypto_proto_req(
+		serialize_buf, MAX_REQ_LEN,
+		req_msg, &serialized_msg_len);
+
+	if (zcbor_status != ZCBOR_SUCCESS)
+		return PSA_ERROR_GENERIC_ERROR;
+
+	uint8_t *req_buf;
+	*call_handle = rpc_caller_begin(context->caller, &req_buf, serialized_msg_len);
+
+	if (!*call_handle)
+		return PSA_ERROR_GENERIC_ERROR;
+
+	memcpy(req_buf, serialize_buf, serialized_msg_len);
+
+	uint8_t *resp_buf;
+	size_t resp_len;
+	rpc_opstatus_t opstatus;
+
+	context->rpc_status = rpc_caller_invoke(context->caller, *call_handle,
+		opcode, &opstatus, &resp_buf, &resp_len);
+
+	if (context->rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+		psa_status = opstatus;
+
+		if ((psa_status == PSA_SUCCESS) && resp_msg) {
+
+			size_t decode_len;
+			zcbor_status = cbor_decode_crypto_proto_resp(
+				resp_buf, resp_len,
+				resp_msg, &decode_len);
+
+			if (zcbor_status != ZCBOR_SUCCESS)
+				psa_status = PSA_ERROR_GENERIC_ERROR;
+		}
+	}
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller.h
new file mode 100644
index 0000000..0ce5102
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef CBOR_CRYPTO_CALLER_H
+#define CBOR_CRYPTO_CALLER_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+#include "crypto-proto_encode.h"
+#include "crypto-proto_decode.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_invoke(struct service_client *context,
+	uint32_t opcode,
+	struct crypto_proto_req *req_msg,
+	struct crypto_proto_resp *resp_msg,
+	rpc_call_handle *call_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_decrypt.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_decrypt.c
new file mode 100644
index 0000000..cb3506b
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_decrypt.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_asymmetric_decrypt.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_asymmetric_decrypt(struct service_client *context,
+	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 crypto_proto_req req_msg;
+	struct crypto_asymmetric_decryption_req *req_params =
+		&req_msg._union__asymmetric_decrypt_req__crypto_asymmetric_decryption_req;
+
+	/* Prepare request message */
+	req_params->_crypto_asymmetric_decryption_req_crypto_parameter_key_id
+		= id;
+	req_params->_crypto_asymmetric_decryption_req_crypto_parameter_alg
+		= alg;
+	req_params->_crypto_asymmetric_decryption_req_crypto_parameter_ciphertext.value
+		= input;
+	req_params->_crypto_asymmetric_decryption_req_crypto_parameter_ciphertext.len
+		= input_length;
+	req_params->_crypto_asymmetric_decryption_req_crypto_parameter_salt.value
+		= salt;
+	req_params->_crypto_asymmetric_decryption_req_crypto_parameter_salt.len
+		= salt_length;
+
+	rpc_call_handle call_handle = 0;
+	struct crypto_proto_resp resp_msg;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT, &req_msg, &resp_msg, &call_handle);
+
+	if (psa_status == PSA_SUCCESS) {
+
+		/* Process response message */
+		const struct crypto_asymmetric_decryption_resp *resp_params =
+			&resp_msg._union__asymmetric_decrypt_resp__crypto_asymmetric_decryption_resp;
+
+		const struct zcbor_string *plaintext_param =
+			&resp_params->_crypto_asymmetric_decryption_resp_crypto_parameter_plaintext;
+
+		if (plaintext_param->len <= output_size) {
+
+			memcpy(output, plaintext_param->value, plaintext_param->len);
+			*output_length = plaintext_param->len;
+		}
+		else {
+
+			psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+		}
+	}
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_decrypt.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_decrypt.h
new file mode 100644
index 0000000..c26b3b7
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_decrypt.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_ASYMMETRIC_DECRYPT_H
+#define CBOR_CRYPTO_CALLER_ASYMMETRIC_DECRYPT_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_asymmetric_decrypt(struct service_client *context,
+	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);
+
+
+static inline psa_status_t crypto_caller_asymmetric_decrypt(struct service_client *context,
+	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 cbor_crypto_caller_asymmetric_decrypt(context,
+		id, alg,
+		input, input_length,
+		salt, salt_length,
+		output, output_size, output_length);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_ASYMMETRIC_DECRYPT_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_encrypt.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_encrypt.c
new file mode 100644
index 0000000..5ac92f2
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_encrypt.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_asymmetric_encrypt.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_asymmetric_encrypt(struct service_client *context,
+	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 crypto_proto_req req_msg;
+	struct crypto_asymmetric_encryption_req *req_params =
+		&req_msg._union__asymmetric_encrypt_req__crypto_asymmetric_encryption_req;
+
+	/* Prepare request message */
+	req_params->_crypto_asymmetric_encryption_req_crypto_parameter_key_id
+		= id;
+	req_params->_crypto_asymmetric_encryption_req_crypto_parameter_alg
+		= alg;
+	req_params->_crypto_asymmetric_encryption_req_crypto_parameter_plaintext.value
+		= input;
+	req_params->_crypto_asymmetric_encryption_req_crypto_parameter_plaintext.len
+		= input_length;
+	req_params->_crypto_asymmetric_encryption_req_crypto_parameter_salt.value
+		= salt;
+	req_params->_crypto_asymmetric_encryption_req_crypto_parameter_salt.len
+		= salt_length;
+
+	rpc_call_handle call_handle = 0;
+	struct crypto_proto_resp resp_msg;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT, &req_msg, &resp_msg, &call_handle);
+
+	if (psa_status == PSA_SUCCESS) {
+
+		/* Process response message */
+		const struct crypto_asymmetric_encryption_resp *resp_params =
+			&resp_msg._union__asymmetric_encrypt_resp__crypto_asymmetric_encryption_resp;
+
+		const struct zcbor_string *ciphertext_param =
+			&resp_params->_crypto_asymmetric_encryption_resp_crypto_parameter_ciphertext;
+
+		if (ciphertext_param->len <= output_size) {
+
+			memcpy(output, ciphertext_param->value, ciphertext_param->len);
+			*output_length = ciphertext_param->len;
+		}
+		else {
+
+			psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+		}
+	}
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_encrypt.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_encrypt.h
new file mode 100644
index 0000000..2c449dd
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_asymmetric_encrypt.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_ASYMMETRIC_ENCRYPT_H
+#define CBOR_CRYPTO_CALLER_ASYMMETRIC_ENCRYPT_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_asymmetric_encrypt(struct service_client *context,
+	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);
+
+static inline psa_status_t crypto_caller_asymmetric_encrypt(struct service_client *context,
+	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 cbor_crypto_caller_asymmetric_encrypt(context,
+		id, alg,
+		input, input_length,
+		salt, salt_length,
+		output, output_size, output_length);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_ASYMMETRIC_ENCRYPT_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_destroy_key.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_destroy_key.c
new file mode 100644
index 0000000..9d57df3
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_destroy_key.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_DESTROY_KEY_H
+#define CBOR_CRYPTO_CALLER_DESTROY_KEY_H
+
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_destroy_key.h"
+#include "crypto-proto_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_destroy_key(struct service_client *context,
+    psa_key_id_t id)
+{
+	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+	struct crypto_proto_req req_msg;
+	struct crypto_destroy_key_req *req_params =
+		&req_msg._union__destroy_key_req__crypto_destroy_key_req;
+
+	/* Prepare request message */
+	req_params->_crypto_destroy_key_req_crypto_parameter_key_id
+		= id;
+
+	rpc_call_handle call_handle = 0;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_DESTROY_KEY, &req_msg, NULL, &call_handle);
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_DESTROY_KEY_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_destroy_key.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_destroy_key.h
new file mode 100644
index 0000000..2cfc4f0
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_destroy_key.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_DESTROY_KEY_H
+#define CBOR_CRYPTO_CALLER_DESTROY_KEY_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_destroy_key(
+	struct service_client *context,
+	psa_key_id_t id);
+
+static inline psa_status_t crypto_caller_destroy_key(
+	struct service_client *context,
+	psa_key_id_t id)
+{
+	return cbor_crypto_caller_destroy_key(context, id);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_DESTROY_KEY_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_key.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_key.c
new file mode 100644
index 0000000..de00b24
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_key.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_export_key.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_export_key(
+	struct service_client *context,
+	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 crypto_proto_req req_msg;
+	struct crypto_export_key_req *req_params =
+		&req_msg._union__export_key_req__crypto_export_key_req;
+
+	/* Prepare request message */
+	req_params->_crypto_export_key_req_crypto_parameter_key_id
+		= id;
+
+	rpc_call_handle call_handle = 0;
+	struct crypto_proto_resp resp_msg;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_EXPORT_KEY, &req_msg, &resp_msg, &call_handle);
+
+	if (psa_status == PSA_SUCCESS) {
+
+		/* Process response message */
+		const struct crypto_export_key_resp *resp_params =
+			&resp_msg._union__export_key_resp__crypto_export_key_resp;
+
+		const struct zcbor_string *data_param =
+			&resp_params->_crypto_export_key_resp_crypto_parameter_data;
+
+		if (data_param->len <= data_size) {
+
+			memcpy(data, data_param->value, data_param->len);
+			*data_length = data_param->len;
+		}
+		else {
+
+			psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+		}
+	}
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_key.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_key.h
new file mode 100644
index 0000000..57ee543
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_key.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_EXPORT_KEY_H
+#define CBOR_CRYPTO_CALLER_EXPORT_KEY_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_export_key(
+	struct service_client *context,
+	psa_key_id_t id,
+	uint8_t *data, size_t data_size, size_t *data_length);
+
+static inline psa_status_t crypto_caller_export_key(
+	struct service_client *context,
+	psa_key_id_t id,
+	uint8_t *data, size_t data_size, size_t *data_length)
+{
+	return cbor_crypto_caller_export_key(
+		context, id,
+		data, data_size, data_length);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_EXPORT_KEY_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_public_key.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_public_key.c
new file mode 100644
index 0000000..d6d04d0
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_public_key.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_EXPORT_PUBLIC_KEY_H
+#define CBOR_CRYPTO_CALLER_EXPORT_PUBLIC_KEY_H
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_export_public_key.h"
+#include "crypto-proto_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_export_public_key(
+	struct service_client *context,
+	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 crypto_proto_req req_msg;
+	struct crypto_export_key_req *req_params =
+		&req_msg._union__export_public_key_req__crypto_export_key_req;
+
+	/* Prepare request message */
+	req_params->_crypto_export_key_req_crypto_parameter_key_id
+		= id;
+
+	rpc_call_handle call_handle = 0;
+	struct crypto_proto_resp resp_msg;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY, &req_msg, &resp_msg, &call_handle);
+
+	if (psa_status == PSA_SUCCESS) {
+
+		/* Process response message */
+		const struct crypto_export_key_resp *resp_params =
+			&resp_msg._union__export_public_key_resp__crypto_export_key_resp;
+
+		const struct zcbor_string *data_param =
+			&resp_params->_crypto_export_key_resp_crypto_parameter_data;
+
+		if (data_param->len <= data_size) {
+
+			memcpy(data, data_param->value, data_param->len);
+			*data_length = data_param->len;
+		}
+		else {
+
+			psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+		}
+	}
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_EXPORT_PUBLIC_KEY_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_public_key.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_public_key.h
new file mode 100644
index 0000000..dd20a7a
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_export_public_key.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_EXPORT_PUBLIC_KEY_H
+#define CBOR_CRYPTO_CALLER_EXPORT_PUBLIC_KEY_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_export_public_key(
+	struct service_client *context,
+	psa_key_id_t id,
+	uint8_t *data, size_t data_size, size_t *data_length);
+
+static inline psa_status_t crypto_caller_export_public_key(
+	struct service_client *context,
+	psa_key_id_t id,
+	uint8_t *data, size_t data_size, size_t *data_length)
+{
+	return cbor_crypto_caller_export_public_key(
+		context, id,
+		data, data_size, data_length);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_EXPORT_PUBLIC_KEY_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_key.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_key.c
new file mode 100644
index 0000000..f38e62a
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_key.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_generate_key.h"
+#include "cbor_crypto_caller_key_attributes.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_generate_key(
+	struct service_client *context,
+	const psa_key_attributes_t *attributes,
+	psa_key_id_t *id)
+{
+	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+	struct crypto_proto_req req_msg;
+	struct crypto_generate_key_req *req_params =
+		&req_msg._union__generate_key_req__crypto_generate_key_req;
+
+	/* Prepare request message */
+	cbor_crypto_caller_translate_key_attributes_to_proto(
+		&req_params->_crypto_generate_key_req_crypto_parameter_attributes,
+		attributes);
+
+	rpc_call_handle call_handle = 0;
+	struct crypto_proto_resp resp_msg;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_GENERATE_KEY, &req_msg, &resp_msg, &call_handle);
+
+	if (psa_status == PSA_SUCCESS) {
+
+		/* Process response message */
+		const struct crypto_generate_key_resp *resp_params =
+			&resp_msg._union__generate_key_resp__crypto_generate_key_resp;
+
+		*id = resp_params->_crypto_generate_key_resp_crypto_parameter_key_id;
+	}
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_key.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_key.h
new file mode 100644
index 0000000..52e06d1
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_key.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_GENERATE_KEY_H
+#define CBOR_CRYPTO_CALLER_GENERATE_KEY_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_generate_key(
+	struct service_client *context,
+	const psa_key_attributes_t *attributes,
+	psa_key_id_t *id);
+
+static inline psa_status_t crypto_caller_generate_key(
+	struct service_client *context,
+	const psa_key_attributes_t *attributes,
+	psa_key_id_t *id)
+{
+	return cbor_crypto_caller_generate_key(context, attributes, id);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_GENERATE_KEY_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_random.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_random.c
new file mode 100644
index 0000000..85583b8
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_random.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_generate_random.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_generate_random(
+	struct service_client *context,
+	uint8_t *output, size_t output_size)
+{
+	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+	struct crypto_proto_req req_msg;
+	struct crypto_generate_random_req *req_params =
+		&req_msg._union__generate_random_req__crypto_generate_random_req;
+
+	/* Prepare request message */
+	req_params->_crypto_generate_random_req_crypto_parameter_size
+		= output_size;
+
+	rpc_call_handle call_handle = 0;
+	struct crypto_proto_resp resp_msg;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_GENERATE_RANDOM, &req_msg, &resp_msg, &call_handle);
+
+	if (psa_status == PSA_SUCCESS) {
+
+		/* Process response message */
+		const struct crypto_generate_random_resp *resp_params =
+			&resp_msg._union__generate_random_resp__crypto_generate_random_resp;
+
+		const struct zcbor_string *bytes_param =
+			&resp_params->_crypto_generate_random_resp_crypto_parameter_random_bytes;
+
+		if (bytes_param->len == output_size) {
+
+			memcpy(output, bytes_param->value, bytes_param->len);
+		}
+		else {
+
+			psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+		}
+	}
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_random.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_random.h
new file mode 100644
index 0000000..df015cf
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_generate_random.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_GENERATE_RANDOM_H
+#define CBOR_CRYPTO_CALLER_GENERATE_RANDOM_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_generate_random(
+	struct service_client *context,
+	uint8_t *output, size_t output_size);
+
+static inline psa_status_t crypto_caller_generate_random(
+	struct service_client *context,
+	uint8_t *output, size_t output_size)
+{
+	return cbor_crypto_caller_generate_random(context, output, output_size);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_GENERATE_RANDOM_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_get_key_attributes.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_get_key_attributes.c
new file mode 100644
index 0000000..645eb48
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_get_key_attributes.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_get_key_attributes.h"
+#include "cbor_crypto_caller_key_attributes.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_get_key_attributes(
+	struct service_client *context,
+	psa_key_id_t id,
+	psa_key_attributes_t *attributes)
+{
+	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+	struct crypto_proto_req req_msg;
+	struct crypto_get_key_attributes_req *req_params =
+		&req_msg._union__get_key_attributes_req__crypto_get_key_attributes_req;
+
+	/* Prepare request message */
+	req_params->_crypto_get_key_attributes_req_crypto_parameter_key_id = id;
+
+	rpc_call_handle call_handle = 0;
+	struct crypto_proto_resp resp_msg;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_GET_KEY_ATTRIBUTES, &req_msg, &resp_msg, &call_handle);
+
+	if (psa_status == PSA_SUCCESS) {
+
+		/* Process response message */
+		const struct crypto_get_key_attributes_resp *resp_params =
+			&resp_msg._union__get_key_attributes_resp__crypto_get_key_attributes_resp;
+
+		const struct crypto_key_attributes *attributes_param =
+			&resp_params->_crypto_get_key_attributes_resp_crypto_parameter_attributes;
+
+		cbor_crypto_caller_translate_key_attributes_from_proto(attributes, attributes_param);
+	}
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_get_key_attributes.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_get_key_attributes.h
new file mode 100644
index 0000000..082e3b5
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_get_key_attributes.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_GET_KEY_ATTRIBUTES_H
+#define CBOR_CRYPTO_CALLER_GET_KEY_ATTRIBUTES_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_get_key_attributes(
+	struct service_client *context,
+	psa_key_id_t id,
+	psa_key_attributes_t *attributes);
+
+static inline psa_status_t crypto_caller_get_key_attributes(
+	struct service_client *context,
+	psa_key_id_t id,
+	psa_key_attributes_t *attributes)
+{
+	return cbor_crypto_caller_get_key_attributes(context, id, attributes);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_GET_KEY_ATTRIBUTES_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_import_key.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_import_key.c
new file mode 100644
index 0000000..0ef651f
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_import_key.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_import_key.h"
+#include "cbor_crypto_caller_key_attributes.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_import_key(
+	struct service_client *context,
+	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 crypto_proto_req req_msg;
+	struct crypto_import_key_req *req_params =
+		&req_msg._union__import_key_req__crypto_import_key_req;
+
+	/* Prepare request message */
+	cbor_crypto_caller_translate_key_attributes_to_proto(
+		&req_params->_crypto_import_key_req_crypto_parameter_attributes,
+		attributes);
+
+	req_params->_crypto_import_key_req_crypto_parameter_data.value = data;
+	req_params->_crypto_import_key_req_crypto_parameter_data.len = data_length;
+
+	rpc_call_handle call_handle = 0;
+	struct crypto_proto_resp resp_msg;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_IMPORT_KEY, &req_msg, &resp_msg, &call_handle);
+
+	if (psa_status == PSA_SUCCESS) {
+
+		/* Process response message */
+		const struct crypto_import_key_resp *resp_params =
+			&resp_msg._union__import_key_resp__crypto_import_key_resp;
+
+		*id = resp_params->_crypto_import_key_resp_crypto_parameter_key_id;
+	}
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_import_key.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_import_key.h
new file mode 100644
index 0000000..f394452
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_import_key.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_IMPORT_KEY_H
+#define CBOR_CRYPTO_CALLER_IMPORT_KEY_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_import_key(
+	struct service_client *context,
+	const psa_key_attributes_t *attributes,
+	const uint8_t *data, size_t data_length,
+	psa_key_id_t *id);
+
+static inline psa_status_t crypto_caller_import_key(
+	struct service_client *context,
+	const psa_key_attributes_t *attributes,
+	const uint8_t *data, size_t data_length,
+	psa_key_id_t *id)
+{
+	return cbor_crypto_caller_import_key(context, attributes, data, data_length, id);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_IMPORT_KEY_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_key_attributes.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_key_attributes.c
new file mode 100644
index 0000000..fc1c978
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_key_attributes.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "cbor_crypto_caller_key_attributes.h"
+
+void cbor_crypto_caller_translate_key_attributes_to_proto(
+	struct crypto_key_attributes *proto_attributes,
+	const psa_key_attributes_t *psa_attributes)
+{
+	proto_attributes->_crypto_key_attributes_type = psa_get_key_type(psa_attributes);
+	proto_attributes->_crypto_key_attributes_key_bits = psa_get_key_bits(psa_attributes);
+	proto_attributes->_crypto_key_attributes_lifetime = psa_get_key_lifetime(psa_attributes);
+	proto_attributes->_crypto_key_attributes_id = psa_get_key_id(psa_attributes);
+
+	proto_attributes->_crypto_key_attributes_policy._crypto_key_policy_usage =
+		psa_get_key_usage_flags(psa_attributes);
+	proto_attributes->_crypto_key_attributes_policy._crypto_key_policy_alg =
+		psa_get_key_algorithm(psa_attributes);
+ }
+
+void cbor_crypto_caller_translate_key_attributes_from_proto(
+	psa_key_attributes_t *psa_attributes,
+	const struct crypto_key_attributes *proto_attributes)
+{
+	psa_set_key_type(psa_attributes, proto_attributes->_crypto_key_attributes_type);
+	psa_set_key_bits(psa_attributes, proto_attributes->_crypto_key_attributes_key_bits);
+	psa_set_key_lifetime(psa_attributes, proto_attributes->_crypto_key_attributes_lifetime);
+
+	if (proto_attributes->_crypto_key_attributes_lifetime == PSA_KEY_LIFETIME_PERSISTENT) {
+
+		psa_set_key_id(psa_attributes, proto_attributes->_crypto_key_attributes_id);
+	}
+
+	psa_set_key_usage_flags(psa_attributes,
+		proto_attributes->_crypto_key_attributes_policy._crypto_key_policy_usage);
+	psa_set_key_algorithm(psa_attributes,
+		proto_attributes->_crypto_key_attributes_policy._crypto_key_policy_alg);
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_key_attributes.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_key_attributes.h
new file mode 100644
index 0000000..863f7b8
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_key_attributes.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_KEY_ATTRIBUTES_H
+#define CBOR_CRYPTO_CALLER_KEY_ATTRIBUTES_H
+
+#include <psa/crypto.h>
+#include "crypto-proto_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cbor_crypto_caller_translate_key_attributes_to_proto(
+	struct crypto_key_attributes *proto_attributes,
+	const psa_key_attributes_t *psa_attributes);
+
+void cbor_crypto_caller_translate_key_attributes_from_proto(
+	psa_key_attributes_t *psa_attributes,
+	const struct crypto_key_attributes *proto_attributes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_KEY_ATTRIBUTES_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_purge_key.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_purge_key.c
new file mode 100644
index 0000000..cfadd07
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_purge_key.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_purge_key.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_purge_key(
+	struct service_client *context,
+	psa_key_id_t id)
+{
+	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+	struct crypto_proto_req req_msg;
+	struct crypto_purge_key_req *req_params =
+		&req_msg._union__purge_key_req__crypto_purge_key_req;
+
+	/* Prepare request message */
+	req_params->_crypto_purge_key_req_crypto_parameter_key_id
+		= id;
+
+	rpc_call_handle call_handle = 0;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_PURGE_KEY, &req_msg, NULL, &call_handle);
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_purge_key.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_purge_key.h
new file mode 100644
index 0000000..872653d
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_purge_key.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_PURGE_KEY_H
+#define CBOR_CRYPTO_CALLER_PURGE_KEY_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_purge_key(
+	struct service_client *context,
+	psa_key_id_t id);
+
+static inline psa_status_t crypto_caller_purge_key(struct service_client *context,
+	psa_key_id_t key)
+{
+	return cbor_crypto_caller_purge_key(context, key);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_PURGE_KEY_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_sign_hash.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_sign_hash.c
new file mode 100644
index 0000000..7895df4
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_sign_hash.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_sign_hash.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_sign_hash(
+	struct service_client *context,
+	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 crypto_proto_req req_msg;
+	struct crypto_sign_hash_req *req_params =
+		&req_msg._union__sign_hash_req__crypto_sign_hash_req;
+
+	/* Prepare request message */
+	req_params->_crypto_sign_hash_req_crypto_parameter_key_id
+		= id;
+	req_params->_crypto_sign_hash_req_crypto_parameter_alg
+		= alg;
+	req_params->_crypto_sign_hash_req_crypto_parameter_hash.value
+		= hash;
+	req_params->_crypto_sign_hash_req_crypto_parameter_hash.len
+		= hash_length;
+
+	rpc_call_handle call_handle = 0;
+	struct crypto_proto_resp resp_msg;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_SIGN_HASH, &req_msg, &resp_msg, &call_handle);
+
+	if (psa_status == PSA_SUCCESS) {
+
+		/* Process response message */
+		const struct crypto_sign_hash_resp *resp_params =
+			&resp_msg._union__sign_hash_resp__crypto_sign_hash_resp;
+
+		const struct zcbor_string *sig_param =
+			&resp_params->_crypto_sign_hash_resp_crypto_parameter_signature;
+
+		if (sig_param->len <= signature_size) {
+
+			memcpy(signature, sig_param->value, sig_param->len);
+			*signature_length = sig_param->len;
+		}
+		else {
+
+			psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
+		}
+	}
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_sign_hash.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_sign_hash.h
new file mode 100644
index 0000000..be0d00b
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_sign_hash.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_SIGN_HASH_H
+#define CBOR_CRYPTO_CALLER_SIGN_HASH_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_sign_hash(
+	struct service_client *context,
+	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);
+
+static inline psa_status_t crypto_caller_sign_hash(struct service_client *context,
+	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 cbor_crypto_caller_sign_hash(
+		context, id, alg,
+		hash, hash_length,
+		signature, signature_size, signature_length);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_SIGN_HASH_H */
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_verify_hash.c b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_verify_hash.c
new file mode 100644
index 0000000..ed238c1
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_verify_hash.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/crypto/packed-c/opcodes.h>
+#include "cbor_crypto_caller.h"
+#include "cbor_crypto_caller_verify_hash.h"
+#include "crypto-proto_types.h"
+
+psa_status_t cbor_crypto_caller_verify_hash(
+	struct service_client *context,
+	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 crypto_proto_req req_msg;
+	struct crypto_verify_hash_req *req_params =
+		&req_msg._union__verify_hash_req__crypto_verify_hash_req;
+
+	/* Prepare request message */
+	req_params->_crypto_verify_hash_req_crypto_parameter_key_id
+		= id;
+	req_params->_crypto_verify_hash_req_crypto_parameter_alg
+		= alg;
+	req_params->_crypto_verify_hash_req_crypto_parameter_hash.value
+		= hash;
+	req_params->_crypto_verify_hash_req_crypto_parameter_hash.len
+		= hash_length;
+	req_params->_crypto_verify_hash_req_crypto_parameter_signature.value
+		= signature;
+	req_params->_crypto_verify_hash_req_crypto_parameter_signature.len
+		= signature_length;
+
+	rpc_call_handle call_handle = 0;
+
+	psa_status = cbor_crypto_caller_invoke(context,
+		TS_CRYPTO_OPCODE_VERIFY_HASH, &req_msg, NULL, &call_handle);
+
+	if (call_handle)
+		rpc_caller_end(context->caller, call_handle);
+
+	return psa_status;
+}
diff --git a/components/service/crypto/client/caller/cbor/cbor_crypto_caller_verify_hash.h b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_verify_hash.h
new file mode 100644
index 0000000..6dc7ea5
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/cbor_crypto_caller_verify_hash.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_CALLER_VERIFY_HASH_H
+#define CBOR_CRYPTO_CALLER_VERIFY_HASH_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+psa_status_t cbor_crypto_caller_verify_hash(
+	struct service_client *context,
+	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);
+
+static inline psa_status_t crypto_caller_verify_hash(
+	struct service_client *context,
+	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 cbor_crypto_caller_verify_hash(
+		context, id, alg,
+		hash, hash_length,
+		signature, signature_length);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_CRYPTO_CALLER_VERIFY_HASH_H */
diff --git a/components/service/crypto/client/caller/cbor/component.cmake b/components/service/crypto/client/caller/cbor/component.cmake
new file mode 100644
index 0000000..ff95a5b
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/component.cmake
@@ -0,0 +1,26 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, 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}/cbor_crypto_caller.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_asymmetric_decrypt.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_asymmetric_encrypt.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_destroy_key.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_purge_key.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_export_key.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_export_public_key.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_generate_random.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_sign_hash.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_verify_hash.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_get_key_attributes.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_key_attributes.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_generate_key.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_crypto_caller_import_key.c"
+	)
diff --git a/components/service/crypto/client/caller/cbor/crypto_caller.h b/components/service/crypto/client/caller/cbor/crypto_caller.h
new file mode 100644
index 0000000..a59a9a0
--- /dev/null
+++ b/components/service/crypto/client/caller/cbor/crypto_caller.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BASE_CBOR_CRYPTO_CALLER_H
+#define BASE_CBOR_CRYPTO_CALLER_H
+
+#include <stdint.h>
+#include <psa/crypto.h>
+#include <service/common/client/service_client.h>
+
+/**
+ * Provides a specialization of the crypto caller interface to
+ * call crypto operations using the cbor serialization of the
+ * crypto access protocol.
+ */
+#include "cbor_crypto_caller_generate_key.h"
+#include "cbor_crypto_caller_asymmetric_decrypt.h"
+#include "cbor_crypto_caller_destroy_key.h"
+#include "cbor_crypto_caller_generate_random.h"
+#include "cbor_crypto_caller_import_key.h"
+#include "cbor_crypto_caller_purge_key.h"
+#include "cbor_crypto_caller_asymmetric_encrypt.h"
+#include "cbor_crypto_caller_export_key.h"
+#include "cbor_crypto_caller_get_key_attributes.h"
+#include "cbor_crypto_caller_sign_hash.h"
+#include "cbor_crypto_caller_export_public_key.h"
+#include "cbor_crypto_caller_verify_hash.h"
+
+#endif /* BASE_CBOR_CRYPTO_CALLER_H */
diff --git a/components/service/crypto/client/cpp/protocol/cbor/cbor_crypto_client.cpp b/components/service/crypto/client/cpp/protocol/cbor/cbor_crypto_client.cpp
new file mode 100644
index 0000000..bb43fb1
--- /dev/null
+++ b/components/service/crypto/client/cpp/protocol/cbor/cbor_crypto_client.cpp
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "cbor_crypto_client.h"
+#include <service/crypto/client/caller/cbor/crypto_caller.h>
+#include <rpc_caller.h>
+
+
+cbor_crypto_client::cbor_crypto_client() :
+	crypto_client()
+{
+
+}
+
+cbor_crypto_client::cbor_crypto_client(struct rpc_caller *caller) :
+	crypto_client(caller)
+{
+
+}
+
+cbor_crypto_client::~cbor_crypto_client()
+{
+
+}
+
+/* Core crypto methods */
+psa_status_t cbor_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 cbor_crypto_client::destroy_key(
+	psa_key_id_t id)
+{
+	return crypto_caller_destroy_key(&m_client, id);
+}
+
+psa_status_t cbor_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 cbor_crypto_client::purge_key(
+	psa_key_id_t id)
+{
+	return crypto_caller_purge_key(&m_client, id);
+}
+
+psa_status_t cbor_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 cbor_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 cbor_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 cbor_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 cbor_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 cbor_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 cbor_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 cbor_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 cbor_crypto_client::generate_random(
+	uint8_t *output, size_t output_size)
+{
+	return crypto_caller_generate_random(&m_client,
+		output, output_size);
+}
+
+/* Hash methods */
+size_t cbor_crypto_client::hash_max_update_size() const
+{
+	return 0;
+}
+
+psa_status_t cbor_crypto_client::hash_setup(
+	uint32_t *op_handle,
+	psa_algorithm_t alg)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::hash_update(
+	uint32_t op_handle,
+	const uint8_t *input, size_t input_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::hash_finish(
+	uint32_t op_handle,
+	uint8_t *hash, size_t hash_size, size_t *hash_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::hash_abort(
+	uint32_t op_handle)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::hash_verify(
+	uint32_t op_handle,
+	const uint8_t *hash, size_t hash_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::hash_clone(
+	uint32_t source_op_handle,
+	uint32_t *target_op_handle)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+/* Cipher methods */
+size_t cbor_crypto_client::cipher_max_update_size() const
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::cipher_encrypt_setup(
+	uint32_t *op_handle,
+	psa_key_id_t key,
+	psa_algorithm_t alg)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::cipher_decrypt_setup(
+	uint32_t *op_handle,
+	psa_key_id_t key,
+	psa_algorithm_t alg)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::cipher_generate_iv(
+	uint32_t op_handle,
+	uint8_t *iv, size_t iv_size, size_t *iv_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::cipher_set_iv(
+	uint32_t op_handle,
+	const uint8_t *iv, size_t iv_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::cipher_update(
+	uint32_t op_handle,
+	const uint8_t *input, size_t input_length,
+	uint8_t *output, size_t output_size, size_t *output_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::cipher_finish(
+	uint32_t op_handle,
+	uint8_t *output, size_t output_size, size_t *output_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::cipher_abort(
+	uint32_t op_handle)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+/* MAC methods */
+size_t cbor_crypto_client::mac_max_update_size() const
+{
+	return 0;
+}
+
+psa_status_t cbor_crypto_client::mac_sign_setup(
+	uint32_t *op_handle,
+	psa_key_id_t key,
+	psa_algorithm_t alg)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::mac_verify_setup(
+	uint32_t *op_handle,
+	psa_key_id_t key,
+	psa_algorithm_t alg)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::mac_update(
+	uint32_t op_handle,
+	const uint8_t *input, size_t input_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::mac_sign_finish(
+	uint32_t op_handle,
+	uint8_t *mac, size_t mac_size, size_t *mac_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::mac_verify_finish(
+	uint32_t op_handle,
+	const uint8_t *mac, size_t mac_length)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::mac_abort(
+	uint32_t op_handle)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+/* Key derivation methods */
+psa_status_t cbor_crypto_client::key_derivation_setup(
+	uint32_t *op_handle,
+	psa_algorithm_t alg)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::key_derivation_get_capacity(
+	const uint32_t op_handle,
+	size_t *capacity)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_crypto_client::key_derivation_set_capacity(
+	uint32_t op_handle,
+	size_t capacity)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_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 cbor_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 cbor_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 cbor_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 cbor_crypto_client::key_derivation_abort(
+	uint32_t op_handle)
+{
+	return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t cbor_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 cbor_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/cbor/cbor_crypto_client.h b/components/service/crypto/client/cpp/protocol/cbor/cbor_crypto_client.h
new file mode 100644
index 0000000..2f2c3c8
--- /dev/null
+++ b/components/service/crypto/client/cpp/protocol/cbor/cbor_crypto_client.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CPP_CBOR_CRYPTO_CLIENT_H
+#define CPP_CBOR_CRYPTO_CLIENT_H
+
+#include <service/crypto/client/cpp/crypto_client.h>
+
+/*
+ * A concrete crypto_client that uses the cbor based crypto access protocol
+ */
+class cbor_crypto_client : public crypto_client
+{
+public:
+	cbor_crypto_client();
+	cbor_crypto_client(struct rpc_caller *caller);
+	virtual ~cbor_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 */
+	size_t hash_max_update_size() const;
+
+	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);
+
+	psa_status_t hash_abort(
+		uint32_t op_handle);
+
+	psa_status_t hash_verify(
+		uint32_t op_handle,
+		const uint8_t *hash, size_t hash_length);
+
+	psa_status_t hash_clone(
+		uint32_t source_op_handle,
+		uint32_t *target_op_handle);
+
+	/* Cipher methods */
+	size_t cipher_max_update_size() const;
+
+	psa_status_t cipher_encrypt_setup(
+		uint32_t *op_handle,
+		psa_key_id_t key,
+		psa_algorithm_t alg);
+
+	psa_status_t cipher_decrypt_setup(
+		uint32_t *op_handle,
+		psa_key_id_t key,
+		psa_algorithm_t alg);
+
+	psa_status_t cipher_generate_iv(
+		uint32_t op_handle,
+		uint8_t *iv, size_t iv_size, size_t *iv_length);
+
+	psa_status_t cipher_set_iv(
+		uint32_t op_handle,
+		const uint8_t *iv, size_t iv_length);
+
+	psa_status_t cipher_update(
+		uint32_t op_handle,
+		const uint8_t *input, size_t input_length,
+		uint8_t *output, size_t output_size, size_t *output_length);
+
+	psa_status_t cipher_finish(
+		uint32_t op_handle,
+		uint8_t *output, size_t output_size, size_t *output_length);
+
+	psa_status_t cipher_abort(
+		uint32_t op_handle);
+
+	/* MAC methods */
+	size_t mac_max_update_size() const;
+
+	psa_status_t mac_sign_setup(
+		uint32_t *op_handle,
+		psa_key_id_t key,
+		psa_algorithm_t alg);
+
+	psa_status_t mac_verify_setup(
+		uint32_t *op_handle,
+		psa_key_id_t key,
+		psa_algorithm_t alg);
+
+	psa_status_t mac_update(
+		uint32_t op_handle,
+		const uint8_t *input, size_t input_length);
+
+	psa_status_t mac_sign_finish(
+		uint32_t op_handle,
+		uint8_t *mac, size_t mac_size, size_t *mac_length);
+
+	psa_status_t mac_verify_finish(
+		uint32_t op_handle,
+		const uint8_t *mac, size_t mac_length);
+
+	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 /* CPP_CBOR_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/cpp/protocol/cbor/component.cmake b/components/service/crypto/client/cpp/protocol/cbor/component.cmake
new file mode 100644
index 0000000..fe95f56
--- /dev/null
+++ b/components/service/crypto/client/cpp/protocol/cbor/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, 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}/cbor_crypto_client.cpp"
+	)
diff --git a/components/service/crypto/provider/serializer/cbor/cbor_crypto_provider_serializer.c b/components/service/crypto/provider/serializer/cbor/cbor_crypto_provider_serializer.c
new file mode 100644
index 0000000..db2439b
--- /dev/null
+++ b/components/service/crypto/provider/serializer/cbor/cbor_crypto_provider_serializer.c
@@ -0,0 +1,727 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <psa/crypto.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include "crypto-proto_encode.h"
+#include "crypto-proto_decode.h"
+#include "cbor_key_attributes_translator.h"
+#include "cbor_crypto_provider_serializer.h"
+
+/* Returns the maximum possible deserialized parameter size for a cbor encoded message. */
+static size_t max_deserialised_parameter_size(const struct call_param_buf *req_buf)
+{
+	/*
+	 * Assume that a deserialized parameter must be the same size or smaller than the
+	 * entire serialized message.
+	 */
+	return req_buf->data_len;
+}
+
+/* Operation: generate_key */
+static rpc_status_t deserialize_generate_key_req(
+	const struct call_param_buf *req_buf,
+	psa_key_attributes_t *attributes)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_generate_key_req *req_params =
+			&req_msg._union__generate_key_req__crypto_generate_key_req;
+
+		cbor_crypto_provider_translate_key_attributes_from_proto(
+			attributes,
+			&req_params->_crypto_generate_key_req_crypto_parameter_attributes);
+
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t serialize_generate_key_resp(
+	struct call_param_buf *resp_buf,
+	psa_key_id_t id)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+	struct crypto_proto_resp resp_msg;
+
+	resp_msg._crypto_proto_resp_union_choice =
+		_union__generate_key_resp;
+
+	struct crypto_generate_key_resp *resp_params =
+		&resp_msg._union__generate_key_resp__crypto_generate_key_resp;
+
+	resp_params->_crypto_generate_key_resp_crypto_parameter_key_id = id;
+
+	size_t encode_len = 0;
+	uint_fast8_t encode_status = cbor_encode_crypto_proto_resp(
+		resp_buf->data, resp_buf->size,
+		&resp_msg, &encode_len);
+
+	if (encode_status == ZCBOR_SUCCESS) {
+
+		resp_buf->data_len = encode_len;
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Operation: destroy_key */
+static rpc_status_t deserialize_destroy_key_req(
+	const struct call_param_buf *req_buf,
+	psa_key_id_t *id)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_destroy_key_req *req_params =
+			&req_msg._union__destroy_key_req__crypto_destroy_key_req;
+
+		*id = req_params->_crypto_destroy_key_req_crypto_parameter_key_id;
+
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Operation: export_key */
+static rpc_status_t deserialize_export_key_req(
+	const struct call_param_buf *req_buf,
+	psa_key_id_t *id)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_export_key_req *req_params =
+			&req_msg._union__export_key_req__crypto_export_key_req;
+
+		*id = req_params->_crypto_export_key_req_crypto_parameter_key_id;
+
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t serialize_export_key_resp(
+	struct call_param_buf *resp_buf,
+	const uint8_t *data, size_t data_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+	struct crypto_proto_resp resp_msg;
+
+	resp_msg._crypto_proto_resp_union_choice =
+		_union__export_key_resp;
+
+	struct crypto_export_key_resp *resp_params =
+		&resp_msg._union__export_key_resp__crypto_export_key_resp;
+
+	resp_params->_crypto_export_key_resp_crypto_parameter_data.value = data;
+	resp_params->_crypto_export_key_resp_crypto_parameter_data.len = data_len;
+
+	size_t encode_len = 0;
+	uint_fast8_t encode_status = cbor_encode_crypto_proto_resp(
+		resp_buf->data, resp_buf->size,
+		&resp_msg, &encode_len);
+
+	if (encode_status == ZCBOR_SUCCESS) {
+
+		resp_buf->data_len = encode_len;
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Operation: import_key */
+static rpc_status_t deserialize_import_key_req(
+	const struct call_param_buf *req_buf,
+	psa_key_attributes_t *attributes,
+	uint8_t *data, size_t *data_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_import_key_req *req_params =
+			&req_msg._union__import_key_req__crypto_import_key_req;
+
+		cbor_crypto_provider_translate_key_attributes_from_proto(
+			attributes,
+			&req_params->_crypto_import_key_req_crypto_parameter_attributes);
+
+		size_t key_data_len =
+			req_params->_crypto_import_key_req_crypto_parameter_data.len;
+
+		if (key_data_len <= *data_len) {
+
+			memcpy(data,
+				req_params->_crypto_import_key_req_crypto_parameter_data.value,
+				key_data_len);
+
+			*data_len = key_data_len;
+
+			rpc_status = TS_RPC_CALL_ACCEPTED;
+		}
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t serialize_import_key_resp(
+	struct call_param_buf *resp_buf,
+	psa_key_id_t id)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+	struct crypto_proto_resp resp_msg;
+
+	resp_msg._crypto_proto_resp_union_choice =
+		_union__import_key_resp;
+
+	struct crypto_import_key_resp *resp_params =
+		&resp_msg._union__import_key_resp__crypto_import_key_resp;
+
+	resp_params->_crypto_import_key_resp_crypto_parameter_key_id = id;
+
+	size_t encode_len = 0;
+	uint_fast8_t encode_status = cbor_encode_crypto_proto_resp(
+		resp_buf->data, resp_buf->size,
+		&resp_msg, &encode_len);
+
+	if (encode_status == ZCBOR_SUCCESS) {
+
+		resp_buf->data_len = encode_len;
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Operation: copy_key */
+static rpc_status_t deserialize_copy_key_req(
+	const struct call_param_buf *req_buf,
+	psa_key_attributes_t *attributes,
+	psa_key_id_t *source_id)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+
+	return rpc_status;
+}
+
+static rpc_status_t serialize_copy_key_resp(
+	struct call_param_buf *resp_buf,
+	psa_key_id_t target_id)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+
+	return rpc_status;
+}
+
+/* Operation: purge_key */
+static rpc_status_t deserialize_purge_key_req(
+	const struct call_param_buf *req_buf,
+	psa_key_id_t *id)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_purge_key_req *req_params =
+			&req_msg._union__purge_key_req__crypto_purge_key_req;
+
+		*id = req_params->_crypto_purge_key_req_crypto_parameter_key_id;
+
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Operation: get_key_attributes */
+static rpc_status_t deserialize_get_key_attributes_req(
+	const struct call_param_buf *req_buf,
+	psa_key_id_t *id)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_get_key_attributes_req *req_params =
+			&req_msg._union__get_key_attributes_req__crypto_get_key_attributes_req;
+
+		*id = req_params->_crypto_get_key_attributes_req_crypto_parameter_key_id;
+
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t serialize_get_key_attributes_resp(
+	struct call_param_buf *resp_buf,
+	const psa_key_attributes_t *attributes)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+	struct crypto_proto_resp resp_msg;
+
+	resp_msg._crypto_proto_resp_union_choice =
+		_union__get_key_attributes_resp;
+
+	struct crypto_get_key_attributes_resp *resp_params =
+		&resp_msg._union__get_key_attributes_resp__crypto_get_key_attributes_resp;
+
+	cbor_crypto_provider_translate_key_attributes_to_proto(
+		&resp_params->_crypto_get_key_attributes_resp_crypto_parameter_attributes,
+		attributes);
+
+	size_t encode_len = 0;
+	uint_fast8_t encode_status = cbor_encode_crypto_proto_resp(
+		resp_buf->data, resp_buf->size,
+		&resp_msg, &encode_len);
+
+	if (encode_status == ZCBOR_SUCCESS) {
+
+		resp_buf->data_len = encode_len;
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Operation: sign_hash */
+static rpc_status_t deserialize_sign_hash_req(
+	const struct call_param_buf *req_buf,
+	psa_key_id_t *id, psa_algorithm_t *alg,
+	uint8_t *hash, size_t *hash_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_sign_hash_req *req_params =
+			&req_msg._union__sign_hash_req__crypto_sign_hash_req;
+
+		*id = req_params->_crypto_sign_hash_req_crypto_parameter_key_id;
+		*alg = req_params->_crypto_sign_hash_req_crypto_parameter_alg;
+
+		size_t req_hash_len =
+			req_params->_crypto_sign_hash_req_crypto_parameter_hash.len;
+
+		if (req_hash_len <= *hash_len) {
+
+			memcpy(hash,
+				req_params->_crypto_sign_hash_req_crypto_parameter_hash.value,
+				req_hash_len);
+
+			*hash_len = req_hash_len;
+
+			rpc_status = TS_RPC_CALL_ACCEPTED;
+		}
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t serialize_sign_hash_resp(
+	struct call_param_buf *resp_buf,
+	const uint8_t *sig, size_t sig_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+	struct crypto_proto_resp resp_msg;
+
+	resp_msg._crypto_proto_resp_union_choice =
+		_union__sign_hash_resp;
+
+	struct crypto_sign_hash_resp *resp_params =
+		&resp_msg._union__sign_hash_resp__crypto_sign_hash_resp;
+
+	resp_params->_crypto_sign_hash_resp_crypto_parameter_signature.value = sig;
+	resp_params->_crypto_sign_hash_resp_crypto_parameter_signature.len = sig_len;
+
+	size_t encode_len = 0;
+	uint_fast8_t encode_status = cbor_encode_crypto_proto_resp(
+		resp_buf->data, resp_buf->size,
+		&resp_msg, &encode_len);
+
+	if (encode_status == ZCBOR_SUCCESS) {
+
+		resp_buf->data_len = encode_len;
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Operation: verify_hash */
+static rpc_status_t deserialize_verify_hash_req(
+	const struct call_param_buf *req_buf,
+	psa_key_id_t *id, psa_algorithm_t *alg,
+	uint8_t *hash, size_t *hash_len,
+	uint8_t *sig, size_t *sig_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_verify_hash_req *req_params =
+			&req_msg._union__verify_hash_req__crypto_verify_hash_req;
+
+		*id = req_params->_crypto_verify_hash_req_crypto_parameter_key_id;
+		*alg = req_params->_crypto_verify_hash_req_crypto_parameter_alg;
+
+		size_t req_hash_len =
+			req_params->_crypto_verify_hash_req_crypto_parameter_hash.len;
+		size_t req_sig_len =
+			req_params->_crypto_verify_hash_req_crypto_parameter_signature.len;
+
+		if ((req_hash_len <= *hash_len) && (req_sig_len <= *sig_len)) {
+
+			memcpy(hash,
+				req_params->_crypto_verify_hash_req_crypto_parameter_hash.value,
+				req_hash_len);
+
+			*hash_len = req_hash_len;
+
+			memcpy(sig,
+				req_params->_crypto_verify_hash_req_crypto_parameter_signature.value,
+				req_sig_len);
+
+			*sig_len = req_sig_len;
+
+			rpc_status = TS_RPC_CALL_ACCEPTED;
+		}
+	}
+
+	return rpc_status;
+}
+
+/* Operation: asymmetric_decrypt */
+static rpc_status_t deserialize_asymmetric_decrypt_req(
+	const struct call_param_buf *req_buf,
+	psa_key_id_t *id, psa_algorithm_t *alg,
+	uint8_t *ciphertext, size_t *ciphertext_len,
+	uint8_t *salt, size_t *salt_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_asymmetric_decryption_req *req_params =
+			&req_msg._union__asymmetric_decrypt_req__crypto_asymmetric_decryption_req;
+
+		*id = req_params->_crypto_asymmetric_decryption_req_crypto_parameter_key_id;
+		*alg = req_params->_crypto_asymmetric_decryption_req_crypto_parameter_alg;
+
+		size_t req_ciphertext_len =
+			req_params->_crypto_asymmetric_decryption_req_crypto_parameter_ciphertext.len;
+		size_t req_salt_len =
+			req_params->_crypto_asymmetric_decryption_req_crypto_parameter_salt.len;
+
+		if ((req_ciphertext_len <= *ciphertext_len) && (req_salt_len <= *salt_len)) {
+
+			memcpy(ciphertext,
+				req_params->_crypto_asymmetric_decryption_req_crypto_parameter_ciphertext.value,
+				req_ciphertext_len);
+
+			*ciphertext_len = req_ciphertext_len;
+
+			memcpy(salt,
+				req_params->_crypto_asymmetric_decryption_req_crypto_parameter_salt.value,
+				req_salt_len);
+
+			*salt_len = req_salt_len;
+
+			rpc_status = TS_RPC_CALL_ACCEPTED;
+		}
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t serialize_asymmetric_decrypt_resp(
+	struct call_param_buf *resp_buf,
+	const uint8_t *plaintext, size_t plaintext_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+	struct crypto_proto_resp resp_msg;
+
+	resp_msg._crypto_proto_resp_union_choice =
+		_union__asymmetric_decrypt_resp;
+
+	struct crypto_asymmetric_decryption_resp *resp_params =
+		&resp_msg._union__asymmetric_decrypt_resp__crypto_asymmetric_decryption_resp;
+
+	resp_params->_crypto_asymmetric_decryption_resp_crypto_parameter_plaintext.value = plaintext;
+	resp_params->_crypto_asymmetric_decryption_resp_crypto_parameter_plaintext.len = plaintext_len;
+
+	size_t encode_len = 0;
+	uint_fast8_t encode_status = cbor_encode_crypto_proto_resp(
+		resp_buf->data, resp_buf->size,
+		&resp_msg, &encode_len);
+
+	if (encode_status == ZCBOR_SUCCESS) {
+
+		resp_buf->data_len = encode_len;
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Operation: asymmetric_encrypt */
+static rpc_status_t deserialize_asymmetric_encrypt_req(
+	const struct call_param_buf *req_buf,
+	psa_key_id_t *id, psa_algorithm_t *alg,
+	uint8_t *plaintext, size_t *plaintext_len,
+	uint8_t *salt, size_t *salt_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_asymmetric_encryption_req *req_params =
+			&req_msg._union__asymmetric_encrypt_req__crypto_asymmetric_encryption_req;
+
+		*id = req_params->_crypto_asymmetric_encryption_req_crypto_parameter_key_id;
+		*alg = req_params->_crypto_asymmetric_encryption_req_crypto_parameter_alg;
+
+		size_t req_plaintext_len =
+			req_params->_crypto_asymmetric_encryption_req_crypto_parameter_plaintext.len;
+		size_t req_salt_len =
+			req_params->_crypto_asymmetric_encryption_req_crypto_parameter_salt.len;
+
+		if ((req_plaintext_len <= *plaintext_len) && (req_salt_len <= *salt_len)) {
+
+			memcpy(plaintext,
+				req_params->_crypto_asymmetric_encryption_req_crypto_parameter_plaintext.value,
+				req_plaintext_len);
+
+			*plaintext_len = req_plaintext_len;
+
+			memcpy(salt,
+				req_params->_crypto_asymmetric_encryption_req_crypto_parameter_salt.value,
+				req_salt_len);
+
+			*salt_len = req_salt_len;
+
+			rpc_status = TS_RPC_CALL_ACCEPTED;
+		}
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t serialize_asymmetric_encrypt_resp(
+	struct call_param_buf *resp_buf,
+	const uint8_t *ciphertext, size_t ciphertext_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+	struct crypto_proto_resp resp_msg;
+
+	resp_msg._crypto_proto_resp_union_choice =
+		_union__asymmetric_encrypt_resp;
+
+	struct crypto_asymmetric_encryption_resp *resp_params =
+		&resp_msg._union__asymmetric_encrypt_resp__crypto_asymmetric_encryption_resp;
+
+	resp_params->_crypto_asymmetric_encryption_resp_crypto_parameter_ciphertext.value = ciphertext;
+	resp_params->_crypto_asymmetric_encryption_resp_crypto_parameter_ciphertext.len = ciphertext_len;
+
+	size_t encode_len = 0;
+	uint_fast8_t encode_status = cbor_encode_crypto_proto_resp(
+		resp_buf->data, resp_buf->size,
+		&resp_msg, &encode_len);
+
+	if (encode_status == ZCBOR_SUCCESS) {
+
+		resp_buf->data_len = encode_len;
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Operation: generate_random */
+static rpc_status_t deserialize_generate_random_req(
+	const struct call_param_buf *req_buf,
+	size_t *size)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+	struct crypto_proto_req req_msg;
+	size_t decode_len = 0;
+
+	uint_fast8_t decode_status = cbor_decode_crypto_proto_req(
+		req_buf->data, req_buf->data_len,
+		&req_msg, &decode_len);
+
+	if (decode_status == ZCBOR_SUCCESS) {
+
+		struct crypto_generate_random_req *req_params =
+			&req_msg._union__generate_random_req__crypto_generate_random_req;
+
+		*size = req_params->_crypto_generate_random_req_crypto_parameter_size;
+
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t serialize_generate_random_resp(
+	struct call_param_buf *resp_buf,
+	const uint8_t *output, size_t output_len)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+	struct crypto_proto_resp resp_msg;
+
+	resp_msg._crypto_proto_resp_union_choice =
+		_union__generate_random_resp;
+
+	struct crypto_generate_random_resp *resp_params =
+		&resp_msg._union__generate_random_resp__crypto_generate_random_resp;
+
+	resp_params->_crypto_generate_random_resp_crypto_parameter_random_bytes.value = output;
+	resp_params->_crypto_generate_random_resp_crypto_parameter_random_bytes.len = output_len;
+
+	size_t encode_len = 0;
+	uint_fast8_t encode_status = cbor_encode_crypto_proto_resp(
+		resp_buf->data, resp_buf->size,
+		&resp_msg, &encode_len);
+
+	if (encode_status == ZCBOR_SUCCESS) {
+
+		resp_buf->data_len = encode_len;
+		rpc_status = TS_RPC_CALL_ACCEPTED;
+	}
+
+	return rpc_status;
+}
+
+/* Singleton method to provide access to the serializer instance */
+const struct crypto_provider_serializer *cbor_crypto_provider_serializer_instance(void)
+{
+	static const struct crypto_provider_serializer instance = {
+		max_deserialised_parameter_size,
+
+		/* generate_key */
+		deserialize_generate_key_req,
+		serialize_generate_key_resp,
+
+		/* destroy key */
+		deserialize_destroy_key_req,
+
+		/* export key */
+		deserialize_export_key_req,
+		serialize_export_key_resp,
+
+		/* export public key */
+		deserialize_export_key_req,
+		serialize_export_key_resp,
+
+		/* import key */
+		deserialize_import_key_req,
+		serialize_import_key_resp,
+
+		/* copy key */
+		deserialize_copy_key_req,
+		serialize_copy_key_resp,
+
+		/* purge key */
+		deserialize_purge_key_req,
+
+		/* get key attributes */
+		deserialize_get_key_attributes_req,
+		serialize_get_key_attributes_resp,
+
+		/* sign hash */
+		deserialize_sign_hash_req,
+		serialize_sign_hash_resp,
+
+		/* verify hash */
+		deserialize_verify_hash_req,
+
+		/* asymmetric decrypt */
+		deserialize_asymmetric_decrypt_req,
+		serialize_asymmetric_decrypt_resp,
+
+		/* asymmetric encrypt */
+		deserialize_asymmetric_encrypt_req,
+		serialize_asymmetric_encrypt_resp,
+
+		/* generate random */
+		deserialize_generate_random_req,
+		serialize_generate_random_resp
+	};
+
+	return &instance;
+}
diff --git a/components/service/crypto/provider/serializer/cbor/cbor_crypto_provider_serializer.h b/components/service/crypto/provider/serializer/cbor/cbor_crypto_provider_serializer.h
new file mode 100644
index 0000000..aae4a1a
--- /dev/null
+++ b/components/service/crypto/provider/serializer/cbor/cbor_crypto_provider_serializer.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_PROVIDER_SERIALIZER_H
+#define CBOR_CRYPTO_PROVIDER_SERIALIZER_H
+
+#include <service/crypto/provider/serializer/crypto_provider_serializer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Singleton method to provide access to the cbor serializer
+ * for the crypto service provider.
+ */
+const struct crypto_provider_serializer *cbor_crypto_provider_serializer_instance(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* CBOR_CRYPTO_PROVIDER_SERIALIZER_H */
diff --git a/components/service/crypto/provider/serializer/cbor/cbor_key_attributes_translator.c b/components/service/crypto/provider/serializer/cbor/cbor_key_attributes_translator.c
new file mode 100644
index 0000000..94a47fd
--- /dev/null
+++ b/components/service/crypto/provider/serializer/cbor/cbor_key_attributes_translator.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "cbor_key_attributes_translator.h"
+
+void cbor_crypto_provider_translate_key_attributes_from_proto(
+	psa_key_attributes_t *psa_attributes,
+	const struct crypto_key_attributes *proto_attributes)
+{
+	psa_set_key_type(psa_attributes, proto_attributes->_crypto_key_attributes_type);
+	psa_set_key_bits(psa_attributes, proto_attributes->_crypto_key_attributes_key_bits);
+	psa_set_key_lifetime(psa_attributes, proto_attributes->_crypto_key_attributes_lifetime);
+
+	if (proto_attributes->_crypto_key_attributes_lifetime == PSA_KEY_LIFETIME_PERSISTENT) {
+
+		psa_set_key_id(psa_attributes, proto_attributes->_crypto_key_attributes_id);
+	}
+
+	psa_set_key_usage_flags(psa_attributes,
+		proto_attributes->_crypto_key_attributes_policy._crypto_key_policy_usage);
+	psa_set_key_algorithm(psa_attributes,
+		proto_attributes->_crypto_key_attributes_policy._crypto_key_policy_alg);
+}
+
+void cbor_crypto_provider_translate_key_attributes_to_proto(
+	struct crypto_key_attributes *proto_attributes,
+	const psa_key_attributes_t *psa_attributes)
+{
+	proto_attributes->_crypto_key_attributes_type = psa_get_key_type(psa_attributes);
+	proto_attributes->_crypto_key_attributes_key_bits = psa_get_key_bits(psa_attributes);
+	proto_attributes->_crypto_key_attributes_lifetime = psa_get_key_lifetime(psa_attributes);
+	proto_attributes->_crypto_key_attributes_id = psa_get_key_id(psa_attributes);
+
+	proto_attributes->_crypto_key_attributes_policy._crypto_key_policy_usage =
+		psa_get_key_usage_flags(psa_attributes);
+	proto_attributes->_crypto_key_attributes_policy._crypto_key_policy_alg =
+		psa_get_key_algorithm(psa_attributes);
+}
diff --git a/components/service/crypto/provider/serializer/cbor/cbor_key_attributes_translator.h b/components/service/crypto/provider/serializer/cbor/cbor_key_attributes_translator.h
new file mode 100644
index 0000000..2e64eb2
--- /dev/null
+++ b/components/service/crypto/provider/serializer/cbor/cbor_key_attributes_translator.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CBOR_CRYPTO_PROVIDER_KEY_ATTRIBUTES_TRANSLATOR_H
+#define CBOR_CRYPTO_PROVIDER_KEY_ATTRIBUTES_TRANSLATOR_H
+
+#include <psa/crypto.h>
+#include "crypto-proto_types.h"
+
+void cbor_crypto_provider_translate_key_attributes_from_proto(
+	psa_key_attributes_t *psa_attributes,
+	const struct crypto_key_attributes *proto_attributes);
+
+void cbor_crypto_provider_translate_key_attributes_to_proto(
+	struct crypto_key_attributes *proto_attributes,
+	const psa_key_attributes_t *psa_attributes);
+
+#endif /* CBOR_CRYPTO_PROVIDER_KEY_ATTRIBUTES_TRANSLATOR_H */
diff --git a/components/service/crypto/provider/serializer/cbor/component.cmake b/components/service/crypto/provider/serializer/cbor/component.cmake
new file mode 100644
index 0000000..51bcc06
--- /dev/null
+++ b/components/service/crypto/provider/serializer/cbor/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, 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}/cbor_crypto_provider_serializer.c"
+	"${CMAKE_CURRENT_LIST_DIR}/cbor_key_attributes_translator.c"
+	)
diff --git a/components/service/crypto/test/service/cbor/component.cmake b/components/service/crypto/test/service/cbor/component.cmake
new file mode 100644
index 0000000..436b913
--- /dev/null
+++ b/components/service/crypto/test/service/cbor/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, 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}/crypto_service_cbor_tests.cpp"
+	)
diff --git a/components/service/crypto/test/service/cbor/crypto_service_cbor_tests.cpp b/components/service/crypto/test/service/cbor/crypto_service_cbor_tests.cpp
new file mode 100644
index 0000000..fe7bf87
--- /dev/null
+++ b/components/service/crypto/test/service/cbor/crypto_service_cbor_tests.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <service/crypto/client/cpp/protocol/cbor/cbor_crypto_client.h>
+#include <service/crypto/test/service/crypto_service_scenarios.h>
+#include <protocols/rpc/common/packed-c/encoding.h>
+#include <service_locator.h>
+#include <CppUTest/TestHarness.h>
+
+/*
+ * Service-level tests that use the CBOR access protocol serialization
+ */
+TEST_GROUP(CryptoServiceCborTests)
+{
+    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_CBOR, &caller);
+        CHECK_TRUE(m_rpc_session_handle);
+
+        m_scenarios = new crypto_service_scenarios(new cbor_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;
+    crypto_service_scenarios *m_scenarios;
+};
+
+TEST(CryptoServiceCborTests, generateVolatileKeys)
+{
+    m_scenarios->generateVolatileKeys();
+}
+
+TEST(CryptoServiceCborTests, generatePersistentKeys)
+{
+    m_scenarios->generatePersistentKeys();
+}
+
+TEST(CryptoServiceCborTests, exportPublicKey)
+{
+    m_scenarios->exportPublicKey();
+}
+
+TEST(CryptoServiceCborTests, exportAndImportKeyPair)
+{
+    m_scenarios->exportAndImportKeyPair();
+}
+
+TEST(CryptoServiceCborTests, signAndVerifyHash)
+{
+    m_scenarios->signAndVerifyHash();
+}
+
+TEST(CryptoServiceCborTests, asymEncryptDecrypt)
+{
+    m_scenarios->asymEncryptDecrypt();
+}
+
+TEST(CryptoServiceCborTests, asymEncryptDecryptWithSalt)
+{
+    m_scenarios->asymEncryptDecryptWithSalt();
+}
+
+TEST(CryptoServiceCborTests, generateRandomNumbers)
+{
+    m_scenarios->generateRandomNumbers();
+}
diff --git a/protocols/rpc/common/packed-c/encoding.h b/protocols/rpc/common/packed-c/encoding.h
index cd7093c..7ae3e1a 100644
--- a/protocols/rpc/common/packed-c/encoding.h
+++ b/protocols/rpc/common/packed-c/encoding.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,26 +12,32 @@
  */
 enum
 {
-    /*
-     * Packed-c encoding.  A lightweight serialization scheme with
-     * C language definition files.
-     */
-    TS_RPC_ENCODING_PACKED_C        =  0,
+	/*
+	 * Packed-c encoding.  A lightweight serialization scheme with
+	 * C language definition files.
+	 */
+	TS_RPC_ENCODING_PACKED_C        =  0,
 
-    /*
-     * Protocol Buffers serialization scheme with language independent
-     * definition files.  Supports client code generation using definition
-     * files.
-     */
-    TS_RPC_ENCODING_PROTOBUF        =  1,
+	/*
+	 * Protocol Buffers serialization scheme with language independent
+	 * definition files.  Supports client code generation using definition
+	 * files.
+	 */
+	TS_RPC_ENCODING_PROTOBUF        =  1,
 
-    /*
-     * The limit of known encodings.  As new encodings are added,
-     * the limit value should be allowed to increase.  An RPC interface
-     * that was built before a new encoding was added should safely
-     * reject an unsupported encoding.
-     */
-    TS_RPC_ENCODING_LIMIT
+	/*
+	 * CBOR serialization scheme.  Protocol messages defined in CDDL
+	 * documents.
+	 */
+	TS_RPC_ENCODING_CBOR            =  2,
+
+	/*
+	 * The limit of known encodings.  As new encodings are added,
+	 * the limit value should be allowed to increase.  An RPC interface
+	 * that was built before a new encoding was added should safely
+	 * reject an unsupported encoding.
+	 */
+	TS_RPC_ENCODING_LIMIT
 };
 
 #endif /* PROTOCOLS_RPC_COMMON_ENCODING_H */