Add hash operation support to Crypto service provider

Adds support for multi-step hash operations.  Only includes
protocol support for packed-c serialization at the moment.
Protobuf serialization still needs to be added.  Includes
crypto context management that can be used for any multi-
step operations such as MAC and symmetric encrypt/decrypt.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: Ib51a9737f1987e1e7531da7edb38d9dc4095cc7e
diff --git a/components/service/crypto/provider/mbedcrypto/crypto_provider.c b/components/service/crypto/provider/mbedcrypto/crypto_provider.c
index 1b2fffd..292c180 100644
--- a/components/service/crypto/provider/mbedcrypto/crypto_provider.c
+++ b/components/service/crypto/provider/mbedcrypto/crypto_provider.c
@@ -24,559 +24,697 @@
 static rpc_status_t asymmetric_decrypt_handler(void *context, struct call_req* req);
 static rpc_status_t asymmetric_encrypt_handler(void *context, struct call_req* req);
 static rpc_status_t generate_random_handler(void *context, struct call_req* req);
+static rpc_status_t hash_setup_handler(void *context, struct call_req* req);
+static rpc_status_t hash_update_handler(void *context, struct call_req* req);
+static rpc_status_t hash_finish_handler(void *context, struct call_req* req);
 
 /* Handler mapping table for service */
 static const struct service_handler handler_table[] = {
-    {TS_CRYPTO_OPCODE_NOP,                  nop_handler},
-    {TS_CRYPTO_OPCODE_GENERATE_KEY,         generate_key_handler},
-    {TS_CRYPTO_OPCODE_DESTROY_KEY,          destroy_key_handler},
-    {TS_CRYPTO_OPCODE_EXPORT_KEY,           export_key_handler},
-    {TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY,    export_public_key_handler},
-    {TS_CRYPTO_OPCODE_IMPORT_KEY,           import_key_handler},
-    {TS_CRYPTO_OPCODE_SIGN_HASH,            sign_hash_handler},
-    {TS_CRYPTO_OPCODE_VERIFY_HASH,          verify_hash_handler},
-    {TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT,   asymmetric_decrypt_handler},
-    {TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT,   asymmetric_encrypt_handler},
-    {TS_CRYPTO_OPCODE_GENERATE_RANDOM,      generate_random_handler}
+	{TS_CRYPTO_OPCODE_NOP,                  nop_handler},
+	{TS_CRYPTO_OPCODE_GENERATE_KEY,         generate_key_handler},
+	{TS_CRYPTO_OPCODE_DESTROY_KEY,          destroy_key_handler},
+	{TS_CRYPTO_OPCODE_EXPORT_KEY,           export_key_handler},
+	{TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY,    export_public_key_handler},
+	{TS_CRYPTO_OPCODE_IMPORT_KEY,           import_key_handler},
+	{TS_CRYPTO_OPCODE_SIGN_HASH,            sign_hash_handler},
+	{TS_CRYPTO_OPCODE_VERIFY_HASH,          verify_hash_handler},
+	{TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT,   asymmetric_decrypt_handler},
+	{TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT,   asymmetric_encrypt_handler},
+	{TS_CRYPTO_OPCODE_GENERATE_RANDOM,      generate_random_handler},
+	{TS_CRYPTO_OPCODE_HASH_SETUP,           hash_setup_handler},
+	{TS_CRYPTO_OPCODE_HASH_UPDATE,          hash_update_handler},
+	{TS_CRYPTO_OPCODE_HASH_FINISH,          hash_finish_handler}
 };
 
 struct rpc_interface *mbed_crypto_provider_init(struct mbed_crypto_provider *context,
-                                        struct storage_backend *storage_backend,
-                                        int trng_instance)
+										struct storage_backend *storage_backend,
+										int trng_instance)
 {
-    struct rpc_interface *rpc_interface = NULL;
+	struct rpc_interface *rpc_interface = NULL;
 
-    trng_adapter_init(trng_instance);
+	crypto_context_pool_init(&context->context_pool);
+	trng_adapter_init(trng_instance);
 
-    /*
-     * A storage provider is required for persistent key storage.  As this
-     * is a mandatory feature of the crypto service, insist on a storage
-     * provider being available.
-     */
-    if (context && storage_backend) {
+	/*
+	 * A storage provider is required for persistent key storage.  As this
+	 * is a mandatory feature of the crypto service, insist on a storage
+	 * provider being available.
+	 */
+	if (context && storage_backend) {
 
-        for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
-            context->serializers[encoding] = NULL;
+		for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
+			context->serializers[encoding] = NULL;
 
-        service_provider_init(&context->base_provider, context,
-                    handler_table, sizeof(handler_table)/sizeof(struct service_handler));
+		service_provider_init(&context->base_provider, context,
+					handler_table, sizeof(handler_table)/sizeof(struct service_handler));
 
-        if ((psa_its_frontend_init(storage_backend) == PSA_SUCCESS) &&
-            (psa_crypto_init() == PSA_SUCCESS)) {
+		if ((psa_its_frontend_init(storage_backend) == PSA_SUCCESS) &&
+			(psa_crypto_init() == PSA_SUCCESS)) {
 
-            rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
-        }
-    }
+			rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
+		}
+	}
 
-    return rpc_interface;
+	return rpc_interface;
 }
 
 void mbed_crypto_provider_deinit(struct mbed_crypto_provider *context)
 {
-    (void)context;
-    trng_adapter_deinit();
+	trng_adapter_deinit();
+	crypto_context_pool_deinit(&context->context_pool);
 }
 
 void mbed_crypto_provider_register_serializer(struct mbed_crypto_provider *context,
-                        unsigned int encoding, const struct crypto_provider_serializer *serializer)
+						unsigned int encoding, const struct crypto_provider_serializer *serializer)
 {
-    if (encoding < TS_RPC_ENCODING_LIMIT)
-        context->serializers[encoding] = serializer;
+	if (encoding < TS_RPC_ENCODING_LIMIT)
+		context->serializers[encoding] = serializer;
 }
 
 static const struct crypto_provider_serializer* get_crypto_serializer(void *context,
-                                                        const struct call_req *req)
+														const struct call_req *req)
 {
-    struct mbed_crypto_provider *this_instance = (struct mbed_crypto_provider*)context;
-    const struct crypto_provider_serializer* serializer = NULL;
-    unsigned int encoding = call_req_get_encoding(req);
+	struct mbed_crypto_provider *this_instance = (struct mbed_crypto_provider*)context;
+	const struct crypto_provider_serializer* serializer = NULL;
+	unsigned int encoding = call_req_get_encoding(req);
 
-    if (encoding < TS_RPC_ENCODING_LIMIT) serializer = this_instance->serializers[encoding];
+	if (encoding < TS_RPC_ENCODING_LIMIT) serializer = this_instance->serializers[encoding];
 
-    return serializer;
+	return serializer;
 }
 
 static rpc_status_t nop_handler(void *context, struct call_req* req)
 {
-    /* Responds to a request by returning success */
-    rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
-    psa_status_t psa_status = PSA_SUCCESS;
+	/* Responds to a request by returning success */
+	rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
+	psa_status_t psa_status = PSA_SUCCESS;
 
-    (void)context;
-    call_req_set_opstatus(req, psa_status);
+	(void)context;
+	call_req_set_opstatus(req, psa_status);
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t generate_key_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    if (serializer)
-        rpc_status = serializer->deserialize_generate_key_req(req_buf, &attributes);
+	if (serializer)
+		rpc_status = serializer->deserialize_generate_key_req(req_buf, &attributes);
 
-    if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-        psa_status_t psa_status;
-        psa_key_id_t id;
+		psa_status_t psa_status;
+		psa_key_id_t id;
 
-        psa_status = psa_generate_key(&attributes, &id);
+		psa_status = psa_generate_key(&attributes, &id);
 
-        if (psa_status == PSA_SUCCESS) {
+		if (psa_status == PSA_SUCCESS) {
 
-            struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
-            rpc_status = serializer->serialize_generate_key_resp(resp_buf, id);
-        }
+			struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+			rpc_status = serializer->serialize_generate_key_resp(resp_buf, id);
+		}
 
-        call_req_set_opstatus(req, psa_status);
-    }
+		call_req_set_opstatus(req, psa_status);
+	}
 
