psasim: add support for psa_{sign,verify}_hash_xxx() and get/set max ops
Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
diff --git a/tests/psa-client-server/psasim/src/psa_functions_codes.h b/tests/psa-client-server/psasim/src/psa_functions_codes.h
index 04401d1..68d9f03 100644
--- a/tests/psa-client-server/psasim/src/psa_functions_codes.h
+++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h
@@ -51,6 +51,8 @@
PSA_HASH_UPDATE,
PSA_HASH_VERIFY,
PSA_IMPORT_KEY,
+ PSA_INTERRUPTIBLE_GET_MAX_OPS,
+ PSA_INTERRUPTIBLE_SET_MAX_OPS,
PSA_KEY_DERIVATION_ABORT,
PSA_KEY_DERIVATION_GET_CAPACITY,
PSA_KEY_DERIVATION_INPUT_BYTES,
@@ -73,8 +75,16 @@
PSA_PURGE_KEY,
PSA_RAW_KEY_AGREEMENT,
PSA_SIGN_HASH,
+ PSA_SIGN_HASH_ABORT,
+ PSA_SIGN_HASH_COMPLETE,
+ PSA_SIGN_HASH_GET_NUM_OPS,
+ PSA_SIGN_HASH_START,
PSA_SIGN_MESSAGE,
PSA_VERIFY_HASH,
+ PSA_VERIFY_HASH_ABORT,
+ PSA_VERIFY_HASH_COMPLETE,
+ PSA_VERIFY_HASH_GET_NUM_OPS,
+ PSA_VERIFY_HASH_START,
PSA_VERIFY_MESSAGE,
};
diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c
index 67a66ff..36fdfdb 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c
@@ -3205,6 +3205,109 @@
}
+uint32_t psa_interruptible_get_max_ops(
+ void
+)
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+ uint32_t value = 0;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ 0;
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ value = 0;
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_INTERRUPTIBLE_GET_MAX_OPS,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_INTERRUPTIBLE_GET_MAX_OPS server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_uint32_t(&rpos, &rremain, &value);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return value;
+}
+
+
+void psa_interruptible_set_max_ops(
+ uint32_t max_ops
+ )
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ psasim_serialise_uint32_t_needs(max_ops);
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_uint32_t(&pos, &remaining, max_ops);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_INTERRUPTIBLE_SET_MAX_OPS,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_INTERRUPTIBLE_SET_MAX_OPS server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+}
+
+
psa_status_t psa_key_derivation_abort(
psa_key_derivation_operation_t *operation
)
@@ -4867,6 +4970,293 @@
}
+psa_status_t psa_sign_hash_abort(
+ psa_sign_hash_interruptible_operation_t *operation
+ )
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation);
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_sign_hash_interruptible_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_SIGN_HASH_ABORT,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_SIGN_HASH_ABORT server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_sign_hash_complete(
+ psa_sign_hash_interruptible_operation_t *operation,
+ uint8_t *signature, size_t signature_size,
+ size_t *signature_length
+ )
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation) +
+ psasim_serialise_buffer_needs(signature, signature_size) +
+ psasim_serialise_size_t_needs(*signature_length);
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_sign_hash_interruptible_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, signature, signature_size);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_size_t(&pos, &remaining, *signature_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_SIGN_HASH_COMPLETE,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_SIGN_HASH_COMPLETE server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_return_buffer(&rpos, &rremain, signature, signature_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&rpos, &rremain, signature_length);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+uint32_t psa_sign_hash_get_num_ops(
+ const psa_sign_hash_interruptible_operation_t *operation
+ )
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+ uint32_t value = 0;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation);
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ value = 0;
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_sign_hash_interruptible_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_SIGN_HASH_GET_NUM_OPS,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_SIGN_HASH_GET_NUM_OPS server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_uint32_t(&rpos, &rremain, &value);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return value;
+}
+
+
+psa_status_t psa_sign_hash_start(
+ psa_sign_hash_interruptible_operation_t *operation,
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg,
+ const uint8_t *hash, size_t hash_length
+ )
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation) +
+ psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+ psasim_serialise_psa_algorithm_t_needs(alg) +
+ psasim_serialise_buffer_needs(hash, hash_length);
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_sign_hash_interruptible_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_SIGN_HASH_START,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_SIGN_HASH_START server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
psa_status_t psa_sign_message(
mbedtls_svc_key_id_t key,
psa_algorithm_t alg,
@@ -5035,6 +5425,277 @@
}
+psa_status_t psa_verify_hash_abort(
+ psa_verify_hash_interruptible_operation_t *operation
+ )
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation);
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_verify_hash_interruptible_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_VERIFY_HASH_ABORT,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_VERIFY_HASH_ABORT server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_verify_hash_complete(
+ psa_verify_hash_interruptible_operation_t *operation
+ )
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation);
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_verify_hash_interruptible_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_VERIFY_HASH_COMPLETE,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_VERIFY_HASH_COMPLETE server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+uint32_t psa_verify_hash_get_num_ops(
+ const psa_verify_hash_interruptible_operation_t *operation
+ )
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+ uint32_t value = 0;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation);
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ value = 0;
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_verify_hash_interruptible_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_VERIFY_HASH_GET_NUM_OPS,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_VERIFY_HASH_GET_NUM_OPS server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_uint32_t(&rpos, &rremain, &value);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return value;
+}
+
+
+psa_status_t psa_verify_hash_start(
+ psa_verify_hash_interruptible_operation_t *operation,
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg,
+ const uint8_t *hash, size_t hash_length,
+ const uint8_t *signature, size_t signature_length
+ )
+{
+ uint8_t *ser_params = NULL;
+ uint8_t *ser_result = NULL;
+ size_t result_length;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+ size_t needed = psasim_serialise_begin_needs() +
+ psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation) +
+ psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+ psasim_serialise_psa_algorithm_t_needs(alg) +
+ psasim_serialise_buffer_needs(hash, hash_length) +
+ psasim_serialise_buffer_needs(signature, signature_length);
+
+ ser_params = malloc(needed);
+ if (ser_params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = ser_params;
+ size_t remaining = needed;
+ int ok;
+ ok = psasim_serialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_verify_hash_interruptible_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, signature, signature_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_VERIFY_HASH_START,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_VERIFY_HASH_START server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = ser_result;
+ size_t rremain = result_length;
+
+ ok = psasim_deserialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
psa_status_t psa_verify_message(
mbedtls_svc_key_id_t key,
psa_algorithm_t alg,
diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
index 41b4bc6..eb31376 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
@@ -3677,6 +3677,111 @@
}
// Returns 1 for success, 0 for failure
+int psa_interruptible_get_max_ops_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ uint32_t value = 0;
+
+ uint8_t *result = NULL;
+ int ok;
+
+ // Now we call the actual target function
+
+ value = psa_interruptible_get_max_ops(
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_uint32_t_needs(value);
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_uint32_t(&rpos, &rremain, value);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_interruptible_set_max_ops_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ uint32_t max_ops;
+
+ uint8_t *pos = in_params;
+ size_t remaining = in_params_len;
+ uint8_t *result = NULL;
+ int ok;
+
+ ok = psasim_deserialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_uint32_t(&pos, &remaining, &max_ops);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ psa_interruptible_set_max_ops(
+ max_ops
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs();
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
int psa_key_derivation_abort_wrapper(
uint8_t *in_params, size_t in_params_len,
uint8_t **out_params, size_t *out_params_len)
@@ -5585,6 +5690,333 @@
}
// Returns 1 for success, 0 for failure
+int psa_sign_hash_abort_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_sign_hash_interruptible_operation_t *operation;
+
+ uint8_t *pos = in_params;
+ size_t remaining = in_params_len;
+ uint8_t *result = NULL;
+ int ok;
+
+ ok = psasim_deserialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_sign_hash_abort(
+ operation
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_psa_status_t_needs(status) +
+ psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation);
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_sign_hash_complete_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_sign_hash_interruptible_operation_t *operation;
+ uint8_t *signature = NULL;
+ size_t signature_size;
+ size_t signature_length;
+
+ uint8_t *pos = in_params;
+ size_t remaining = in_params_len;
+ uint8_t *result = NULL;
+ int ok;
+
+ ok = psasim_deserialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &signature, &signature_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &signature_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_sign_hash_complete(
+ operation,
+ signature, signature_size,
+ &signature_length
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_psa_status_t_needs(status) +
+ psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation) +
+ psasim_serialise_buffer_needs(signature, signature_size) +
+ psasim_serialise_size_t_needs(signature_length);
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_buffer(&rpos, &rremain, signature, signature_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_size_t(&rpos, &rremain, signature_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(signature);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(signature);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_sign_hash_get_num_ops_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ uint32_t value = 0;
+ psa_sign_hash_interruptible_operation_t *operation;
+
+ uint8_t *pos = in_params;
+ size_t remaining = in_params_len;
+ uint8_t *result = NULL;
+ int ok;
+
+ ok = psasim_deserialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ value = psa_sign_hash_get_num_ops(
+ operation
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_uint32_t_needs(value);
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_uint32_t(&rpos, &rremain, value);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_sign_hash_start_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_sign_hash_interruptible_operation_t *operation;
+ mbedtls_svc_key_id_t key;
+ psa_algorithm_t alg;
+ uint8_t *hash = NULL;
+ size_t hash_length;
+
+ uint8_t *pos = in_params;
+ size_t remaining = in_params_len;
+ uint8_t *result = NULL;
+ int ok;
+
+ ok = psasim_deserialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_sign_hash_start(
+ operation,
+ key,
+ alg,
+ hash, hash_length
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_psa_status_t_needs(status) +
+ psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation);
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(hash);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(hash);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
int psa_sign_message_wrapper(
uint8_t *in_params, size_t in_params_len,
uint8_t **out_params, size_t *out_params_len)
@@ -5788,6 +6220,312 @@
}
// Returns 1 for success, 0 for failure
+int psa_verify_hash_abort_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_verify_hash_interruptible_operation_t *operation;
+
+ uint8_t *pos = in_params;
+ size_t remaining = in_params_len;
+ uint8_t *result = NULL;
+ int ok;
+
+ ok = psasim_deserialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_verify_hash_abort(
+ operation
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_psa_status_t_needs(status) +
+ psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation);
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_verify_hash_complete_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_verify_hash_interruptible_operation_t *operation;
+
+ uint8_t *pos = in_params;
+ size_t remaining = in_params_len;
+ uint8_t *result = NULL;
+ int ok;
+
+ ok = psasim_deserialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_verify_hash_complete(
+ operation
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_psa_status_t_needs(status) +
+ psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation);
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_verify_hash_get_num_ops_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ uint32_t value = 0;
+ psa_verify_hash_interruptible_operation_t *operation;
+
+ uint8_t *pos = in_params;
+ size_t remaining = in_params_len;
+ uint8_t *result = NULL;
+ int ok;
+
+ ok = psasim_deserialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ value = psa_verify_hash_get_num_ops(
+ operation
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_uint32_t_needs(value);
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_uint32_t(&rpos, &rremain, value);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_verify_hash_start_wrapper(
+ uint8_t *in_params, size_t in_params_len,
+ uint8_t **out_params, size_t *out_params_len)
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_verify_hash_interruptible_operation_t *operation;
+ mbedtls_svc_key_id_t key;
+ psa_algorithm_t alg;
+ uint8_t *hash = NULL;
+ size_t hash_length;
+ uint8_t *signature = NULL;
+ size_t signature_length;
+
+ uint8_t *pos = in_params;
+ size_t remaining = in_params_len;
+ uint8_t *result = NULL;
+ int ok;
+
+ ok = psasim_deserialise_begin(&pos, &remaining);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &signature, &signature_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_verify_hash_start(
+ operation,
+ key,
+ alg,
+ hash, hash_length,
+ signature, signature_length
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_psa_status_t_needs(status) +
+ psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation);
+
+ result = malloc(result_size);
+ if (result == NULL) {
+ goto fail;
+ }
+
+ uint8_t *rpos = result;
+ size_t rremain = result_size;
+
+ ok = psasim_serialise_begin(&rpos, &rremain);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(hash);
+ free(signature);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(hash);
+ free(signature);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
int psa_verify_message_wrapper(
uint8_t *in_params, size_t in_params_len,
uint8_t **out_params, size_t *out_params_len)
@@ -6075,6 +6813,14 @@
ok = psa_import_key_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
+ case PSA_INTERRUPTIBLE_GET_MAX_OPS:
+ ok = psa_interruptible_get_max_ops_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_INTERRUPTIBLE_SET_MAX_OPS:
+ ok = psa_interruptible_set_max_ops_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
case PSA_KEY_DERIVATION_ABORT:
ok = psa_key_derivation_abort_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
@@ -6163,6 +6909,22 @@
ok = psa_sign_hash_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
+ case PSA_SIGN_HASH_ABORT:
+ ok = psa_sign_hash_abort_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_SIGN_HASH_COMPLETE:
+ ok = psa_sign_hash_complete_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_SIGN_HASH_GET_NUM_OPS:
+ ok = psa_sign_hash_get_num_ops_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_SIGN_HASH_START:
+ ok = psa_sign_hash_start_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
case PSA_SIGN_MESSAGE:
ok = psa_sign_message_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
@@ -6171,6 +6933,22 @@
ok = psa_verify_hash_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
+ case PSA_VERIFY_HASH_ABORT:
+ ok = psa_verify_hash_abort_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_VERIFY_HASH_COMPLETE:
+ ok = psa_verify_hash_complete_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_VERIFY_HASH_GET_NUM_OPS:
+ ok = psa_verify_hash_get_num_ops_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_VERIFY_HASH_START:
+ ok = psa_verify_hash_start_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
case PSA_VERIFY_MESSAGE:
ok = psa_verify_message_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
diff --git a/tests/psa-client-server/psasim/src/psa_sim_generate.pl b/tests/psa-client-server/psasim/src/psa_sim_generate.pl
index dfbced1..344ad25 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl
@@ -4872,3 +4872,555 @@
uint8_t *data,
size_t data_size,
size_t *data_length);
+
+/**
+ * \brief Set the maximum number of ops allowed to be
+ * executed by an interruptible function in a
+ * single call.
+ *
+ * \warning This is a beta API, and thus subject to change
+ * at any point. It is not bound by the usual
+ * interface stability promises.
+ *
+ * \note The time taken to execute a single op is
+ * implementation specific and depends on
+ * software, hardware, the algorithm, key type and
+ * curve chosen. Even within a single operation,
+ * successive ops can take differing amounts of
+ * time. The only guarantee is that lower values
+ * for \p max_ops means functions will block for a
+ * lesser maximum amount of time. The functions
+ * \c psa_sign_interruptible_get_num_ops() and
+ * \c psa_verify_interruptible_get_num_ops() are
+ * provided to help with tuning this value.
+ *
+ * \note This value defaults to
+ * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, which
+ * means the whole operation will be done in one
+ * go, regardless of the number of ops required.
+ *
+ * \note If more ops are needed to complete a
+ * computation, #PSA_OPERATION_INCOMPLETE will be
+ * returned by the function performing the
+ * computation. It is then the caller's
+ * responsibility to either call again with the
+ * same operation context until it returns 0 or an
+ * error code; or to call the relevant abort
+ * function if the answer is no longer required.
+ *
+ * \note The interpretation of \p max_ops is also
+ * implementation defined. On a hard real time
+ * system, this can indicate a hard deadline, as a
+ * real-time system needs a guarantee of not
+ * spending more than X time, however care must be
+ * taken in such an implementation to avoid the
+ * situation whereby calls just return, not being
+ * able to do any actual work within the allotted
+ * time. On a non-real-time system, the
+ * implementation can be more relaxed, but again
+ * whether this number should be interpreted as as
+ * hard or soft limit or even whether a less than
+ * or equals as regards to ops executed in a
+ * single call is implementation defined.
+ *
+ * \note For keys in local storage when no accelerator
+ * driver applies, please see also the
+ * documentation for \c mbedtls_ecp_set_max_ops(),
+ * which is the internal implementation in these
+ * cases.
+ *
+ * \warning With implementations that interpret this number
+ * as a hard limit, setting this number too small
+ * may result in an infinite loop, whereby each
+ * call results in immediate return with no ops
+ * done (as there is not enough time to execute
+ * any), and thus no result will ever be achieved.
+ *
+ * \note This only applies to functions whose
+ * documentation mentions they may return
+ * #PSA_OPERATION_INCOMPLETE.
+ *
+ * \param max_ops The maximum number of ops to be executed in a
+ * single call. This can be a number from 0 to
+ * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0
+ * is the least amount of work done per call.
+ */
+void psa_interruptible_set_max_ops(uint32_t max_ops);
+
+/**
+ * \brief Get the maximum number of ops allowed to be
+ * executed by an interruptible function in a
+ * single call. This will return the last
+ * value set by
+ * \c psa_interruptible_set_max_ops() or
+ * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED if
+ * that function has never been called.
+ *
+ * \warning This is a beta API, and thus subject to change
+ * at any point. It is not bound by the usual
+ * interface stability promises.
+ *
+ * \return Maximum number of ops allowed to be
+ * executed by an interruptible function in a
+ * single call.
+ */
+uint32_t psa_interruptible_get_max_ops(void);
+
+/**
+ * \brief Get the number of ops that a hash signing
+ * operation has taken so far. If the operation
+ * has completed, then this will represent the
+ * number of ops required for the entire
+ * operation. After initialization or calling
+ * \c psa_sign_hash_interruptible_abort() on
+ * the operation, a value of 0 will be returned.
+ *
+ * \note This interface is guaranteed re-entrant and
+ * thus may be called from driver code.
+ *
+ * \warning This is a beta API, and thus subject to change
+ * at any point. It is not bound by the usual
+ * interface stability promises.
+ *
+ * This is a helper provided to help you tune the
+ * value passed to \c
+ * psa_interruptible_set_max_ops().
+ *
+ * \param operation The \c psa_sign_hash_interruptible_operation_t
+ * to use. This must be initialized first.
+ *
+ * \return Number of ops that the operation has taken so
+ * far.
+ */
+uint32_t psa_sign_hash_get_num_ops(
+ const psa_sign_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief Get the number of ops that a hash verification
+ * operation has taken so far. If the operation
+ * has completed, then this will represent the
+ * number of ops required for the entire
+ * operation. After initialization or calling \c
+ * psa_verify_hash_interruptible_abort() on the
+ * operation, a value of 0 will be returned.
+ *
+ * \warning This is a beta API, and thus subject to change
+ * at any point. It is not bound by the usual
+ * interface stability promises.
+ *
+ * This is a helper provided to help you tune the
+ * value passed to \c
+ * psa_interruptible_set_max_ops().
+ *
+ * \param operation The \c
+ * psa_verify_hash_interruptible_operation_t to
+ * use. This must be initialized first.
+ *
+ * \return Number of ops that the operation has taken so
+ * far.
+ */
+uint32_t psa_verify_hash_get_num_ops(
+ const psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief Start signing a hash or short message with a
+ * private key, in an interruptible manner.
+ *
+ * \see \c psa_sign_hash_complete()
+ *
+ * \warning This is a beta API, and thus subject to change
+ * at any point. It is not bound by the usual
+ * interface stability promises.
+ *
+ * \note This function combined with \c
+ * psa_sign_hash_complete() is equivalent to
+ * \c psa_sign_hash() but
+ * \c psa_sign_hash_complete() can return early and
+ * resume according to the limit set with \c
+ * psa_interruptible_set_max_ops() to reduce the
+ * maximum time spent in a function call.
+ *
+ * \note Users should call \c psa_sign_hash_complete()
+ * repeatedly on the same context after a
+ * successful call to this function until \c
+ * psa_sign_hash_complete() either returns 0 or an
+ * error. \c psa_sign_hash_complete() will return
+ * #PSA_OPERATION_INCOMPLETE if there is more work
+ * to do. Alternatively users can call
+ * \c psa_sign_hash_abort() at any point if they no
+ * longer want the result.
+ *
+ * \note If this function returns an error status, the
+ * operation enters an error state and must be
+ * aborted by calling \c psa_sign_hash_abort().
+ *
+ * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t
+ * to use. This must be initialized first.
+ *
+ * \param key Identifier of the key to use for the operation.
+ * It must be an asymmetric key pair. The key must
+ * allow the usage #PSA_KEY_USAGE_SIGN_HASH.
+ * \param alg A signature algorithm (\c PSA_ALG_XXX
+ * value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ * is true), that is compatible with
+ * the type of \p key.
+ * \param[in] hash The hash or message to sign.
+ * \param hash_length Size of the \p hash buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * The operation started successfully - call \c psa_sign_hash_complete()
+ * with the same context to complete the operation
+ *
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The key does not have the #PSA_KEY_USAGE_SIGN_HASH flag, or it does
+ * not permit the requested algorithm.
+ * \retval #PSA_ERROR_BAD_STATE
+ * An operation has previously been started on this context, and is
+ * still in progress.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The library has not been previously initialized by psa_crypto_init().
+ * It is implementation-dependent whether a failure to initialize
+ * results in this error code.
+ */
+psa_status_t psa_sign_hash_start(
+ psa_sign_hash_interruptible_operation_t *operation,
+ mbedtls_svc_key_id_t key, psa_algorithm_t alg,
+ const uint8_t *hash, size_t hash_length);
+
+/**
+ * \brief Continue and eventually complete the action of
+ * signing a hash or short message with a private
+ * key, in an interruptible manner.
+ *
+ * \see \c psa_sign_hash_start()
+ *
+ * \warning This is a beta API, and thus subject to change
+ * at any point. It is not bound by the usual
+ * interface stability promises.
+ *
+ * \note This function combined with \c
+ * psa_sign_hash_start() is equivalent to
+ * \c psa_sign_hash() but this function can return
+ * early and resume according to the limit set with
+ * \c psa_interruptible_set_max_ops() to reduce the
+ * maximum time spent in a function call.
+ *
+ * \note Users should call this function on the same
+ * operation object repeatedly until it either
+ * returns 0 or an error. This function will return
+ * #PSA_OPERATION_INCOMPLETE if there is more work
+ * to do. Alternatively users can call
+ * \c psa_sign_hash_abort() at any point if they no
+ * longer want the result.
+ *
+ * \note When this function returns successfully, the
+ * operation becomes inactive. If this function
+ * returns an error status, the operation enters an
+ * error state and must be aborted by calling
+ * \c psa_sign_hash_abort().
+ *
+ * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t
+ * to use. This must be initialized first, and have
+ * had \c psa_sign_hash_start() called with it
+ * first.
+ *
+ * \param[out] signature Buffer where the signature is to be written.
+ * \param signature_size Size of the \p signature buffer in bytes. This
+ * must be appropriate for the selected
+ * algorithm and key:
+ * - The required signature size is
+ * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c
+ * key_bits, \c alg) where \c key_type and \c
+ * key_bits are the type and bit-size
+ * respectively of key.
+ * - #PSA_SIGNATURE_MAX_SIZE evaluates to the
+ * maximum signature size of any supported
+ * signature algorithm.
+ * \param[out] signature_length On success, the number of bytes that make up
+ * the returned signature value.
+ *
+ * \retval #PSA_SUCCESS
+ * Operation completed successfully
+ *
+ * \retval #PSA_OPERATION_INCOMPLETE
+ * Operation was interrupted due to the setting of \c
+ * psa_interruptible_set_max_ops(). There is still work to be done.
+ * Call this function again with the same operation object.
+ *
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p signature buffer is too small. You can
+ * determine a sufficient buffer size by calling
+ * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \c alg)
+ * where \c key_type and \c key_bits are the type and bit-size
+ * respectively of \c key.
+ *
+ * \retval #PSA_ERROR_BAD_STATE
+ * An operation was not previously started on this context via
+ * \c psa_sign_hash_start().
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The library has either not been previously initialized by
+ * psa_crypto_init() or you did not previously call
+ * psa_sign_hash_start() with this operation object. It is
+ * implementation-dependent whether a failure to initialize results in
+ * this error code.
+ */
+psa_status_t psa_sign_hash_complete(
+ psa_sign_hash_interruptible_operation_t *operation,
+ uint8_t *signature, size_t signature_size,
+ size_t *signature_length);
+
+/**
+ * \brief Abort a sign hash operation.
+ *
+ * \warning This is a beta API, and thus subject to change
+ * at any point. It is not bound by the usual
+ * interface stability promises.
+ *
+ * \note This function is the only function that clears
+ * the number of ops completed as part of the
+ * operation. Please ensure you copy this value via
+ * \c psa_sign_hash_get_num_ops() if required
+ * before calling.
+ *
+ * \note Aborting an operation frees all associated
+ * resources except for the \p operation structure
+ * itself. Once aborted, the operation object can
+ * be reused for another operation by calling \c
+ * psa_sign_hash_start() again.
+ *
+ * \note You may call this function any time after the
+ * operation object has been initialized. In
+ * particular, calling \c psa_sign_hash_abort()
+ * after the operation has already been terminated
+ * by a call to \c psa_sign_hash_abort() or
+ * psa_sign_hash_complete() is safe.
+ *
+ * \param[in,out] operation Initialized sign hash operation.
+ *
+ * \retval #PSA_SUCCESS
+ * The operation was aborted successfully.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The library has not been previously initialized by psa_crypto_init().
+ * It is implementation-dependent whether a failure to initialize
+ * results in this error code.
+ */
+psa_status_t psa_sign_hash_abort(
+ psa_sign_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief Start reading and verifying a hash or short
+ * message, in an interruptible manner.
+ *
+ * \see \c psa_verify_hash_complete()
+ *
+ * \warning This is a beta API, and thus subject to change
+ * at any point. It is not bound by the usual
+ * interface stability promises.
+ *
+ * \note This function combined with \c
+ * psa_verify_hash_complete() is equivalent to
+ * \c psa_verify_hash() but \c
+ * psa_verify_hash_complete() can return early and
+ * resume according to the limit set with \c
+ * psa_interruptible_set_max_ops() to reduce the
+ * maximum time spent in a function.
+ *
+ * \note Users should call \c psa_verify_hash_complete()
+ * repeatedly on the same operation object after a
+ * successful call to this function until \c
+ * psa_verify_hash_complete() either returns 0 or
+ * an error. \c psa_verify_hash_complete() will
+ * return #PSA_OPERATION_INCOMPLETE if there is
+ * more work to do. Alternatively users can call
+ * \c psa_verify_hash_abort() at any point if they
+ * no longer want the result.
+ *
+ * \note If this function returns an error status, the
+ * operation enters an error state and must be
+ * aborted by calling \c psa_verify_hash_abort().
+ *
+ * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t
+ * to use. This must be initialized first.
+ *
+ * \param key Identifier of the key to use for the operation.
+ * The key must allow the usage
+ * #PSA_KEY_USAGE_VERIFY_HASH.
+ * \param alg A signature algorithm (\c PSA_ALG_XXX
+ * value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ * is true), that is compatible with
+ * the type of \p key.
+ * \param[in] hash The hash whose signature is to be verified.
+ * \param hash_length Size of the \p hash buffer in bytes.
+ * \param[in] signature Buffer containing the signature to verify.
+ * \param signature_length Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * The operation started successfully - please call \c
+ * psa_verify_hash_complete() with the same context to complete the
+ * operation.
+ *
+ * \retval #PSA_ERROR_BAD_STATE
+ * Another operation has already been started on this context, and is
+ * still in progress.
+ *
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The key does not have the #PSA_KEY_USAGE_VERIFY_HASH flag, or it does
+ * not permit the requested algorithm.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The library has not been previously initialized by psa_crypto_init().
+ * It is implementation-dependent whether a failure to initialize
+ * results in this error code.
+ */
+psa_status_t psa_verify_hash_start(
+ psa_verify_hash_interruptible_operation_t *operation,
+ mbedtls_svc_key_id_t key, psa_algorithm_t alg,
+ const uint8_t *hash, size_t hash_length,
+ const uint8_t *signature, size_t signature_length);
+
+/**
+ * \brief Continue and eventually complete the action of
+ * reading and verifying a hash or short message
+ * signed with a private key, in an interruptible
+ * manner.
+ *
+ * \see \c psa_verify_hash_start()
+ *
+ * \warning This is a beta API, and thus subject to change
+ * at any point. It is not bound by the usual
+ * interface stability promises.
+ *
+ * \note This function combined with \c
+ * psa_verify_hash_start() is equivalent to
+ * \c psa_verify_hash() but this function can
+ * return early and resume according to the limit
+ * set with \c psa_interruptible_set_max_ops() to
+ * reduce the maximum time spent in a function
+ * call.
+ *
+ * \note Users should call this function on the same
+ * operation object repeatedly until it either
+ * returns 0 or an error. This function will return
+ * #PSA_OPERATION_INCOMPLETE if there is more work
+ * to do. Alternatively users can call
+ * \c psa_verify_hash_abort() at any point if they
+ * no longer want the result.
+ *
+ * \note When this function returns successfully, the
+ * operation becomes inactive. If this function
+ * returns an error status, the operation enters an
+ * error state and must be aborted by calling
+ * \c psa_verify_hash_abort().
+ *
+ * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t
+ * to use. This must be initialized first, and have
+ * had \c psa_verify_hash_start() called with it
+ * first.
+ *
+ * \retval #PSA_SUCCESS
+ * Operation completed successfully, and the passed signature is valid.
+ *
+ * \retval #PSA_OPERATION_INCOMPLETE
+ * Operation was interrupted due to the setting of \c
+ * psa_interruptible_set_max_ops(). There is still work to be done.
+ * Call this function again with the same operation object.
+ *
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ * The calculation was performed successfully, but the passed
+ * signature is not a valid signature.
+ * \retval #PSA_ERROR_BAD_STATE
+ * An operation was not previously started on this context via
+ * \c psa_verify_hash_start().
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The library has either not been previously initialized by
+ * psa_crypto_init() or you did not previously call
+ * psa_verify_hash_start() on this object. It is
+ * implementation-dependent whether a failure to initialize results in
+ * this error code.
+ */
+psa_status_t psa_verify_hash_complete(
+ psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief Abort a verify hash operation.
+ *
+ * \warning This is a beta API, and thus subject to change at
+ * any point. It is not bound by the usual interface
+ * stability promises.
+ *
+ * \note This function is the only function that clears the
+ * number of ops completed as part of the operation.
+ * Please ensure you copy this value via
+ * \c psa_verify_hash_get_num_ops() if required
+ * before calling.
+ *
+ * \note Aborting an operation frees all associated
+ * resources except for the operation structure
+ * itself. Once aborted, the operation object can be
+ * reused for another operation by calling \c
+ * psa_verify_hash_start() again.
+ *
+ * \note You may call this function any time after the
+ * operation object has been initialized.
+ * In particular, calling \c psa_verify_hash_abort()
+ * after the operation has already been terminated by
+ * a call to \c psa_verify_hash_abort() or
+ * psa_verify_hash_complete() is safe.
+ *
+ * \param[in,out] operation Initialized verify hash operation.
+ *
+ * \retval #PSA_SUCCESS
+ * The operation was aborted successfully.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The library has not been previously initialized by psa_crypto_init().
+ * It is implementation-dependent whether a failure to initialize
+ * results in this error code.
+ */
+psa_status_t psa_verify_hash_abort(
+ psa_verify_hash_interruptible_operation_t *operation);
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.c b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
index 4de7802..84e2339 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
@@ -253,6 +253,82 @@
return -1; /* not found */
}
+static psa_sign_hash_interruptible_operation_t sign_hash_interruptible_operations[MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t sign_hash_interruptible_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t next_sign_hash_interruptible_operation_handle = 1;
+
+/* Get a free slot */
+static ssize_t allocate_sign_hash_interruptible_operation_slot(void)
+{
+ psasim_client_handle_t handle = next_sign_hash_interruptible_operation_handle++;
+ if (next_sign_hash_interruptible_operation_handle == 0) { /* wrapped around */
+ FATAL("Sign_hash_interruptible operation handle wrapped");
+ }
+
+ for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+ if (sign_hash_interruptible_operation_handles[i] == 0) {
+ sign_hash_interruptible_operation_handles[i] = handle;
+ return i;
+ }
+ }
+
+ ERROR("All slots are currently used. Unable to allocate a new one.");
+
+ return -1; /* all in use */
+}
+
+/* Find the slot given the handle */
+static ssize_t find_sign_hash_interruptible_slot_by_handle(psasim_client_handle_t handle)
+{
+ for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+ if (sign_hash_interruptible_operation_handles[i] == handle) {
+ return i;
+ }
+ }
+
+ ERROR("Unable to find slot by handle %u", handle);
+
+ return -1; /* not found */
+}
+
+static psa_verify_hash_interruptible_operation_t verify_hash_interruptible_operations[MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t verify_hash_interruptible_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t next_verify_hash_interruptible_operation_handle = 1;
+
+/* Get a free slot */
+static ssize_t allocate_verify_hash_interruptible_operation_slot(void)
+{
+ psasim_client_handle_t handle = next_verify_hash_interruptible_operation_handle++;
+ if (next_verify_hash_interruptible_operation_handle == 0) { /* wrapped around */
+ FATAL("Verify_hash_interruptible operation handle wrapped");
+ }
+
+ for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+ if (verify_hash_interruptible_operation_handles[i] == 0) {
+ verify_hash_interruptible_operation_handles[i] = handle;
+ return i;
+ }
+ }
+
+ ERROR("All slots are currently used. Unable to allocate a new one.");
+
+ return -1; /* all in use */
+}
+
+/* Find the slot given the handle */
+static ssize_t find_verify_hash_interruptible_slot_by_handle(psasim_client_handle_t handle)
+{
+ for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+ if (verify_hash_interruptible_operation_handles[i] == handle) {
+ return i;
+ }
+ }
+
+ ERROR("Unable to find slot by handle %u", handle);
+
+ return -1; /* not found */
+}
+
size_t psasim_serialise_begin_needs(void)
{
/* The serialisation buffer will
@@ -467,6 +543,41 @@
return 1;
}
+size_t psasim_serialise_uint32_t_needs(uint32_t value)
+{
+ return sizeof(value);
+}
+
+int psasim_serialise_uint32_t(uint8_t **pos,
+ size_t *remaining,
+ uint32_t value)
+{
+ if (*remaining < sizeof(value)) {
+ return 0;
+ }
+
+ memcpy(*pos, &value, sizeof(value));
+ *pos += sizeof(value);
+
+ return 1;
+}
+
+int psasim_deserialise_uint32_t(uint8_t **pos,
+ size_t *remaining,
+ uint32_t *value)
+{
+ if (*remaining < sizeof(*value)) {
+ return 0;
+ }
+
+ memcpy(value, *pos, sizeof(*value));
+
+ *pos += sizeof(*value);
+ *remaining -= sizeof(*value);
+
+ return 1;
+}
+
size_t psasim_serialise_uint64_t_needs(uint64_t value)
{
return sizeof(value);
@@ -1255,6 +1366,192 @@
return 1;
}
+size_t psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(psa_sign_hash_interruptible_operation_t value)
+{
+ return sizeof(value);
+}
+
+int psasim_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_sign_hash_interruptible_operation_t value)
+{
+ if (*remaining < sizeof(value)) {
+ return 0;
+ }
+
+ memcpy(*pos, &value, sizeof(value));
+ *pos += sizeof(value);
+
+ return 1;
+}
+
+int psasim_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_sign_hash_interruptible_operation_t *value)
+{
+ if (*remaining < sizeof(*value)) {
+ return 0;
+ }
+
+ memcpy(value, *pos, sizeof(*value));
+
+ *pos += sizeof(*value);
+ *remaining -= sizeof(*value);
+
+ return 1;
+}
+
+size_t psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(psa_sign_hash_interruptible_operation_t *operation)
+{
+ (void) operation;
+
+ /* We will actually return a handle */
+ return sizeof(psasim_operation_t);
+}
+
+int psasim_server_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_sign_hash_interruptible_operation_t *operation)
+{
+ psasim_operation_t client_operation;
+
+ if (*remaining < sizeof(client_operation)) {
+ return 0;
+ }
+
+ ssize_t slot = operation - sign_hash_interruptible_operations;
+
+ client_operation.handle = sign_hash_interruptible_operation_handles[slot];
+
+ memcpy(*pos, &client_operation, sizeof(client_operation));
+ *pos += sizeof(client_operation);
+
+ return 1;
+}
+
+int psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_sign_hash_interruptible_operation_t **operation)
+{
+ psasim_operation_t client_operation;
+
+ if (*remaining < sizeof(psasim_operation_t)) {
+ return 0;
+ }
+
+ memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
+ *pos += sizeof(psasim_operation_t);
+ *remaining -= sizeof(psasim_operation_t);
+
+ ssize_t slot;
+ if (client_operation.handle == 0) { /* We need a new handle */
+ slot = allocate_sign_hash_interruptible_operation_slot();
+ } else {
+ slot = find_sign_hash_interruptible_slot_by_handle(client_operation.handle);
+ }
+
+ if (slot < 0) {
+ return 0;
+ }
+
+ *operation = &sign_hash_interruptible_operations[slot];
+
+ return 1;
+}
+
+size_t psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(psa_verify_hash_interruptible_operation_t value)
+{
+ return sizeof(value);
+}
+
+int psasim_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_verify_hash_interruptible_operation_t value)
+{
+ if (*remaining < sizeof(value)) {
+ return 0;
+ }
+
+ memcpy(*pos, &value, sizeof(value));
+ *pos += sizeof(value);
+
+ return 1;
+}
+
+int psasim_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_verify_hash_interruptible_operation_t *value)
+{
+ if (*remaining < sizeof(*value)) {
+ return 0;
+ }
+
+ memcpy(value, *pos, sizeof(*value));
+
+ *pos += sizeof(*value);
+ *remaining -= sizeof(*value);
+
+ return 1;
+}
+
+size_t psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(psa_verify_hash_interruptible_operation_t *operation)
+{
+ (void) operation;
+
+ /* We will actually return a handle */
+ return sizeof(psasim_operation_t);
+}
+
+int psasim_server_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_verify_hash_interruptible_operation_t *operation)
+{
+ psasim_operation_t client_operation;
+
+ if (*remaining < sizeof(client_operation)) {
+ return 0;
+ }
+
+ ssize_t slot = operation - verify_hash_interruptible_operations;
+
+ client_operation.handle = verify_hash_interruptible_operation_handles[slot];
+
+ memcpy(*pos, &client_operation, sizeof(client_operation));
+ *pos += sizeof(client_operation);
+
+ return 1;
+}
+
+int psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_verify_hash_interruptible_operation_t **operation)
+{
+ psasim_operation_t client_operation;
+
+ if (*remaining < sizeof(psasim_operation_t)) {
+ return 0;
+ }
+
+ memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
+ *pos += sizeof(psasim_operation_t);
+ *remaining -= sizeof(psasim_operation_t);
+
+ ssize_t slot;
+ if (client_operation.handle == 0) { /* We need a new handle */
+ slot = allocate_verify_hash_interruptible_operation_slot();
+ } else {
+ slot = find_verify_hash_interruptible_slot_by_handle(client_operation.handle);
+ }
+
+ if (slot < 0) {
+ return 0;
+ }
+
+ *operation = &verify_hash_interruptible_operations[slot];
+
+ return 1;
+}
+
size_t psasim_serialise_mbedtls_svc_key_id_t_needs(mbedtls_svc_key_id_t value)
{
return sizeof(value);
@@ -1302,4 +1599,8 @@
memset(cipher_operations, 0, sizeof(cipher_operations));
memset(key_derivation_operation_handles, 0, sizeof(key_derivation_operation_handles));
memset(key_derivation_operations, 0, sizeof(key_derivation_operations));
+ memset(sign_hash_interruptible_operation_handles, 0, sizeof(sign_hash_interruptible_operation_handles));
+ memset(sign_hash_interruptible_operations, 0, sizeof(sign_hash_interruptible_operations));
+ memset(verify_hash_interruptible_operation_handles, 0, sizeof(verify_hash_interruptible_operation_handles));
+ memset(verify_hash_interruptible_operations, 0, sizeof(verify_hash_interruptible_operations));
}
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.h b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
index 1028518..4bd7fe9 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
@@ -264,6 +264,48 @@
size_t *remaining,
uint16_t *value);
+/** Return how much buffer space is needed by \c psasim_serialise_uint32_t()
+ * to serialise an `uint32_t`.
+ *
+ * \param value The value that will be serialised into the buffer
+ * (needed in case some serialisations are value-
+ * dependent).
+ *
+ * \return The number of bytes needed in the buffer by
+ * \c psasim_serialise_uint32_t() to serialise
+ * the given value.
+ */
+size_t psasim_serialise_uint32_t_needs(uint32_t value);
+
+/** Serialise an `uint32_t` into a buffer.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value The value to serialise into the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_uint32_t(uint8_t **pos,
+ size_t *remaining,
+ uint32_t value);
+
+/** Deserialise an `uint32_t` from a buffer.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value Pointer to an `uint32_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_uint32_t(uint8_t **pos,
+ size_t *remaining,
+ uint32_t *value);
+
/** Return how much buffer space is needed by \c psasim_serialise_uint64_t()
* to serialise an `uint64_t`.
*
@@ -1011,6 +1053,174 @@
size_t *remaining,
psa_key_derivation_operation_t **value);
+/** Return how much buffer space is needed by \c psasim_serialise_psa_sign_hash_interruptible_operation_t()
+ * to serialise a `psa_sign_hash_interruptible_operation_t`.
+ *
+ * \param value The value that will be serialised into the buffer
+ * (needed in case some serialisations are value-
+ * dependent).
+ *
+ * \return The number of bytes needed in the buffer by
+ * \c psasim_serialise_psa_sign_hash_interruptible_operation_t() to serialise
+ * the given value.
+ */
+size_t psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(psa_sign_hash_interruptible_operation_t value);
+
+/** Serialise a `psa_sign_hash_interruptible_operation_t` into a buffer.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value The value to serialise into the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_sign_hash_interruptible_operation_t value);
+
+/** Deserialise a `psa_sign_hash_interruptible_operation_t` from a buffer.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value Pointer to a `psa_sign_hash_interruptible_operation_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_sign_hash_interruptible_operation_t *value);
+
+/** Return how much buffer space is needed by \c psasim_server_serialise_psa_sign_hash_interruptible_operation_t()
+ * to serialise a `psa_sign_hash_interruptible_operation_t`.
+ *
+ * \param value The value that will be serialised into the buffer
+ * (needed in case some serialisations are value-
+ * dependent).
+ *
+ * \return The number of bytes needed in the buffer by
+ * \c psasim_serialise_psa_sign_hash_interruptible_operation_t() to serialise
+ * the given value.
+ */
+size_t psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(psa_sign_hash_interruptible_operation_t *value);
+
+/** Serialise a `psa_sign_hash_interruptible_operation_t` into a buffer on the server side.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value The value to serialise into the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_server_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_sign_hash_interruptible_operation_t *value);
+
+/** Deserialise a `psa_sign_hash_interruptible_operation_t` from a buffer on the server side.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value Pointer to a `psa_sign_hash_interruptible_operation_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_sign_hash_interruptible_operation_t **value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_psa_verify_hash_interruptible_operation_t()
+ * to serialise a `psa_verify_hash_interruptible_operation_t`.
+ *
+ * \param value The value that will be serialised into the buffer
+ * (needed in case some serialisations are value-
+ * dependent).
+ *
+ * \return The number of bytes needed in the buffer by
+ * \c psasim_serialise_psa_verify_hash_interruptible_operation_t() to serialise
+ * the given value.
+ */
+size_t psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(psa_verify_hash_interruptible_operation_t value);
+
+/** Serialise a `psa_verify_hash_interruptible_operation_t` into a buffer.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value The value to serialise into the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_verify_hash_interruptible_operation_t value);
+
+/** Deserialise a `psa_verify_hash_interruptible_operation_t` from a buffer.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value Pointer to a `psa_verify_hash_interruptible_operation_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_verify_hash_interruptible_operation_t *value);
+
+/** Return how much buffer space is needed by \c psasim_server_serialise_psa_verify_hash_interruptible_operation_t()
+ * to serialise a `psa_verify_hash_interruptible_operation_t`.
+ *
+ * \param value The value that will be serialised into the buffer
+ * (needed in case some serialisations are value-
+ * dependent).
+ *
+ * \return The number of bytes needed in the buffer by
+ * \c psasim_serialise_psa_verify_hash_interruptible_operation_t() to serialise
+ * the given value.
+ */
+size_t psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(psa_verify_hash_interruptible_operation_t *value);
+
+/** Serialise a `psa_verify_hash_interruptible_operation_t` into a buffer on the server side.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value The value to serialise into the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_server_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_verify_hash_interruptible_operation_t *value);
+
+/** Deserialise a `psa_verify_hash_interruptible_operation_t` from a buffer on the server side.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the buffer.
+ * \param value Pointer to a `psa_verify_hash_interruptible_operation_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_verify_hash_interruptible_operation_t **value);
+
/** Return how much buffer space is needed by \c psasim_serialise_mbedtls_svc_key_id_t()
* to serialise a `mbedtls_svc_key_id_t`.
*
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
index 43ba661..ed5dd9a 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
@@ -36,7 +36,7 @@
# are).
#
my @types = qw(unsigned-int int size_t
- uint16_t uint64_t
+ uint16_t uint32_t uint64_t
buffer
psa_key_production_parameters_t
psa_status_t psa_algorithm_t psa_key_derivation_step_t
@@ -46,6 +46,8 @@
psa_mac_operation_t
psa_cipher_operation_t
psa_key_derivation_operation_t
+ psa_sign_hash_interruptible_operation_t
+ psa_verify_hash_interruptible_operation_t
mbedtls_svc_key_id_t);
grep(s/-/ /g, @types);