aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Hall <julian.hall@arm.com>2021-07-15 14:31:07 +0100
committerGyorgy Szing <Gyorgy.Szing@arm.com>2021-10-06 00:48:23 +0200
commit0ed3d4538b2836fdac44886a6b4e7828cfb6bbe0 (patch)
treeadd78e0668a3a3abb185549cc9248daf62891695
parent7bfb18e215aae621fe5f331b20c8ea0e329c42ef (diff)
downloadtrusted-services-0ed3d4538b2836fdac44886a6b4e7828cfb6bbe0.tar.gz
Extend hash operation support
Remaining hash operations for aborting, verifying and cloning hash operations added. Signed-off-by: Julian Hall <julian.hall@arm.com> Change-Id: If40483fe1be095145bb046d8d9fae4d0ad030931
-rw-r--r--components/service/crypto/client/psa/psa_hash.c121
-rw-r--r--components/service/crypto/provider/extension/hash/hash_provider.c147
-rw-r--r--components/service/crypto/provider/extension/hash/serializer/hash_provider_serializer.h16
-rw-r--r--components/service/crypto/provider/extension/hash/serializer/packed-c/packedc_hash_provider_serializer.c100
-rw-r--r--protocols/service/crypto/packed-c/hash.h47
-rw-r--r--protocols/service/crypto/packed-c/opcodes.h22
6 files changed, 426 insertions, 27 deletions
diff --git a/components/service/crypto/client/psa/psa_hash.c b/components/service/crypto/client/psa/psa_hash.c
index 55970ce3a..61bcf233f 100644
--- a/components/service/crypto/client/psa/psa_hash.c
+++ b/components/service/crypto/client/psa/psa_hash.c
@@ -179,20 +179,135 @@ psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
{
- return PSA_ERROR_NOT_SUPPORTED;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ struct ts_crypto_hash_abort_in req_msg;
+ size_t req_fixed_len = sizeof(struct ts_crypto_hash_abort_in);
+ size_t req_len = req_fixed_len;
+
+ req_msg.op_handle = operation->handle;
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(psa_crypto_client_instance.caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ memcpy(req_buf, &req_msg, req_fixed_len);
+
+ psa_crypto_client_instance.rpc_status =
+ rpc_caller_invoke(psa_crypto_client_instance.caller, call_handle,
+ TS_CRYPTO_OPCODE_HASH_ABORT, &opstatus, &resp_buf, &resp_len);
+
+ if (psa_crypto_client_instance.rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
+
+ rpc_caller_end(psa_crypto_client_instance.caller, call_handle);
+ }
+
+ return psa_status;
}
psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
const uint8_t *hash,
size_t hash_length)
{
- return PSA_ERROR_NOT_SUPPORTED;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ struct ts_crypto_hash_verify_in req_msg;
+ size_t req_fixed_len = sizeof(struct ts_crypto_hash_verify_in);
+ size_t req_len = req_fixed_len;
+
+ req_msg.op_handle = operation->handle;
+
+ /* Mandatory input data parameter */
+ struct tlv_record data_record;
+ data_record.tag = TS_CRYPTO_HASH_VERIFY_IN_TAG_HASH;
+ data_record.length = hash_length;
+ data_record.value = hash;
+ req_len += tlv_required_space(data_record.length);
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(psa_crypto_client_instance.caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+ struct tlv_iterator req_iter;
+
+ memcpy(req_buf, &req_msg, req_fixed_len);
+
+ tlv_iterator_begin(&req_iter, &req_buf[req_fixed_len], req_len - req_fixed_len);
+ tlv_encode(&req_iter, &data_record);
+
+ psa_crypto_client_instance.rpc_status =
+ rpc_caller_invoke(psa_crypto_client_instance.caller, call_handle,
+ TS_CRYPTO_OPCODE_HASH_VERIFY, &opstatus, &resp_buf, &resp_len);
+
+ if (psa_crypto_client_instance.rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
+
+ rpc_caller_end(psa_crypto_client_instance.caller, call_handle);
+ }
+
+ return psa_status;
}
psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
psa_hash_operation_t *target_operation)
{
- return PSA_ERROR_NOT_SUPPORTED;
+ psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ struct ts_crypto_hash_clone_in req_msg;
+ size_t req_fixed_len = sizeof(struct ts_crypto_hash_clone_in);
+ size_t req_len = req_fixed_len;
+
+ req_msg.source_op_handle = source_operation->handle;
+
+ rpc_call_handle call_handle;
+ uint8_t *req_buf;
+
+ call_handle = rpc_caller_begin(psa_crypto_client_instance.caller, &req_buf, req_len);
+
+ if (call_handle) {
+
+ uint8_t *resp_buf;
+ size_t resp_len;
+ int opstatus;
+
+ memcpy(req_buf, &req_msg, req_fixed_len);
+
+ psa_crypto_client_instance.rpc_status =
+ rpc_caller_invoke(psa_crypto_client_instance.caller, call_handle,
+ TS_CRYPTO_OPCODE_HASH_CLONE, &opstatus, &resp_buf, &resp_len);
+
+ if (psa_crypto_client_instance.rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status = opstatus;
+
+ if (psa_status == PSA_SUCCESS) {
+
+ if (resp_len >= sizeof(struct ts_crypto_hash_clone_out)) {
+
+ struct ts_crypto_hash_clone_out resp_msg;
+ memcpy(&resp_msg, resp_buf, sizeof(struct ts_crypto_hash_clone_out));
+ target_operation->handle = resp_msg.target_op_handle;
+ }
+ else {
+ /* Failed to decode response message */
+ psa_status = PSA_ERROR_GENERIC_ERROR;
+ }
+ }
+ }
+
+ rpc_caller_end(psa_crypto_client_instance.caller, call_handle);
+ }
+
+ return psa_status;
}
psa_status_t psa_hash_compare(psa_algorithm_t alg,
diff --git a/components/service/crypto/provider/extension/hash/hash_provider.c b/components/service/crypto/provider/extension/hash/hash_provider.c
index 5a7ae3c28..2c560513f 100644
--- a/components/service/crypto/provider/extension/hash/hash_provider.c
+++ b/components/service/crypto/provider/extension/hash/hash_provider.c
@@ -14,12 +14,18 @@
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);
+static rpc_status_t hash_abort_handler(void *context, struct call_req* req);
+static rpc_status_t hash_verify_handler(void *context, struct call_req* req);
+static rpc_status_t hash_clone_handler(void *context, struct call_req* req);
/* Handler mapping table for service */
static const struct service_handler handler_table[] = {
{TS_CRYPTO_OPCODE_HASH_SETUP, hash_setup_handler},
{TS_CRYPTO_OPCODE_HASH_UPDATE, hash_update_handler},
- {TS_CRYPTO_OPCODE_HASH_FINISH, hash_finish_handler}
+ {TS_CRYPTO_OPCODE_HASH_FINISH, hash_finish_handler},
+ {TS_CRYPTO_OPCODE_HASH_ABORT, hash_abort_handler},
+ {TS_CRYPTO_OPCODE_HASH_VERIFY, hash_verify_handler},
+ {TS_CRYPTO_OPCODE_HASH_CLONE, hash_clone_handler}
};
void hash_provider_init(struct hash_provider *context)
@@ -123,6 +129,8 @@ static rpc_status_t hash_update_handler(void *context, struct call_req* req)
if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+ psa_status_t psa_status = PSA_ERROR_BAD_STATE;
+
struct crypto_context *crypto_context =
crypto_context_pool_find(&this_instance->context_pool,
CRYPTO_CONTEXT_OP_ID_HASH, call_req_get_caller_id(req),
@@ -130,13 +138,10 @@ static rpc_status_t hash_update_handler(void *context, struct call_req* req)
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;
+ psa_status = psa_hash_update(&crypto_context->op.hash, data, data_len);
}
+
+ call_req_set_opstatus(req, psa_status);
}
return rpc_status;
@@ -156,6 +161,8 @@ static rpc_status_t hash_finish_handler(void *context, struct call_req* req)
if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+ psa_status_t psa_status = PSA_ERROR_BAD_STATE;
+
struct crypto_context *crypto_context =
crypto_context_pool_find(&this_instance->context_pool,
CRYPTO_CONTEXT_OP_ID_HASH, call_req_get_caller_id(req),
@@ -163,7 +170,6 @@ static rpc_status_t hash_finish_handler(void *context, struct call_req* req)
if (crypto_context) {
- psa_status_t psa_status;
size_t hash_len;
uint8_t hash[PSA_HASH_MAX_SIZE];
@@ -176,13 +182,130 @@ static rpc_status_t hash_finish_handler(void *context, struct call_req* req)
}
crypto_context_pool_free(&this_instance->context_pool, crypto_context);
+ }
- call_req_set_opstatus(req, psa_status);
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t hash_abort_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 hash_provider_serializer *serializer = get_serializer(context, req);
+ struct hash_provider *this_instance = (struct hash_provider*)context;
+
+ uint32_t op_handle;
+
+ if (serializer)
+ rpc_status = serializer->deserialize_hash_abort_req(req_buf, &op_handle);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ /* Return success if operation is no longer active and
+ * doesn't need aborting.
+ */
+ psa_status_t psa_status = PSA_SUCCESS;
+
+ 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 = psa_hash_abort(&crypto_context->op.hash);
+ crypto_context_pool_free(&this_instance->context_pool, crypto_context);
}
- else {
- /* Requested context doesn't exist */
- rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
+
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t hash_verify_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 hash_provider_serializer *serializer = get_serializer(context, req);
+ struct hash_provider *this_instance = (struct hash_provider*)context;
+
+ uint32_t op_handle;
+ const uint8_t *hash;
+ size_t hash_len;
+
+ if (serializer)
+ rpc_status = serializer->deserialize_hash_verify_req(req_buf, &op_handle, &hash, &hash_len);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status = PSA_ERROR_BAD_STATE;
+
+ 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 = psa_hash_verify(&crypto_context->op.hash, hash, hash_len);
+ }
+
+ call_req_set_opstatus(req, psa_status);
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t hash_clone_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 hash_provider_serializer *serializer = get_serializer(context, req);
+ struct hash_provider *this_instance = (struct hash_provider*)context;
+
+ uint32_t source_op_handle;
+
+ if (serializer)
+ rpc_status = serializer->deserialize_hash_clone_req(req_buf, &source_op_handle);
+
+ if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+
+ psa_status_t psa_status = PSA_ERROR_BAD_STATE;
+
+ struct crypto_context *source_crypto_context =
+ crypto_context_pool_find(&this_instance->context_pool,
+ CRYPTO_CONTEXT_OP_ID_HASH, call_req_get_caller_id(req),
+ source_op_handle);
+
+ if (source_crypto_context) {
+
+ uint32_t target_op_handle;
+
+ struct crypto_context *target_crypto_context = crypto_context_pool_alloc(
+ &this_instance->context_pool,
+ CRYPTO_CONTEXT_OP_ID_HASH, call_req_get_caller_id(req),
+ &target_op_handle);
+
+ if (target_crypto_context) {
+
+ target_crypto_context->op.hash = psa_hash_operation_init();
+
+ psa_status = psa_hash_clone(&source_crypto_context->op.hash,
+ &target_crypto_context->op.hash);
+
+ if (psa_status == PSA_SUCCESS) {
+
+ struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ rpc_status = serializer->serialize_hash_clone_resp(resp_buf, target_op_handle);
+ }
+ }
}
+
+ call_req_set_opstatus(req, psa_status);
}
return rpc_status;
diff --git a/components/service/crypto/provider/extension/hash/serializer/hash_provider_serializer.h b/components/service/crypto/provider/extension/hash/serializer/hash_provider_serializer.h
index 5aa3c95e2..1611e6e63 100644
--- a/components/service/crypto/provider/extension/hash/serializer/hash_provider_serializer.h
+++ b/components/service/crypto/provider/extension/hash/serializer/hash_provider_serializer.h
@@ -35,6 +35,22 @@ struct hash_provider_serializer {
rpc_status_t (*serialize_hash_finish_resp)(struct call_param_buf *resp_buf,
const uint8_t *hash, size_t hash_len);
+
+ /* Operation: hash_abort */
+ rpc_status_t (*deserialize_hash_abort_req)(const struct call_param_buf *req_buf,
+ uint32_t *op_handle);
+
+ /* Operation: hash_verify */
+ rpc_status_t (*deserialize_hash_verify_req)(const struct call_param_buf *req_buf,
+ uint32_t *op_handle,
+ const uint8_t **hash, size_t *hash_len);
+
+ /* Operation: hash_clone */
+ rpc_status_t (*deserialize_hash_clone_req)(const struct call_param_buf *req_buf,
+ uint32_t *source_op_handle);
+
+ rpc_status_t (*serialize_hash_clone_resp)(struct call_param_buf *resp_buf,
+ uint32_t target_op_handle);
};
#endif /* HASH_PROVIDER_SERIALIZER_H */
diff --git a/components/service/crypto/provider/extension/hash/serializer/packed-c/packedc_hash_provider_serializer.c b/components/service/crypto/provider/extension/hash/serializer/packed-c/packedc_hash_provider_serializer.c
index 2006f38fb..ac0c35e47 100644
--- a/components/service/crypto/provider/extension/hash/serializer/packed-c/packedc_hash_provider_serializer.c
+++ b/components/service/crypto/provider/extension/hash/serializer/packed-c/packedc_hash_provider_serializer.c
@@ -45,7 +45,6 @@ static rpc_status_t serialize_hash_setup_resp(struct call_param_buf *resp_buf,
}
return rpc_status;
-
}
/* Operation: hash_update */
@@ -126,6 +125,99 @@ static rpc_status_t serialize_hash_finish_resp(struct call_param_buf *resp_buf,
return rpc_status;
}
+/* Operation: hash_abort */
+static rpc_status_t deserialize_hash_abort_req(const struct call_param_buf *req_buf,
+ uint32_t *op_handle)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ struct ts_crypto_hash_abort_in recv_msg;
+ size_t expected_fixed_len = sizeof(struct ts_crypto_hash_abort_in);
+
+ if (expected_fixed_len <= req_buf->data_len) {
+
+ memcpy(&recv_msg, req_buf->data, expected_fixed_len);
+ *op_handle = recv_msg.op_handle;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+/* Operation: hash_verify */
+static rpc_status_t deserialize_hash_verify_req(const struct call_param_buf *req_buf,
+ uint32_t *op_handle,
+ const uint8_t **hash, size_t *hash_len)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ struct ts_crypto_hash_verify_in recv_msg;
+ size_t expected_fixed_len = sizeof(struct ts_crypto_hash_verify_in);
+
+ if (expected_fixed_len <= req_buf->data_len) {
+
+ struct tlv_const_iterator req_iter;
+ struct tlv_record decoded_record;
+
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+
+ memcpy(&recv_msg, req_buf->data, expected_fixed_len);
+
+ *op_handle = recv_msg.op_handle;
+
+ tlv_const_iterator_begin(&req_iter,
+ (uint8_t*)req_buf->data + expected_fixed_len,
+ req_buf->data_len - expected_fixed_len);
+
+ if (tlv_find_decode(&req_iter, TS_CRYPTO_HASH_VERIFY_IN_TAG_HASH, &decoded_record)) {
+
+ *hash = decoded_record.value;
+ *hash_len = decoded_record.length;
+ }
+ else {
+ /* Default to a zero length data */
+ *hash_len = 0;
+ }
+ }
+
+ return rpc_status;
+}
+
+/* Operation: hash_clone */
+static rpc_status_t deserialize_hash_clone_req(const struct call_param_buf *req_buf,
+ uint32_t *source_op_handle)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+ struct ts_crypto_hash_clone_in recv_msg;
+ size_t expected_fixed_len = sizeof(struct ts_crypto_hash_clone_in);
+
+ if (expected_fixed_len <= req_buf->data_len) {
+
+ memcpy(&recv_msg, req_buf->data, expected_fixed_len);
+ *source_op_handle = recv_msg.source_op_handle;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
+static rpc_status_t serialize_hash_clone_resp(struct call_param_buf *resp_buf,
+ uint32_t target_op_handle)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+ struct ts_crypto_hash_clone_out resp_msg;
+ size_t fixed_len = sizeof(struct ts_crypto_hash_clone_out);
+
+ resp_msg.target_op_handle = target_op_handle;
+
+ if (fixed_len <= resp_buf->size) {
+
+ memcpy(resp_buf->data, &resp_msg, fixed_len);
+ resp_buf->data_len = fixed_len;
+ rpc_status = TS_RPC_CALL_ACCEPTED;
+ }
+
+ return rpc_status;
+}
+
/* Singleton method to provide access to the serializer instance */
const struct hash_provider_serializer *packedc_hash_provider_serializer_instance(void)
{
@@ -134,7 +226,11 @@ const struct hash_provider_serializer *packedc_hash_provider_serializer_instance
serialize_hash_setup_resp,
deserialize_hash_update_req,
deserialize_hash_finish_req,
- serialize_hash_finish_resp
+ serialize_hash_finish_resp,
+ deserialize_hash_abort_req,
+ deserialize_hash_verify_req,
+ deserialize_hash_clone_req,
+ serialize_hash_clone_resp
};
return &instance;
diff --git a/protocols/service/crypto/packed-c/hash.h b/protocols/service/crypto/packed-c/hash.h
index 13ae3b9dd..36ed3f64e 100644
--- a/protocols/service/crypto/packed-c/hash.h
+++ b/protocols/service/crypto/packed-c/hash.h
@@ -15,7 +15,7 @@
*/
-/********
+/****************************************
* hash_setup operation definition
*/
@@ -31,7 +31,7 @@ struct __attribute__ ((__packed__)) ts_crypto_hash_setup_out
uint32_t op_handle;
};
-/*********
+/****************************************
* hash_update operation definition
*/
@@ -47,7 +47,7 @@ enum
TS_CRYPTO_HASH_UPDATE_IN_TAG_DATA = 1
};
-/*********
+/****************************************
* hash_finish operation definition
*/
@@ -63,5 +63,46 @@ enum
TS_CRYPTO_HASH_FINISH_OUT_TAG_HASH = 1
};
+/****************************************
+ * hash_abort operation definition
+ */
+
+/* Mandatory fixed sized input parameters */
+struct __attribute__ ((__packed__)) ts_crypto_hash_abort_in
+{
+ uint32_t op_handle;
+};
+
+/****************************************
+ * hash_verify operation definition
+ */
+
+/* Mandatory fixed sized input parameters */
+struct __attribute__ ((__packed__)) ts_crypto_hash_verify_in
+{
+ uint32_t op_handle;
+};
+
+/* Variable length input parameter tags */
+enum
+{
+ TS_CRYPTO_HASH_VERIFY_IN_TAG_HASH = 1
+};
+
+/****************************************
+ * hash_clone operation definition
+ */
+
+/* Mandatory fixed sized input parameters */
+struct __attribute__ ((__packed__)) ts_crypto_hash_clone_in
+{
+ uint32_t source_op_handle;
+};
+
+/* Mandatory fixed sized output parameters */
+struct __attribute__ ((__packed__)) ts_crypto_hash_clone_out
+{
+ uint32_t target_op_handle;
+};
#endif /* TS_CRYPTO_HASH_H */
diff --git a/protocols/service/crypto/packed-c/opcodes.h b/protocols/service/crypto/packed-c/opcodes.h
index fa23175da..b0ccff33e 100644
--- a/protocols/service/crypto/packed-c/opcodes.h
+++ b/protocols/service/crypto/packed-c/opcodes.h
@@ -9,8 +9,10 @@
/* C/C++ definition of crypto service opcodes
*/
-#define TS_CRYPTO_OPCODE_BASE (0x0100)
+
+/* Base operations */
#define TS_CRYPTO_OPCODE_NOP (0x0000)
+#define TS_CRYPTO_OPCODE_BASE (0x0100)
#define TS_CRYPTO_OPCODE_GENERATE_KEY (TS_CRYPTO_OPCODE_BASE + 1)
#define TS_CRYPTO_OPCODE_DESTROY_KEY (TS_CRYPTO_OPCODE_BASE + 2)
#define TS_CRYPTO_OPCODE_EXPORT_KEY (TS_CRYPTO_OPCODE_BASE + 5)
@@ -21,11 +23,17 @@
#define TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT (TS_CRYPTO_OPCODE_BASE + 10)
#define TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT (TS_CRYPTO_OPCODE_BASE + 11)
#define TS_CRYPTO_OPCODE_GENERATE_RANDOM (TS_CRYPTO_OPCODE_BASE + 12)
-#define TS_CRYPTO_OPCODE_HASH_SETUP (TS_CRYPTO_OPCODE_BASE + 13)
-#define TS_CRYPTO_OPCODE_HASH_UPDATE (TS_CRYPTO_OPCODE_BASE + 14)
-#define TS_CRYPTO_OPCODE_HASH_FINISH (TS_CRYPTO_OPCODE_BASE + 15)
-#define TS_CRYPTO_OPCODE_COPY_KEY (TS_CRYPTO_OPCODE_BASE + 16)
-#define TS_CRYPTO_OPCODE_PURGE_KEY (TS_CRYPTO_OPCODE_BASE + 17)
-#define TS_CRYPTO_OPCODE_GET_KEY_ATTRIBUTES (TS_CRYPTO_OPCODE_BASE + 18)
+#define TS_CRYPTO_OPCODE_COPY_KEY (TS_CRYPTO_OPCODE_BASE + 13)
+#define TS_CRYPTO_OPCODE_PURGE_KEY (TS_CRYPTO_OPCODE_BASE + 14)
+#define TS_CRYPTO_OPCODE_GET_KEY_ATTRIBUTES (TS_CRYPTO_OPCODE_BASE + 15)
+
+/* Hash operations */
+#define TS_CRYPTO_OPCODE_HASH_BASE (0x0200)
+#define TS_CRYPTO_OPCODE_HASH_SETUP (TS_CRYPTO_OPCODE_HASH_BASE + 1)
+#define TS_CRYPTO_OPCODE_HASH_UPDATE (TS_CRYPTO_OPCODE_HASH_BASE + 2)
+#define TS_CRYPTO_OPCODE_HASH_FINISH (TS_CRYPTO_OPCODE_HASH_BASE + 3)
+#define TS_CRYPTO_OPCODE_HASH_ABORT (TS_CRYPTO_OPCODE_HASH_BASE + 4)
+#define TS_CRYPTO_OPCODE_HASH_VERIFY (TS_CRYPTO_OPCODE_HASH_BASE + 5)
+#define TS_CRYPTO_OPCODE_HASH_CLONE (TS_CRYPTO_OPCODE_HASH_BASE + 6)
#endif /* TS_CRYPTO_OPCODES_H */