-    psa_reset_key_attributes(&attributes);
+	psa_reset_key_attributes(&attributes);
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t destroy_key_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    psa_key_id_t id;
+	psa_key_id_t id;
 
-    if (serializer)
-        rpc_status = serializer->deserialize_destroy_key_req(req_buf, &id);
+	if (serializer)
+		rpc_status = serializer->deserialize_destroy_key_req(req_buf, &id);
 
-    if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-        psa_status_t psa_status;
+		psa_status_t psa_status;
 
-        psa_status = psa_destroy_key(id);
-        call_req_set_opstatus(req, psa_status);
-    }
+		psa_status = psa_destroy_key(id);
+		call_req_set_opstatus(req, psa_status);
+	}
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t export_key_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    psa_key_id_t id;
+	psa_key_id_t id;
 
-    if (serializer)
-        rpc_status = serializer->deserialize_export_key_req(req_buf, &id);
+	if (serializer)
+		rpc_status = serializer->deserialize_export_key_req(req_buf, &id);
 
-    if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-        psa_status_t psa_status;
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+		psa_status_t psa_status;
+		psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-        psa_status = psa_get_key_attributes(id, &attributes);
+		psa_status = psa_get_key_attributes(id, &attributes);
 
-        if (psa_status == PSA_SUCCESS) {
+		if (psa_status == PSA_SUCCESS) {
 
-            size_t max_export_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
-                psa_get_key_type(&attributes),
-                psa_get_key_bits(&attributes));
+			size_t max_export_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
+				psa_get_key_type(&attributes),
+				psa_get_key_bits(&attributes));
 
-            uint8_t *key_buffer = malloc(max_export_size);
+			uint8_t *key_buffer = malloc(max_export_size);
 
-            if (key_buffer) {
+			if (key_buffer) {
 
-                size_t export_size;
-                psa_status = psa_export_key(id, key_buffer, max_export_size, &export_size);
+				size_t export_size;
+				psa_status = psa_export_key(id, key_buffer, max_export_size, &export_size);
 
-                if (psa_status == PSA_SUCCESS) {
+				if (psa_status == PSA_SUCCESS) {
 
-                    struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
-                    rpc_status = serializer->serialize_export_key_resp(resp_buf, key_buffer, export_size);
-                }
+					struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+					rpc_status = serializer->serialize_export_key_resp(resp_buf, key_buffer, export_size);
+				}
 
-                free(key_buffer);
-            }
-            else {
-                /* Failed to allocate key buffer */
-                rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
-            }
-        }
+				free(key_buffer);
+			}
+			else {
+				/* Failed to allocate key buffer */
+				rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+			}
+		}
 
-        call_req_set_opstatus(req, psa_status);
-        psa_reset_key_attributes(&attributes);
-    }
+		call_req_set_opstatus(req, psa_status);
+		psa_reset_key_attributes(&attributes);
+	}
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t export_public_key_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    psa_key_id_t id;
+	psa_key_id_t id;
 
-    if (serializer)
-        rpc_status = serializer->deserialize_export_public_key_req(req_buf, &id);
+	if (serializer)
+		rpc_status = serializer->deserialize_export_public_key_req(req_buf, &id);
 
-    if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-        psa_status_t psa_status;
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+		psa_status_t psa_status;
+		psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-        psa_status = psa_get_key_attributes(id, &attributes);
+		psa_status = psa_get_key_attributes(id, &attributes);
 
-        if (psa_status == PSA_SUCCESS) {
+		if (psa_status == PSA_SUCCESS) {
 
-            size_t max_export_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(
-                PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(psa_get_key_type(&attributes)),
-                psa_get_key_bits(&attributes));
+			size_t max_export_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(
+				PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(psa_get_key_type(&attributes)),
+				psa_get_key_bits(&attributes));
 
-            uint8_t *key_buffer = malloc(max_export_size);
+			uint8_t *key_buffer = malloc(max_export_size);
 
-            if (key_buffer) {
+			if (key_buffer) {
 
-                size_t export_size;
-                psa_status = psa_export_public_key(id, key_buffer, max_export_size, &export_size);
+				size_t export_size;
+				psa_status = psa_export_public_key(id, key_buffer, max_export_size, &export_size);
 
-                if (psa_status == PSA_SUCCESS) {
+				if (psa_status == PSA_SUCCESS) {
 
-                    struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
-                    rpc_status = serializer->serialize_export_public_key_resp(resp_buf, key_buffer, export_size);
-                }
+					struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+					rpc_status = serializer->serialize_export_public_key_resp(resp_buf, key_buffer, export_size);
+				}
 
-                free(key_buffer);
-            }
-            else {
-                /* Failed to allocate key buffer */
-                rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
-            }
-        }
+				free(key_buffer);
+			}
+			else {
+				/* Failed to allocate key buffer */
+				rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+			}
+		}
 
-        call_req_set_opstatus(req, psa_status);
-        psa_reset_key_attributes(&attributes);
-    }
+		call_req_set_opstatus(req, psa_status);
+		psa_reset_key_attributes(&attributes);
+	}
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t import_key_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    if (serializer) {
+	if (serializer) {
 
-        size_t key_data_len = serializer->max_deserialised_parameter_size(req_buf);
-        uint8_t *key_buffer = malloc(key_data_len);
+		size_t key_data_len = serializer->max_deserialised_parameter_size(req_buf);
+		uint8_t *key_buffer = malloc(key_data_len);
 
-        if (key_buffer) {
+		if (key_buffer) {
 
-            psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-            rpc_status = serializer->deserialize_import_key_req(req_buf, &attributes, key_buffer, &key_data_len);
+			psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+			rpc_status = serializer->deserialize_import_key_req(req_buf, &attributes, key_buffer, &key_data_len);
 
-            if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+			if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-                psa_status_t psa_status;
-                psa_key_id_t id;
+				psa_status_t psa_status;
+				psa_key_id_t id;
 
-                psa_status = psa_import_key(&attributes, key_buffer, key_data_len, &id);
+				psa_status = psa_import_key(&attributes, key_buffer, key_data_len, &id);
 
-                if (psa_status == PSA_SUCCESS) {
+				if (psa_status == PSA_SUCCESS) {
 
-                    struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
-                    rpc_status = serializer->serialize_import_key_resp(resp_buf, id);
-                }
+					struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+					rpc_status = serializer->serialize_import_key_resp(resp_buf, id);
+				}
 
-                call_req_set_opstatus(req, psa_status);
-            }
+				call_req_set_opstatus(req, psa_status);
+			}
 
-            psa_reset_key_attributes(&attributes);
-            free(key_buffer);
-        }
-        else {
+			psa_reset_key_attributes(&attributes);
+			free(key_buffer);
+		}
+		else {
 
-            rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
-        }
-    }
+			rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+		}
+	}
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t sign_hash_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    psa_key_id_t id;
-    psa_algorithm_t alg;
-    size_t hash_len = PSA_HASH_MAX_SIZE;
-    uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
+	psa_key_id_t id;
+	psa_algorithm_t alg;
+	size_t hash_len = PSA_HASH_MAX_SIZE;
+	uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
 
-    if (serializer)
-        rpc_status = serializer->deserialize_sign_hash_req(req_buf, &id, &alg, hash_buffer, &hash_len);
+	if (serializer)
+		rpc_status = serializer->deserialize_sign_hash_req(req_buf, &id, &alg, hash_buffer, &hash_len);
 
-    if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-        psa_status_t psa_status;
-        size_t sig_len;
-        uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
+		psa_status_t psa_status;
+		size_t sig_len;
+		uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
 
-        psa_status = psa_sign_hash(id, alg,
-                    hash_buffer, hash_len,
-                    sig_buffer, sizeof(sig_buffer), &sig_len);
+		psa_status = psa_sign_hash(id, alg,
+					hash_buffer, hash_len,
+					sig_buffer, sizeof(sig_buffer), &sig_len);
 
-        if (psa_status == PSA_SUCCESS) {
+		if (psa_status == PSA_SUCCESS) {
 
-            struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
-            rpc_status = serializer->serialize_sign_hash_resp(resp_buf, sig_buffer, sig_len);
-        }
+			struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+			rpc_status = serializer->serialize_sign_hash_resp(resp_buf, sig_buffer, sig_len);
+		}
 
-        call_req_set_opstatus(req, psa_status);
-    }
+		call_req_set_opstatus(req, psa_status);
+	}
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t verify_hash_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    psa_key_id_t id;
-    psa_algorithm_t alg;
-    size_t hash_len = PSA_HASH_MAX_SIZE;
-    uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
-    size_t sig_len = PSA_SIGNATURE_MAX_SIZE;
-    uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
+	psa_key_id_t id;
+	psa_algorithm_t alg;
+	size_t hash_len = PSA_HASH_MAX_SIZE;
+	uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
+	size_t sig_len = PSA_SIGNATURE_MAX_SIZE;
+	uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
 
-    if (serializer)
-        rpc_status = serializer->deserialize_verify_hash_req(req_buf, &id, &alg,
-                                            hash_buffer, &hash_len,
-                                            sig_buffer, &sig_len);
+	if (serializer)
+		rpc_status = serializer->deserialize_verify_hash_req(req_buf, &id, &alg,
+											hash_buffer, &hash_len,
+											sig_buffer, &sig_len);
 
-    if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-        psa_status_t psa_status;
+		psa_status_t psa_status;
 
-        psa_status = psa_verify_hash(id, alg,
-                    hash_buffer, hash_len,
-                    sig_buffer, sig_len);
+		psa_status = psa_verify_hash(id, alg,
+					hash_buffer, hash_len,
+					sig_buffer, sig_len);
 
-        call_req_set_opstatus(req, psa_status);
-    }
+		call_req_set_opstatus(req, psa_status);
+	}
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t asymmetric_decrypt_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    if (serializer) {
+	if (serializer) {
 
-        size_t max_param_size = serializer->max_deserialised_parameter_size(req_buf);
+		size_t max_param_size = serializer->max_deserialised_parameter_size(req_buf);
 
-        psa_key_id_t id;
-        psa_algorithm_t alg;
-        size_t ciphertext_len = max_param_size;
-        uint8_t *ciphertext_buffer = malloc(ciphertext_len);
-        size_t salt_len = max_param_size;
-        uint8_t *salt_buffer = malloc(salt_len);
+		psa_key_id_t id;
+		psa_algorithm_t alg;
+		size_t ciphertext_len = max_param_size;
+		uint8_t *ciphertext_buffer = malloc(ciphertext_len);
+		size_t salt_len = max_param_size;
+		uint8_t *salt_buffer = malloc(salt_len);
 
-        if (ciphertext_buffer && salt_buffer) {
+		if (ciphertext_buffer && salt_buffer) {
 
-            rpc_status = serializer->deserialize_asymmetric_decrypt_req(req_buf,
-                                                    &id, &alg,
-                                                    ciphertext_buffer, &ciphertext_len,
-                                                    salt_buffer, &salt_len);
+			rpc_status = serializer->deserialize_asymmetric_decrypt_req(req_buf,
+													&id, &alg,
+													ciphertext_buffer, &ciphertext_len,
+													salt_buffer, &salt_len);
 
-            if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+			if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-                psa_status_t psa_status;
-                psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+				psa_status_t psa_status;
+				psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-                psa_status = psa_get_key_attributes(id, &attributes);
+				psa_status = psa_get_key_attributes(id, &attributes);
 
-                if (psa_status == PSA_SUCCESS) {
+				if (psa_status == PSA_SUCCESS) {
 
-                    size_t max_decrypt_size = PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(
-                        psa_get_key_type(&attributes),
-                        psa_get_key_bits(&attributes),
-                        alg);
+					size_t max_decrypt_size = PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(
+						psa_get_key_type(&attributes),
+						psa_get_key_bits(&attributes),
+						alg);
 
-                    size_t plaintext_len;
-                    uint8_t *plaintext_buffer = malloc(max_decrypt_size);
+					size_t plaintext_len;
+					uint8_t *plaintext_buffer = malloc(max_decrypt_size);
 
-                    if (plaintext_buffer) {
+					if (plaintext_buffer) {
 
-                        /* Salt is an optional parameter */
-                        uint8_t *salt = (salt_len) ? salt_buffer : NULL;
+						/* Salt is an optional parameter */
+						uint8_t *salt = (salt_len) ? salt_buffer : NULL;
 
-                        psa_status = psa_asymmetric_decrypt(id, alg,
-                                    ciphertext_buffer, ciphertext_len,
-                                    salt, salt_len,
-                                    plaintext_buffer, max_decrypt_size, &plaintext_len);
+						psa_status = psa_asymmetric_decrypt(id, alg,
+									ciphertext_buffer, ciphertext_len,
+									salt, salt_len,
+									plaintext_buffer, max_decrypt_size, &plaintext_len);
 
-                        if (psa_status == PSA_SUCCESS) {
+						if (psa_status == PSA_SUCCESS) {
 
-                            struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
-                            rpc_status = serializer->serialize_asymmetric_decrypt_resp(resp_buf,
-                                                                plaintext_buffer, plaintext_len);
-                        }
+							struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+							rpc_status = serializer->serialize_asymmetric_decrypt_resp(resp_buf,
+																plaintext_buffer, plaintext_len);
+						}
 
-                        free(plaintext_buffer);
-                    }
-                    else {
-                        /* Failed to allocate ouptput buffer */
-                        rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
-                    }
-                }
+						free(plaintext_buffer);
+					}
+					else {
+						/* Failed to allocate ouptput buffer */
+						rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+					}
+				}
 
-                call_req_set_opstatus(req, psa_status);
-                psa_reset_key_attributes(&attributes);
-            }
-        }
-        else {
-            /* Failed to allocate buffers */
-            rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
-        }
+				call_req_set_opstatus(req, psa_status);
+				psa_reset_key_attributes(&attributes);
+			}
+		}
+		else {
+			/* Failed to allocate buffers */
+			rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+		}
 
-        free(ciphertext_buffer);
-        free(salt_buffer);
-    }
+		free(ciphertext_buffer);
+		free(salt_buffer);
+	}
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t asymmetric_encrypt_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    if (serializer) {
+	if (serializer) {
 
-        size_t max_param_size = serializer->max_deserialised_parameter_size(req_buf);
+		size_t max_param_size = serializer->max_deserialised_parameter_size(req_buf);
 
-        psa_key_id_t id;
-        psa_algorithm_t alg;
-        size_t plaintext_len = max_param_size;
-        uint8_t *plaintext_buffer = malloc(plaintext_len);
-        size_t salt_len = max_param_size;
-        uint8_t *salt_buffer = malloc(salt_len);
+		psa_key_id_t id;
+		psa_algorithm_t alg;
+		size_t plaintext_len = max_param_size;
+		uint8_t *plaintext_buffer = malloc(plaintext_len);
+		size_t salt_len = max_param_size;
+		uint8_t *salt_buffer = malloc(salt_len);
 
-        if (plaintext_buffer && salt_buffer) {
+		if (plaintext_buffer && salt_buffer) {
 
-            rpc_status = serializer->deserialize_asymmetric_encrypt_req(req_buf,
-                                                    &id, &alg,
-                                                    plaintext_buffer, &plaintext_len,
-                                                    salt_buffer, &salt_len);
+			rpc_status = serializer->deserialize_asymmetric_encrypt_req(req_buf,
+													&id, &alg,
+													plaintext_buffer, &plaintext_len,
+													salt_buffer, &salt_len);
 
-            if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+			if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-                psa_status_t psa_status;
-                psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+				psa_status_t psa_status;
+				psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-                psa_status = psa_get_key_attributes(id, &attributes);
+				psa_status = psa_get_key_attributes(id, &attributes);
 
-                if (psa_status == PSA_SUCCESS) {
+				if (psa_status == PSA_SUCCESS) {
 
-                    size_t max_encrypt_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(
-                        psa_get_key_type(&attributes),
-                        psa_get_key_bits(&attributes),
-                        alg);
+					size_t max_encrypt_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(
+						psa_get_key_type(&attributes),
+						psa_get_key_bits(&attributes),
+						alg);
 
-                    size_t ciphertext_len;
-                    uint8_t *ciphertext_buffer = malloc(max_encrypt_size);
+					size_t ciphertext_len;
+					uint8_t *ciphertext_buffer = malloc(max_encrypt_size);
 
-                    if (ciphertext_buffer) {
+					if (ciphertext_buffer) {
 
-                        /* Salt is an optional parameter */
-                        uint8_t *salt = (salt_len) ? salt_buffer : NULL;
+						/* Salt is an optional parameter */
+						uint8_t *salt = (salt_len) ? salt_buffer : NULL;
 
-                        psa_status = psa_asymmetric_encrypt(id, alg,
-                                    plaintext_buffer, plaintext_len,
-                                    salt, salt_len,
-                                    ciphertext_buffer, max_encrypt_size, &ciphertext_len);
+						psa_status = psa_asymmetric_encrypt(id, alg,
+									plaintext_buffer, plaintext_len,
+									salt, salt_len,
+									ciphertext_buffer, max_encrypt_size, &ciphertext_len);
 
-                        if (psa_status == PSA_SUCCESS) {
+						if (psa_status == PSA_SUCCESS) {
 
-                            struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
-                            rpc_status = serializer->serialize_asymmetric_encrypt_resp(resp_buf,
-                                                                ciphertext_buffer, ciphertext_len);
-                        }
+							struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+							rpc_status = serializer->serialize_asymmetric_encrypt_resp(resp_buf,
+																ciphertext_buffer, ciphertext_len);
+						}
 
-                        free(ciphertext_buffer);
-                    }
-                    else {
-                        /* Failed to allocate ouptput buffer */
-                        rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
-                    }
-                }
+						free(ciphertext_buffer);
+					}
+					else {
+						/* Failed to allocate ouptput buffer */
+						rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+					}
+				}
 
-                call_req_set_opstatus(req, psa_status);
-                psa_reset_key_attributes(&attributes);
-            }
-        }
-        else {
-            /* Failed to allocate buffers */
-            rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
-        }
+				call_req_set_opstatus(req, psa_status);
+				psa_reset_key_attributes(&attributes);
+			}
+		}
+		else {
+			/* Failed to allocate buffers */
+			rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+		}
 
-        free(plaintext_buffer);
-        free(salt_buffer);
-    }
+		free(plaintext_buffer);
+		free(salt_buffer);
+	}
 
-    return rpc_status;
+	return rpc_status;
 }
 
 static rpc_status_t generate_random_handler(void *context, struct call_req* req)
 {
-    rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
-    struct call_param_buf *req_buf = call_req_get_req_buf(req);
-    const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
 
-    size_t output_size;
+	size_t output_size;
 
-    if (serializer)
-        rpc_status = serializer->deserialize_generate_random_req(req_buf, &output_size);
+	if (serializer)
+		rpc_status = serializer->deserialize_generate_random_req(req_buf, &output_size);
 
-    if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
 
-        psa_status_t psa_status;
-        uint8_t *output_buffer = malloc(output_size);
+		psa_status_t psa_status;
+		uint8_t *output_buffer = malloc(output_size);
 
-        if (output_buffer) {
+		if (output_buffer) {
 
-            psa_status = psa_generate_random(output_buffer, output_size);
+			psa_status = psa_generate_random(output_buffer, output_size);
 
-            if (psa_status == PSA_SUCCESS) {
+			if (psa_status == PSA_SUCCESS) {
 
-                struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
-                rpc_status = serializer->serialize_generate_random_resp(resp_buf,
-                                                    output_buffer, output_size);
-            }
+				struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+				rpc_status = serializer->serialize_generate_random_resp(resp_buf,
+													output_buffer, output_size);
+			}
 
-            call_req_set_opstatus(req, psa_status);
-            free(output_buffer);
-        }
-        else {
-            /* Failed to allocate output buffer */
-            rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
-        }
-    }
+			call_req_set_opstatus(req, psa_status);
+			free(output_buffer);
+		}
+		else {
+			/* Failed to allocate output buffer */
+			rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+		}
+	}
 
-    return rpc_status;
+	return rpc_status;
+}
+
+static rpc_status_t hash_setup_handler(void *context, struct call_req* req)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	struct mbed_crypto_provider *this_instance = (struct mbed_crypto_provider*)context;
+
+	psa_algorithm_t alg;
+
+	if (serializer)
+		rpc_status = serializer->deserialize_hash_setup_req(req_buf, &alg);
+
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+		uint32_t op_handle;
+
+		struct crypto_context *crypto_context =
+			crypto_context_pool_alloc(&this_instance->context_pool,
+				CRYPTO_CONTEXT_OP_ID_HASH, call_req_get_caller_id(req),
+				&op_handle);
+
+		if (crypto_context) {
+
+			psa_status_t psa_status;
+
+			crypto_context->op.hash = psa_hash_operation_init();
+			psa_status = psa_hash_setup(&crypto_context->op.hash, alg);
+
+			if (psa_status == PSA_SUCCESS) {
+
+				struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+				rpc_status = serializer->serialize_hash_setup_resp(resp_buf, op_handle);
+			}
+
+			if ((psa_status != PSA_SUCCESS) || (rpc_status != TS_RPC_CALL_ACCEPTED)) {
+
+				crypto_context_pool_free(&this_instance->context_pool, crypto_context);
+			}
+
+			call_req_set_opstatus(req, psa_status);
+		}
+		else {
+			/* Failed to allocate crypto context for transaction */
+			rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+		}
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t hash_update_handler(void *context, struct call_req* req)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	struct mbed_crypto_provider *this_instance = (struct mbed_crypto_provider*)context;
+
+	uint32_t op_handle;
+	const uint8_t *data;
+	size_t data_len;
+
+	if (serializer)
+		rpc_status = serializer->deserialize_hash_update_req(req_buf, &op_handle, &data, &data_len);
+
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+		struct crypto_context *crypto_context =
+			crypto_context_pool_find(&this_instance->context_pool,
+				CRYPTO_CONTEXT_OP_ID_HASH, call_req_get_caller_id(req),
+				op_handle);
+
+		if (crypto_context) {
+
+			psa_status_t psa_status = psa_hash_update(&crypto_context->op.hash, data, data_len);
+			call_req_set_opstatus(req, psa_status);
+		}
+		else {
+			/* Requested context doesn't exist */
+			rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+		}
+	}
+
+	return rpc_status;
+}
+
+static rpc_status_t hash_finish_handler(void *context, struct call_req* req)
+{
+	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+	const struct crypto_provider_serializer *serializer = get_crypto_serializer(context, req);
+	struct mbed_crypto_provider *this_instance = (struct mbed_crypto_provider*)context;
+
+	uint32_t op_handle;
+
+	if (serializer)
+		rpc_status = serializer->deserialize_hash_finish_req(req_buf, &op_handle);
+
+	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+		struct crypto_context *crypto_context =
+			crypto_context_pool_find(&this_instance->context_pool,
+				CRYPTO_CONTEXT_OP_ID_HASH, call_req_get_caller_id(req),
+				op_handle);
+
+		if (crypto_context) {
+
+			psa_status_t psa_status;
+			size_t hash_len;
+			uint8_t hash[PSA_HASH_MAX_SIZE];
+
+			psa_status = psa_hash_finish(&crypto_context->op.hash, hash, sizeof(hash), &hash_len);
+
+			if (psa_status == PSA_SUCCESS) {
+
+				struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+				rpc_status = serializer->serialize_hash_finish_resp(resp_buf, hash, hash_len);
+			}
+
+			crypto_context_pool_free(&this_instance->context_pool, crypto_context);
+
+			call_req_set_opstatus(req, psa_status);
+		}
+		else {
+			/* Requested context doesn't exist */
+			rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+		}
+	}
+
+	return rpc_status;
 }