psasim: add support for psa_key_derivation_xxx() and psa_raw_key_agreement() to the simulator
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 12c05e3..c9b72e6 100644
--- a/tests/psa-client-server/psasim/src/psa_functions_codes.h
+++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h
@@ -45,6 +45,17 @@
PSA_HASH_UPDATE,
PSA_HASH_VERIFY,
PSA_IMPORT_KEY,
+ PSA_KEY_DERIVATION_ABORT,
+ PSA_KEY_DERIVATION_GET_CAPACITY,
+ PSA_KEY_DERIVATION_INPUT_BYTES,
+ PSA_KEY_DERIVATION_INPUT_INTEGER,
+ PSA_KEY_DERIVATION_INPUT_KEY,
+ PSA_KEY_DERIVATION_KEY_AGREEMENT,
+ PSA_KEY_DERIVATION_OUTPUT_BYTES,
+ PSA_KEY_DERIVATION_OUTPUT_KEY,
+ PSA_KEY_DERIVATION_OUTPUT_KEY_EXT,
+ PSA_KEY_DERIVATION_SET_CAPACITY,
+ PSA_KEY_DERIVATION_SETUP,
PSA_MAC_ABORT,
PSA_MAC_COMPUTE,
PSA_MAC_SIGN_FINISH,
@@ -53,6 +64,7 @@
PSA_MAC_VERIFY,
PSA_MAC_VERIFY_FINISH,
PSA_MAC_VERIFY_SETUP,
+ PSA_RAW_KEY_AGREEMENT,
};
#endif /* _PSA_FUNCTIONS_CODES_H_ */
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 1ae2dd7..84f2b5a 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
@@ -2705,6 +2705,822 @@
}
+psa_status_t psa_key_derivation_abort(
+ psa_key_derivation_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_key_derivation_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_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_ABORT,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_get_capacity(
+ const psa_key_derivation_operation_t *operation,
+ size_t *capacity
+ )
+{
+ 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_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_size_t_needs(*capacity);
+
+ 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_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_size_t(&pos, &remaining, *capacity);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_GET_CAPACITY,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_GET_CAPACITY 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_size_t(&rpos, &rremain, capacity);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_input_bytes(
+ psa_key_derivation_operation_t *operation,
+ psa_key_derivation_step_t step,
+ const uint8_t *data, size_t data_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_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_psa_key_derivation_step_t_needs(step) +
+ psasim_serialise_buffer_needs(data, data_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_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_key_derivation_step_t(&pos, &remaining, step);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, data, data_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_INPUT_BYTES,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_INPUT_BYTES 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_input_integer(
+ psa_key_derivation_operation_t *operation,
+ psa_key_derivation_step_t step,
+ uint64_t value
+ )
+{
+ 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_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_psa_key_derivation_step_t_needs(step) +
+ psasim_serialise_uint64_t_needs(value);
+
+ 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_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_key_derivation_step_t(&pos, &remaining, step);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_uint64_t(&pos, &remaining, value);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_INPUT_INTEGER,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_INPUT_INTEGER 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_input_key(
+ psa_key_derivation_operation_t *operation,
+ psa_key_derivation_step_t step,
+ mbedtls_svc_key_id_t key
+ )
+{
+ 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_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_psa_key_derivation_step_t_needs(step) +
+ psasim_serialise_mbedtls_svc_key_id_t_needs(key);
+
+ 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_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_key_derivation_step_t(&pos, &remaining, step);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_INPUT_KEY,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_INPUT_KEY 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_key_agreement(
+ psa_key_derivation_operation_t *operation,
+ psa_key_derivation_step_t step,
+ mbedtls_svc_key_id_t private_key,
+ const uint8_t *peer_key, size_t peer_key_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_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_psa_key_derivation_step_t_needs(step) +
+ psasim_serialise_mbedtls_svc_key_id_t_needs(private_key) +
+ psasim_serialise_buffer_needs(peer_key, peer_key_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_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_key_derivation_step_t(&pos, &remaining, step);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, private_key);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, peer_key, peer_key_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_KEY_AGREEMENT,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_KEY_AGREEMENT 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_output_bytes(
+ psa_key_derivation_operation_t *operation,
+ uint8_t *output, size_t output_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_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_buffer_needs(output, output_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_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, output, output_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_OUTPUT_BYTES,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_OUTPUT_BYTES 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_return_buffer(&rpos, &rremain, output, output_length);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_output_key(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ mbedtls_svc_key_id_t *key
+ )
+{
+ 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_key_attributes_t_needs(*attributes) +
+ psasim_serialise_psa_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_mbedtls_svc_key_id_t_needs(*key);
+
+ 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_key_attributes_t(&pos, &remaining, *attributes);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_key_derivation_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 = psa_crypto_call(PSA_KEY_DERIVATION_OUTPUT_KEY,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_OUTPUT_KEY 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_mbedtls_svc_key_id_t(&rpos, &rremain, key);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_output_key_ext(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ const psa_key_production_parameters_t *params, size_t params_data_length,
+ mbedtls_svc_key_id_t *key
+ )
+{
+ 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_key_attributes_t_needs(*attributes) +
+ psasim_serialise_psa_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_psa_key_production_parameters_t_needs(params, params_data_length) +
+ psasim_serialise_mbedtls_svc_key_id_t_needs(*key);
+
+ 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_key_attributes_t(&pos, &remaining, *attributes);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_key_production_parameters_t(&pos, &remaining, params, params_data_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, *key);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_OUTPUT_KEY_EXT,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_OUTPUT_KEY_EXT 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_mbedtls_svc_key_id_t(&rpos, &rremain, key);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_set_capacity(
+ psa_key_derivation_operation_t *operation,
+ size_t capacity
+ )
+{
+ 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_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_size_t_needs(capacity);
+
+ 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_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_size_t(&pos, &remaining, capacity);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_SET_CAPACITY,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_SET_CAPACITY 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
+psa_status_t psa_key_derivation_setup(
+ psa_key_derivation_operation_t *operation,
+ psa_algorithm_t alg
+ )
+{
+ 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_key_derivation_operation_t_needs(*operation) +
+ psasim_serialise_psa_algorithm_t_needs(alg);
+
+ 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_key_derivation_operation_t(&pos, &remaining, *operation);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_KEY_DERIVATION_SETUP,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_KEY_DERIVATION_SETUP 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
+
+
psa_status_t psa_mac_abort(
psa_mac_operation_t *operation
)
@@ -3307,3 +4123,95 @@
return status;
}
+
+
+psa_status_t psa_raw_key_agreement(
+ psa_algorithm_t alg,
+ mbedtls_svc_key_id_t private_key,
+ const uint8_t *peer_key, size_t peer_key_length,
+ uint8_t *output, size_t output_size,
+ size_t *output_length
+ )
+{
+ 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_algorithm_t_needs(alg) +
+ psasim_serialise_mbedtls_svc_key_id_t_needs(private_key) +
+ psasim_serialise_buffer_needs(peer_key, peer_key_length) +
+ psasim_serialise_buffer_needs(output, output_size) +
+ psasim_serialise_size_t_needs(*output_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_algorithm_t(&pos, &remaining, alg);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, private_key);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, peer_key, peer_key_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, output, output_size);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_size_t(&pos, &remaining, *output_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_RAW_KEY_AGREEMENT,
+ ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+ if (!ok) {
+ printf("PSA_RAW_KEY_AGREEMENT 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_return_buffer(&rpos, &rremain, output, output_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&rpos, &rremain, output_length);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(ser_params);
+ free(ser_result);
+
+ return status;
+}
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 897d504..92ce96a 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
@@ -3083,6 +3083,929 @@
}
// 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)
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_key_derivation_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_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_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_key_derivation_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_key_derivation_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_key_derivation_get_capacity_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_key_derivation_operation_t *operation;
+ size_t capacity;
+
+ 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_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &capacity);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_get_capacity(
+ operation,
+ &capacity
+ );
+
+ // 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_serialise_size_t_needs(capacity);
+
+ 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_serialise_size_t(&rpos, &rremain, capacity);
+ 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_input_bytes_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_key_derivation_operation_t *operation;
+ psa_key_derivation_step_t step;
+ uint8_t *data = NULL;
+ size_t data_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_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_key_derivation_step_t(&pos, &remaining, &step);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &data, &data_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_input_bytes(
+ operation,
+ step,
+ data, data_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_key_derivation_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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(data);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(data);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_key_derivation_input_integer_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_key_derivation_operation_t *operation;
+ psa_key_derivation_step_t step;
+ uint64_t value;
+
+ 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_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_key_derivation_step_t(&pos, &remaining, &step);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_uint64_t(&pos, &remaining, &value);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_input_integer(
+ operation,
+ step,
+ value
+ );
+
+ // 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_key_derivation_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_key_derivation_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_key_derivation_input_key_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_key_derivation_operation_t *operation;
+ psa_key_derivation_step_t step;
+ mbedtls_svc_key_id_t key;
+
+ 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_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_key_derivation_step_t(&pos, &remaining, &step);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_input_key(
+ operation,
+ step,
+ key
+ );
+
+ // 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_key_derivation_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_key_derivation_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_key_derivation_key_agreement_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_key_derivation_operation_t *operation;
+ psa_key_derivation_step_t step;
+ mbedtls_svc_key_id_t private_key;
+ uint8_t *peer_key = NULL;
+ size_t peer_key_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_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_key_derivation_step_t(&pos, &remaining, &step);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &private_key);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &peer_key, &peer_key_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_key_agreement(
+ operation,
+ step,
+ private_key,
+ peer_key, peer_key_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_key_derivation_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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(peer_key);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(peer_key);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_key_derivation_output_bytes_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_key_derivation_operation_t *operation;
+ uint8_t *output = NULL;
+ size_t output_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_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &output, &output_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_output_bytes(
+ operation,
+ output, output_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_key_derivation_operation_t_needs(operation) +
+ psasim_serialise_buffer_needs(output, output_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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_buffer(&rpos, &rremain, output, output_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(output);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(output);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_key_derivation_output_key_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_key_attributes_t attributes;
+ psa_key_derivation_operation_t *operation;
+ mbedtls_svc_key_id_t key;
+
+ 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_psa_key_attributes_t(&pos, &remaining, &attributes);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_output_key(
+ &attributes,
+ operation,
+ &key
+ );
+
+ // 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_key_derivation_operation_t_needs(operation) +
+ psasim_serialise_mbedtls_svc_key_id_t_needs(key);
+
+ 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_mbedtls_svc_key_id_t(&rpos, &rremain, key);
+ 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_output_key_ext_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_key_attributes_t attributes;
+ psa_key_derivation_operation_t *operation;
+ psa_key_production_parameters_t *params = NULL;
+ size_t params_data_length;
+ mbedtls_svc_key_id_t key;
+
+ 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_psa_key_attributes_t(&pos, &remaining, &attributes);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_server_deserialise_psa_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_key_production_parameters_t(&pos, &remaining, ¶ms, ¶ms_data_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_output_key_ext(
+ &attributes,
+ operation,
+ params, params_data_length,
+ &key
+ );
+
+ // 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_key_derivation_operation_t_needs(operation) +
+ psasim_serialise_mbedtls_svc_key_id_t_needs(key);
+
+ 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_key_derivation_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_mbedtls_svc_key_id_t(&rpos, &rremain, key);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(params);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(params);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_key_derivation_set_capacity_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_key_derivation_operation_t *operation;
+ size_t capacity;
+
+ 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_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &capacity);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_set_capacity(
+ operation,
+ capacity
+ );
+
+ // 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_key_derivation_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_key_derivation_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_key_derivation_setup_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_key_derivation_operation_t *operation;
+ psa_algorithm_t alg;
+
+ 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_key_derivation_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_key_derivation_setup(
+ operation,
+ alg
+ );
+
+ // 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_key_derivation_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_key_derivation_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_mac_abort_wrapper(
uint8_t *in_params, size_t in_params_len,
uint8_t **out_params, size_t *out_params_len)
@@ -3782,6 +4705,117 @@
return 0; // This shouldn't happen!
}
+// Returns 1 for success, 0 for failure
+int psa_raw_key_agreement_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_algorithm_t alg;
+ mbedtls_svc_key_id_t private_key;
+ uint8_t *peer_key = NULL;
+ size_t peer_key_length;
+ uint8_t *output = NULL;
+ size_t output_size;
+ size_t output_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_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &private_key);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &peer_key, &peer_key_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &output, &output_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &output_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_raw_key_agreement(
+ alg,
+ private_key,
+ peer_key, peer_key_length,
+ output, output_size,
+ &output_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_serialise_buffer_needs(output, output_size) +
+ psasim_serialise_size_t_needs(output_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_serialise_buffer(&rpos, &rremain, output, output_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_size_t(&rpos, &rremain, output_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(peer_key);
+ free(output);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(peer_key);
+ free(output);
+
+ return 0; // This shouldn't happen!
+}
+
psa_status_t psa_crypto_call(psa_msg_t msg)
{
int ok = 0;
@@ -3954,6 +4988,50 @@
ok = psa_import_key_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);
+ break;
+ case PSA_KEY_DERIVATION_GET_CAPACITY:
+ ok = psa_key_derivation_get_capacity_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_KEY_DERIVATION_INPUT_BYTES:
+ ok = psa_key_derivation_input_bytes_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_KEY_DERIVATION_INPUT_INTEGER:
+ ok = psa_key_derivation_input_integer_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_KEY_DERIVATION_INPUT_KEY:
+ ok = psa_key_derivation_input_key_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_KEY_DERIVATION_KEY_AGREEMENT:
+ ok = psa_key_derivation_key_agreement_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_KEY_DERIVATION_OUTPUT_BYTES:
+ ok = psa_key_derivation_output_bytes_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_KEY_DERIVATION_OUTPUT_KEY:
+ ok = psa_key_derivation_output_key_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_KEY_DERIVATION_OUTPUT_KEY_EXT:
+ ok = psa_key_derivation_output_key_ext_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_KEY_DERIVATION_SET_CAPACITY:
+ ok = psa_key_derivation_set_capacity_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_KEY_DERIVATION_SETUP:
+ ok = psa_key_derivation_setup_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
case PSA_MAC_ABORT:
ok = psa_mac_abort_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
@@ -3986,6 +5064,10 @@
ok = psa_mac_verify_setup_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
+ case PSA_RAW_KEY_AGREEMENT:
+ ok = psa_raw_key_agreement_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
}
free(in_params);
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 97e92bc..5510be1 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl
@@ -3321,3 +3321,880 @@
* results in this error code.
*/
psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation);
+
+/** \defgroup key_derivation Key derivation and pseudorandom generation
+ * @{
+ */
+
+/** The type of the state data structure for key derivation operations.
+ *
+ * Before calling any function on a key derivation operation object, the
+ * application must initialize it by any of the following means:
+ * - Set the structure to all-bits-zero, for example:
+ * \code
+ * psa_key_derivation_operation_t operation;
+ * memset(&operation, 0, sizeof(operation));
+ * \endcode
+ * - Initialize the structure to logical zero values, for example:
+ * \code
+ * psa_key_derivation_operation_t operation = {0};
+ * \endcode
+ * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT,
+ * for example:
+ * \code
+ * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+ * \endcode
+ * - Assign the result of the function psa_key_derivation_operation_init()
+ * to the structure, for example:
+ * \code
+ * psa_key_derivation_operation_t operation;
+ * operation = psa_key_derivation_operation_init();
+ * \endcode
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice.
+ */
+typedef struct psa_key_derivation_s psa_key_derivation_operation_t;
+
+/** \def PSA_KEY_DERIVATION_OPERATION_INIT
+ *
+ * This macro returns a suitable initializer for a key derivation operation
+ * object of type #psa_key_derivation_operation_t.
+ */
+
+/** Return an initial value for a key derivation operation object.
+ */
+static psa_key_derivation_operation_t psa_key_derivation_operation_init(void);
+
+/** Set up a key derivation operation.
+ *
+ * A key derivation algorithm takes some inputs and uses them to generate
+ * a byte stream in a deterministic way.
+ * This byte stream can be used to produce keys and other
+ * cryptographic material.
+ *
+ * To derive a key:
+ * -# Start with an initialized object of type #psa_key_derivation_operation_t.
+ * -# Call psa_key_derivation_setup() to select the algorithm.
+ * -# Provide the inputs for the key derivation by calling
+ * psa_key_derivation_input_bytes() or psa_key_derivation_input_key()
+ * as appropriate. Which inputs are needed, in what order, and whether
+ * they may be keys and if so of what type depends on the algorithm.
+ * -# Optionally set the operation's maximum capacity with
+ * psa_key_derivation_set_capacity(). You may do this before, in the middle
+ * of or after providing inputs. For some algorithms, this step is mandatory
+ * because the output depends on the maximum capacity.
+ * -# To derive a key, call psa_key_derivation_output_key() or
+ * psa_key_derivation_output_key_ext().
+ * To derive a byte string for a different purpose, call
+ * psa_key_derivation_output_bytes().
+ * Successive calls to these functions use successive output bytes
+ * calculated by the key derivation algorithm.
+ * -# Clean up the key derivation operation object with
+ * psa_key_derivation_abort().
+ *
+ * If this function returns an error, the key derivation operation object is
+ * not changed.
+ *
+ * If an error occurs at any step after a call to psa_key_derivation_setup(),
+ * the operation will need to be reset by a call to psa_key_derivation_abort().
+ *
+ * Implementations must reject an attempt to derive a key of size 0.
+ *
+ * \param[in,out] operation The key derivation operation object
+ * to set up. It must
+ * have been initialized but not set up yet.
+ * \param alg The key derivation algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c alg is not a key derivation algorithm.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \c alg is not supported or is not a key derivation algorithm.
+ * \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_BAD_STATE
+ * The operation state is not valid (it must be inactive), or
+ * 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_key_derivation_setup(
+ psa_key_derivation_operation_t *operation,
+ psa_algorithm_t alg);
+
+/** Retrieve the current capacity of a key derivation operation.
+ *
+ * The capacity of a key derivation is the maximum number of bytes that it can
+ * return. When you get *N* bytes of output from a key derivation operation,
+ * this reduces its capacity by *N*.
+ *
+ * \param[in] operation The operation to query.
+ * \param[out] capacity On success, the capacity of the operation.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (it must be active), or
+ * 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_key_derivation_get_capacity(
+ const psa_key_derivation_operation_t *operation,
+ size_t *capacity);
+
+/** Set the maximum capacity of a key derivation operation.
+ *
+ * The capacity of a key derivation operation is the maximum number of bytes
+ * that the key derivation operation can return from this point onwards.
+ *
+ * \param[in,out] operation The key derivation operation object to modify.
+ * \param capacity The new capacity of the operation.
+ * It must be less or equal to the operation's
+ * current capacity.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \p capacity is larger than the operation's current capacity.
+ * In this case, the operation object remains valid and its capacity
+ * remains unchanged.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (it must be active), or 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_key_derivation_set_capacity(
+ psa_key_derivation_operation_t *operation,
+ size_t capacity);
+
+/** Use the maximum possible capacity for a key derivation operation.
+ *
+ * Use this value as the capacity argument when setting up a key derivation
+ * to indicate that the operation should have the maximum possible capacity.
+ * The value of the maximum possible capacity depends on the key derivation
+ * algorithm.
+ */
+#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t) (-1))
+
+/** Provide an input for key derivation or key agreement.
+ *
+ * Which inputs are required and in what order depends on the algorithm.
+ * Refer to the documentation of each key derivation or key agreement
+ * algorithm for information.
+ *
+ * This function passes direct inputs, which is usually correct for
+ * non-secret inputs. To pass a secret input, which should be in a key
+ * object, call psa_key_derivation_input_key() instead of this function.
+ * Refer to the documentation of individual step types
+ * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t)
+ * for more information.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_key_derivation_abort().
+ *
+ * \param[in,out] operation The key derivation operation object to use.
+ * It must have been set up with
+ * psa_key_derivation_setup() and must not
+ * have produced any output yet.
+ * \param step Which step the input data is for.
+ * \param[in] data Input data to use.
+ * \param data_length Size of the \p data buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c step is not compatible with the operation's algorithm, or
+ * \c step does not allow direct inputs.
+ * \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_BAD_STATE
+ * The operation state is not valid for this input \p step, or
+ * 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_key_derivation_input_bytes(
+ psa_key_derivation_operation_t *operation,
+ psa_key_derivation_step_t step,
+ const uint8_t *data,
+ size_t data_length);
+
+/** Provide a numeric input for key derivation or key agreement.
+ *
+ * Which inputs are required and in what order depends on the algorithm.
+ * However, when an algorithm requires a particular order, numeric inputs
+ * usually come first as they tend to be configuration parameters.
+ * Refer to the documentation of each key derivation or key agreement
+ * algorithm for information.
+ *
+ * This function is used for inputs which are fixed-size non-negative
+ * integers.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_key_derivation_abort().
+ *
+ * \param[in,out] operation The key derivation operation object to use.
+ * It must have been set up with
+ * psa_key_derivation_setup() and must not
+ * have produced any output yet.
+ * \param step Which step the input data is for.
+ * \param[in] value The value of the numeric input.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c step is not compatible with the operation's algorithm, or
+ * \c step does not allow numeric inputs.
+ * \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_BAD_STATE
+ * The operation state is not valid for this input \p step, or
+ * 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_key_derivation_input_integer(
+ psa_key_derivation_operation_t *operation,
+ psa_key_derivation_step_t step,
+ uint64_t value);
+
+/** Provide an input for key derivation in the form of a key.
+ *
+ * Which inputs are required and in what order depends on the algorithm.
+ * Refer to the documentation of each key derivation or key agreement
+ * algorithm for information.
+ *
+ * This function obtains input from a key object, which is usually correct for
+ * secret inputs or for non-secret personalization strings kept in the key
+ * store. To pass a non-secret parameter which is not in the key store,
+ * call psa_key_derivation_input_bytes() instead of this function.
+ * Refer to the documentation of individual step types
+ * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t)
+ * for more information.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_key_derivation_abort().
+ *
+ * \param[in,out] operation The key derivation operation object to use.
+ * It must have been set up with
+ * psa_key_derivation_setup() and must not
+ * have produced any output yet.
+ * \param step Which step the input data is for.
+ * \param key Identifier of the key. It must have an
+ * appropriate type for step and must allow the
+ * usage #PSA_KEY_USAGE_DERIVE or
+ * #PSA_KEY_USAGE_VERIFY_DERIVATION (see note)
+ * and the algorithm used by the operation.
+ *
+ * \note Once all inputs steps are completed, the operations will allow:
+ * - psa_key_derivation_output_bytes() if each input was either a direct input
+ * or a key with #PSA_KEY_USAGE_DERIVE set;
+ * - psa_key_derivation_output_key() or psa_key_derivation_output_key_ext()
+ * if the input for step
+ * #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD
+ * was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was
+ * either a direct input or a key with #PSA_KEY_USAGE_DERIVE set;
+ * - psa_key_derivation_verify_bytes() if each input was either a direct input
+ * or a key with #PSA_KEY_USAGE_VERIFY_DERIVATION set;
+ * - psa_key_derivation_verify_key() under the same conditions as
+ * psa_key_derivation_verify_bytes().
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The key allows neither #PSA_KEY_USAGE_DERIVE nor
+ * #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this
+ * algorithm.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c step is not compatible with the operation's algorithm, or
+ * \c step does not allow key inputs of the given type
+ * or does not allow key inputs at all.
+ * \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_BAD_STATE
+ * The operation state is not valid for this input \p step, or
+ * 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_key_derivation_input_key(
+ psa_key_derivation_operation_t *operation,
+ psa_key_derivation_step_t step,
+ mbedtls_svc_key_id_t key);
+
+/** Perform a key agreement and use the shared secret as input to a key
+ * derivation.
+ *
+ * A key agreement algorithm takes two inputs: a private key \p private_key
+ * a public key \p peer_key.
+ * The result of this function is passed as input to a key derivation.
+ * The output of this key derivation can be extracted by reading from the
+ * resulting operation to produce keys and other cryptographic material.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_key_derivation_abort().
+ *
+ * \param[in,out] operation The key derivation operation object to use.
+ * It must have been set up with
+ * psa_key_derivation_setup() with a
+ * key agreement and derivation algorithm
+ * \c alg (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true
+ * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg)
+ * is false).
+ * The operation must be ready for an
+ * input of the type given by \p step.
+ * \param step Which step the input data is for.
+ * \param private_key Identifier of the private key to use. It must
+ * allow the usage #PSA_KEY_USAGE_DERIVE.
+ * \param[in] peer_key Public key of the peer. The peer key must be in the
+ * same format that psa_import_key() accepts for the
+ * public key type corresponding to the type of
+ * private_key. That is, this function performs the
+ * equivalent of
+ * #psa_import_key(...,
+ * `peer_key`, `peer_key_length`) where
+ * with key attributes indicating the public key
+ * type corresponding to the type of `private_key`.
+ * For example, for EC keys, this means that peer_key
+ * is interpreted as a point on the curve that the
+ * private key is on. The standard formats for public
+ * keys are documented in the documentation of
+ * psa_export_public_key().
+ * \param peer_key_length Size of \p peer_key in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c private_key is not compatible with \c alg,
+ * or \p peer_key is not valid for \c alg or not compatible with
+ * \c private_key, or \c step does not allow an input resulting
+ * from a key agreement.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \c alg is not supported or is not a key derivation algorithm.
+ * \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_BAD_STATE
+ * The operation state is not valid for this key agreement \p step,
+ * or 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_key_derivation_key_agreement(
+ psa_key_derivation_operation_t *operation,
+ psa_key_derivation_step_t step,
+ mbedtls_svc_key_id_t private_key,
+ const uint8_t *peer_key,
+ size_t peer_key_length);
+
+/** Read some data from a key derivation operation.
+ *
+ * This function calculates output bytes from a key derivation algorithm and
+ * return those bytes.
+ * If you view the key derivation's output as a stream of bytes, this
+ * function destructively reads the requested number of bytes from the
+ * stream.
+ * The operation's capacity decreases by the number of bytes read.
+ *
+ * If this function returns an error status other than
+ * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error
+ * state and must be aborted by calling psa_key_derivation_abort().
+ *
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[out] output Buffer where the output will be written.
+ * \param output_length Number of bytes to output.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * One of the inputs was a key whose policy didn't allow
+ * #PSA_KEY_USAGE_DERIVE.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ * The operation's capacity was less than
+ * \p output_length bytes. Note that in this case,
+ * no output is written to the output buffer.
+ * The operation's capacity is set to 0, thus
+ * subsequent calls to this function will not
+ * succeed, even with a smaller output buffer.
+ * \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_BAD_STATE
+ * The operation state is not valid (it must be active and completed
+ * all required input steps), or 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_key_derivation_output_bytes(
+ psa_key_derivation_operation_t *operation,
+ uint8_t *output,
+ size_t output_length);
+
+/** Derive a key from an ongoing key derivation operation.
+ *
+ * This function calculates output bytes from a key derivation algorithm
+ * and uses those bytes to generate a key deterministically.
+ * The key's location, usage policy, type and size are taken from
+ * \p attributes.
+ *
+ * If you view the key derivation's output as a stream of bytes, this
+ * function destructively reads as many bytes as required from the
+ * stream.
+ * The operation's capacity decreases by the number of bytes read.
+ *
+ * If this function returns an error status other than
+ * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error
+ * state and must be aborted by calling psa_key_derivation_abort().
+ *
+ * How much output is produced and consumed from the operation, and how
+ * the key is derived, depends on the key type and on the key size
+ * (denoted \c bits below):
+ *
+ * - For key types for which the key is an arbitrary sequence of bytes
+ * of a given size, this function is functionally equivalent to
+ * calling #psa_key_derivation_output_bytes
+ * and passing the resulting output to #psa_import_key.
+ * However, this function has a security benefit:
+ * if the implementation provides an isolation boundary then
+ * the key material is not exposed outside the isolation boundary.
+ * As a consequence, for these key types, this function always consumes
+ * exactly (\c bits / 8) bytes from the operation.
+ * The following key types defined in this specification follow this scheme:
+ *
+ * - #PSA_KEY_TYPE_AES;
+ * - #PSA_KEY_TYPE_ARIA;
+ * - #PSA_KEY_TYPE_CAMELLIA;
+ * - #PSA_KEY_TYPE_DERIVE;
+ * - #PSA_KEY_TYPE_HMAC;
+ * - #PSA_KEY_TYPE_PASSWORD_HASH.
+ *
+ * - For ECC keys on a Montgomery elliptic curve
+ * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a
+ * Montgomery curve), this function always draws a byte string whose
+ * length is determined by the curve, and sets the mandatory bits
+ * accordingly. That is:
+ *
+ * - Curve25519 (#PSA_ECC_FAMILY_MONTGOMERY, 255 bits): draw a 32-byte
+ * string and process it as specified in RFC 7748 §5.
+ * - Curve448 (#PSA_ECC_FAMILY_MONTGOMERY, 448 bits): draw a 56-byte
+ * string and process it as specified in RFC 7748 §5.
+ *
+ * - For key types for which the key is represented by a single sequence of
+ * \c bits bits with constraints as to which bit sequences are acceptable,
+ * this function draws a byte string of length (\c bits / 8) bytes rounded
+ * up to the nearest whole number of bytes. If the resulting byte string
+ * is acceptable, it becomes the key, otherwise the drawn bytes are discarded.
+ * This process is repeated until an acceptable byte string is drawn.
+ * The byte string drawn from the operation is interpreted as specified
+ * for the output produced by psa_export_key().
+ * The following key types defined in this specification follow this scheme:
+ *
+ * - #PSA_KEY_TYPE_DES.
+ * Force-set the parity bits, but discard forbidden weak keys.
+ * For 2-key and 3-key triple-DES, the three keys are generated
+ * successively (for example, for 3-key triple-DES,
+ * if the first 8 bytes specify a weak key and the next 8 bytes do not,
+ * discard the first 8 bytes, use the next 8 bytes as the first key,
+ * and continue reading output from the operation to derive the other
+ * two keys).
+ * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group)
+ * where \c group designates any Diffie-Hellman group) and
+ * ECC keys on a Weierstrass elliptic curve
+ * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a
+ * Weierstrass curve).
+ * For these key types, interpret the byte string as integer
+ * in big-endian order. Discard it if it is not in the range
+ * [0, *N* - 2] where *N* is the boundary of the private key domain
+ * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA,
+ * or the order of the curve's base point for ECC).
+ * Add 1 to the resulting integer and use this as the private key *x*.
+ * This method allows compliance to NIST standards, specifically
+ * the methods titled "key-pair generation by testing candidates"
+ * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman,
+ * in FIPS 186-4 §B.1.2 for DSA, and
+ * in NIST SP 800-56A §5.6.1.2.2 or
+ * FIPS 186-4 §B.4.2 for elliptic curve keys.
+ *
+ * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR,
+ * the way in which the operation output is consumed is
+ * implementation-defined.
+ *
+ * In all cases, the data that is read is discarded from the operation.
+ * The operation's capacity is decreased by the number of bytes read.
+ *
+ * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET,
+ * the input to that step must be provided with psa_key_derivation_input_key().
+ * Future versions of this specification may include additional restrictions
+ * on the derived key based on the attributes and strength of the secret key.
+ *
+ * \note This function is equivalent to calling
+ * psa_key_derivation_output_key_ext()
+ * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ * and `params_data_length == 0` (i.e. `params->data` is empty).
+ *
+ * \param[in] attributes The attributes for the new key.
+ * If the key type to be created is
+ * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
+ * the policy must be the same as in the current
+ * operation.
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[out] key On success, an identifier for the newly created
+ * key. For persistent keys, this is the key
+ * identifier defined in \p attributes.
+ * \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * If the key is persistent, the key material and the key's metadata
+ * have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ * This is an attempt to create a persistent key, and there is
+ * already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ * There was not enough data to create the desired key.
+ * Note that in this case, no output is written to the output buffer.
+ * The operation's capacity is set to 0, thus subsequent calls to
+ * this function will not succeed, even with a smaller output buffer.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * The key type or key size is not supported, either by the
+ * implementation in general or in this particular location.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The provided key attributes are not valid for the operation.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The #PSA_KEY_DERIVATION_INPUT_SECRET or
+ * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
+ * key; or one of the inputs was a key whose policy didn't allow
+ * #PSA_KEY_USAGE_DERIVE.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (it must be active and completed
+ * all required input steps), or 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_key_derivation_output_key(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ mbedtls_svc_key_id_t *key);
+
+/** Derive a key from an ongoing key derivation operation with custom
+ * production parameters.
+ *
+ * See the description of psa_key_derivation_out_key() for the operation of
+ * this function with the default production parameters.
+ * Mbed TLS currently does not currently support any non-default production
+ * parameters.
+ *
+ * \note This function is experimental and may change in future minor
+ * versions of Mbed TLS.
+ *
+ * \param[in] attributes The attributes for the new key.
+ * If the key type to be created is
+ * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
+ * the policy must be the same as in the current
+ * operation.
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[in] params Customization parameters for the key derivation.
+ * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ * with \p params_data_length = 0,
+ * this function is equivalent to
+ * psa_key_derivation_output_key().
+ * Mbed TLS currently only supports the default
+ * production parameters, i.e.
+ * #PSA_KEY_PRODUCTION_PARAMETERS_INIT,
+ * for all key types.
+ * \param params_data_length
+ * Length of `params->data` in bytes.
+ * \param[out] key On success, an identifier for the newly created
+ * key. For persistent keys, this is the key
+ * identifier defined in \p attributes.
+ * \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * If the key is persistent, the key material and the key's metadata
+ * have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ * This is an attempt to create a persistent key, and there is
+ * already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ * There was not enough data to create the desired key.
+ * Note that in this case, no output is written to the output buffer.
+ * The operation's capacity is set to 0, thus subsequent calls to
+ * this function will not succeed, even with a smaller output buffer.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * The key type or key size is not supported, either by the
+ * implementation in general or in this particular location.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The provided key attributes are not valid for the operation.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The #PSA_KEY_DERIVATION_INPUT_SECRET or
+ * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
+ * key; or one of the inputs was a key whose policy didn't allow
+ * #PSA_KEY_USAGE_DERIVE.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (it must be active and completed
+ * all required input steps), or 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_key_derivation_output_key_ext(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length,
+ mbedtls_svc_key_id_t *key);
+
+/** Compare output data from a key derivation operation to an expected value.
+ *
+ * This function calculates output bytes from a key derivation algorithm and
+ * compares those bytes to an expected value in constant time.
+ * If you view the key derivation's output as a stream of bytes, this
+ * function destructively reads the expected number of bytes from the
+ * stream before comparing them.
+ * The operation's capacity decreases by the number of bytes read.
+ *
+ * This is functionally equivalent to the following code:
+ * \code
+ * psa_key_derivation_output_bytes(operation, tmp, output_length);
+ * if (memcmp(output, tmp, output_length) != 0)
+ * return PSA_ERROR_INVALID_SIGNATURE;
+ * \endcode
+ * except (1) it works even if the key's policy does not allow outputting the
+ * bytes, and (2) the comparison will be done in constant time.
+ *
+ * If this function returns an error status other than
+ * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE,
+ * the operation enters an error state and must be aborted by calling
+ * psa_key_derivation_abort().
+ *
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[in] expected_output Buffer containing the expected derivation output.
+ * \param output_length Length of the expected output; this is also the
+ * number of bytes that will be read.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ * The output was read successfully, but it differs from the expected
+ * output.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * One of the inputs was a key whose policy didn't allow
+ * #PSA_KEY_USAGE_VERIFY_DERIVATION.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ * The operation's capacity was less than
+ * \p output_length bytes. Note that in this case,
+ * the operation's capacity is set to 0, thus
+ * subsequent calls to this function will not
+ * succeed, even with a smaller expected output.
+ * \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_BAD_STATE
+ * The operation state is not valid (it must be active and completed
+ * all required input steps), or 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_key_derivation_verify_bytes(
+ psa_key_derivation_operation_t *operation,
+ const uint8_t *expected_output,
+ size_t output_length);
+
+/** Compare output data from a key derivation operation to an expected value
+ * stored in a key object.
+ *
+ * This function calculates output bytes from a key derivation algorithm and
+ * compares those bytes to an expected value, provided as key of type
+ * #PSA_KEY_TYPE_PASSWORD_HASH.
+ * If you view the key derivation's output as a stream of bytes, this
+ * function destructively reads the number of bytes corresponding to the
+ * length of the expected value from the stream before comparing them.
+ * The operation's capacity decreases by the number of bytes read.
+ *
+ * This is functionally equivalent to exporting the key and calling
+ * psa_key_derivation_verify_bytes() on the result, except that it
+ * works even if the key cannot be exported.
+ *
+ * If this function returns an error status other than
+ * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE,
+ * the operation enters an error state and must be aborted by calling
+ * psa_key_derivation_abort().
+ *
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[in] expected A key of type #PSA_KEY_TYPE_PASSWORD_HASH
+ * containing the expected output. Its policy must
+ * include the #PSA_KEY_USAGE_VERIFY_DERIVATION flag
+ * and the permitted algorithm must match the
+ * operation. The value of this key was likely
+ * computed by a previous call to
+ * psa_key_derivation_output_key() or
+ * psa_key_derivation_output_key_ext().
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ * The output was read successfully, but if differs from the expected
+ * output.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * The key passed as the expected value does not exist.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The key passed as the expected value has an invalid type.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The key passed as the expected value does not allow this usage or
+ * this algorithm; or one of the inputs was a key whose policy didn't
+ * allow #PSA_KEY_USAGE_VERIFY_DERIVATION.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ * The operation's capacity was less than
+ * the length of the expected value. In this case,
+ * the operation's capacity is set to 0, thus
+ * subsequent calls to this function will not
+ * succeed, even with a smaller expected output.
+ * \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_BAD_STATE
+ * The operation state is not valid (it must be active and completed
+ * all required input steps), or 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_key_derivation_verify_key(
+ psa_key_derivation_operation_t *operation,
+ psa_key_id_t expected);
+
+/** Abort a key derivation operation.
+ *
+ * Aborting an operation frees all associated resources except for the \c
+ * operation structure itself. Once aborted, the operation object can be reused
+ * for another operation by calling psa_key_derivation_setup() again.
+ *
+ * This function may be called at any time after the operation
+ * object has been initialized as described in #psa_key_derivation_operation_t.
+ *
+ * In particular, it is valid to call psa_key_derivation_abort() twice, or to
+ * call psa_key_derivation_abort() on an operation that has not been set up.
+ *
+ * \param[in,out] operation The operation to abort.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \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_key_derivation_abort(
+ psa_key_derivation_operation_t *operation);
+
+/** Perform a key agreement and return the raw shared secret.
+ *
+ * \warning The raw result of a key agreement algorithm such as finite-field
+ * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should
+ * not be used directly as key material. It should instead be passed as
+ * input to a key derivation algorithm. To chain a key agreement with
+ * a key derivation, use psa_key_derivation_key_agreement() and other
+ * functions from the key derivation interface.
+ *
+ * \param alg The key agreement algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg)
+ * is true).
+ * \param private_key Identifier of the private key to use. It must
+ * allow the usage #PSA_KEY_USAGE_DERIVE.
+ * \param[in] peer_key Public key of the peer. It must be
+ * in the same format that psa_import_key()
+ * accepts. The standard formats for public
+ * keys are documented in the documentation
+ * of psa_export_public_key().
+ * \param peer_key_length Size of \p peer_key in bytes.
+ * \param[out] output Buffer where the decrypted message is to
+ * be written.
+ * \param output_size Size of the \c output buffer in bytes.
+ * \param[out] output_length On success, the number of bytes
+ * that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \p alg is not a key agreement algorithm, or
+ * \p private_key is not compatible with \p alg,
+ * or \p peer_key is not valid for \p alg or not compatible with
+ * \p private_key.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * \p output_size is too small
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \p alg is not a supported key agreement algorithm.
+ * \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_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_raw_key_agreement(psa_algorithm_t alg,
+ mbedtls_svc_key_id_t private_key,
+ const uint8_t *peer_key,
+ size_t peer_key_length,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length);
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 975abd2..4de7802 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
@@ -215,6 +215,44 @@
return -1; /* not found */
}
+static psa_key_derivation_operation_t key_derivation_operations[MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t key_derivation_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t next_key_derivation_operation_handle = 1;
+
+/* Get a free slot */
+static ssize_t allocate_key_derivation_operation_slot(void)
+{
+ psasim_client_handle_t handle = next_key_derivation_operation_handle++;
+ if (next_key_derivation_operation_handle == 0) { /* wrapped around */
+ FATAL("Key_derivation operation handle wrapped");
+ }
+
+ for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+ if (key_derivation_operation_handles[i] == 0) {
+ key_derivation_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_key_derivation_slot_by_handle(psasim_client_handle_t handle)
+{
+ for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+ if (key_derivation_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
@@ -394,6 +432,76 @@
return 1;
}
+size_t psasim_serialise_uint16_t_needs(uint16_t value)
+{
+ return sizeof(value);
+}
+
+int psasim_serialise_uint16_t(uint8_t **pos,
+ size_t *remaining,
+ uint16_t value)
+{
+ if (*remaining < sizeof(value)) {
+ return 0;
+ }
+
+ memcpy(*pos, &value, sizeof(value));
+ *pos += sizeof(value);
+
+ return 1;
+}
+
+int psasim_deserialise_uint16_t(uint8_t **pos,
+ size_t *remaining,
+ uint16_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);
+}
+
+int psasim_serialise_uint64_t(uint8_t **pos,
+ size_t *remaining,
+ uint64_t value)
+{
+ if (*remaining < sizeof(value)) {
+ return 0;
+ }
+
+ memcpy(*pos, &value, sizeof(value));
+ *pos += sizeof(value);
+
+ return 1;
+}
+
+int psasim_deserialise_uint64_t(uint8_t **pos,
+ size_t *remaining,
+ uint64_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_buffer_needs(const uint8_t *buffer, size_t buffer_size)
{
(void) buffer;
@@ -496,6 +604,100 @@
return 1;
}
+#define SER_TAG_SIZE 4
+
+size_t psasim_serialise_psa_key_production_parameters_t_needs(
+ const psa_key_production_parameters_t *params,
+ size_t data_length)
+{
+ /* We will serialise with 4-byte tag = "PKPP" + 4-byte overall length at the beginning,
+ * followed by size_t data_length, then the actual data from the structure.
+ */
+ return SER_TAG_SIZE + sizeof(uint32_t) + sizeof(data_length) + sizeof(*params) + data_length;
+}
+
+int psasim_serialise_psa_key_production_parameters_t(uint8_t **pos,
+ size_t *remaining,
+ const psa_key_production_parameters_t *params,
+ size_t data_length)
+{
+ if (data_length > UINT32_MAX / 2) { /* arbitrary limit */
+ return 0; /* too big to serialise */
+ }
+
+ /* We use 32-bit lengths, which should be enough for any reasonable usage :) */
+ /* (the UINT32_MAX / 2 above is an even more conservative check to avoid overflow here) */
+ uint32_t len = (uint32_t) (sizeof(data_length) + sizeof(*params) + data_length);
+ if (*remaining < SER_TAG_SIZE + sizeof(uint32_t) + len) {
+ return 0;
+ }
+
+ char tag[SER_TAG_SIZE] = "PKPP";
+
+ memcpy(*pos, tag, sizeof(tag));
+ memcpy(*pos + sizeof(tag), &len, sizeof(len));
+ *pos += sizeof(tag) + sizeof(len);
+ *remaining -= sizeof(tag) + sizeof(len);
+
+ memcpy(*pos, &data_length, sizeof(data_length));
+ memcpy(*pos + sizeof(data_length), params, sizeof(*params) + data_length);
+ *pos += sizeof(data_length) + sizeof(*params) + data_length;
+ *remaining -= sizeof(data_length) + sizeof(*params) + data_length;
+
+ return 1;
+}
+
+int psasim_deserialise_psa_key_production_parameters_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_production_parameters_t **params,
+ size_t *data_length)
+{
+ if (*remaining < SER_TAG_SIZE + sizeof(uint32_t)) {
+ return 0; /* can't even be an empty serialisation */
+ }
+
+ char tag[SER_TAG_SIZE] = "PKPP"; /* expected */
+ uint32_t len;
+
+ memcpy(&len, *pos + sizeof(tag), sizeof(len));
+
+ if (memcmp(*pos, tag, sizeof(tag)) != 0) {
+ return 0; /* wrong tag */
+ }
+
+ *pos += sizeof(tag) + sizeof(len);
+ *remaining -= sizeof(tag) + sizeof(len);
+
+ if (*remaining < sizeof(*data_length)) {
+ return 0; /* missing data_length */
+ }
+ memcpy(data_length, *pos, sizeof(*data_length));
+
+ if ((size_t)len != (sizeof(data_length) + sizeof(**params) + *data_length)) {
+ return 0; /* wrong length */
+ }
+
+ if (*remaining < sizeof(*data_length) + sizeof(**params) + *data_length) {
+ return 0; /* not enough data provided */
+ }
+
+ *pos += sizeof(data_length);
+ *remaining -= sizeof(data_length);
+
+ psa_key_production_parameters_t *out = malloc(sizeof(**params) + *data_length);
+ if (out == NULL) {
+ return 0; /* allocation failure */
+ }
+
+ memcpy(out, *pos, sizeof(*out) + *data_length);
+ *pos += sizeof(*out) + *data_length;
+ *remaining -= sizeof(*out) + *data_length;
+
+ *params = out;
+
+ return 1;
+}
+
size_t psasim_serialise_psa_status_t_needs(psa_status_t value)
{
return psasim_serialise_int_needs(value);
@@ -534,6 +736,25 @@
return psasim_deserialise_unsigned_int(pos, remaining, value);
}
+size_t psasim_serialise_psa_key_derivation_step_t_needs(psa_key_derivation_step_t value)
+{
+ return psasim_serialise_uint16_t_needs(value);
+}
+
+int psasim_serialise_psa_key_derivation_step_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_step_t value)
+{
+ return psasim_serialise_uint16_t(pos, remaining, value);
+}
+
+int psasim_deserialise_psa_key_derivation_step_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_step_t *value)
+{
+ return psasim_deserialise_uint16_t(pos, remaining, value);
+}
+
size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t value)
{
return sizeof(value);
@@ -941,6 +1162,99 @@
return 1;
}
+size_t psasim_serialise_psa_key_derivation_operation_t_needs(psa_key_derivation_operation_t value)
+{
+ return sizeof(value);
+}
+
+int psasim_serialise_psa_key_derivation_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_operation_t value)
+{
+ if (*remaining < sizeof(value)) {
+ return 0;
+ }
+
+ memcpy(*pos, &value, sizeof(value));
+ *pos += sizeof(value);
+
+ return 1;
+}
+
+int psasim_deserialise_psa_key_derivation_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_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_key_derivation_operation_t_needs(psa_key_derivation_operation_t *operation)
+{
+ (void) operation;
+
+ /* We will actually return a handle */
+ return sizeof(psasim_operation_t);
+}
+
+int psasim_server_serialise_psa_key_derivation_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_operation_t *operation)
+{
+ psasim_operation_t client_operation;
+
+ if (*remaining < sizeof(client_operation)) {
+ return 0;
+ }
+
+ ssize_t slot = operation - key_derivation_operations;
+
+ client_operation.handle = key_derivation_operation_handles[slot];
+
+ memcpy(*pos, &client_operation, sizeof(client_operation));
+ *pos += sizeof(client_operation);
+
+ return 1;
+}
+
+int psasim_server_deserialise_psa_key_derivation_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_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_key_derivation_operation_slot();
+ } else {
+ slot = find_key_derivation_slot_by_handle(client_operation.handle);
+ }
+
+ if (slot < 0) {
+ return 0;
+ }
+
+ *operation = &key_derivation_operations[slot];
+
+ return 1;
+}
+
size_t psasim_serialise_mbedtls_svc_key_id_t_needs(mbedtls_svc_key_id_t value)
{
return sizeof(value);
@@ -986,4 +1300,6 @@
memset(mac_operations, 0, sizeof(mac_operations));
memset(cipher_operation_handles, 0, sizeof(cipher_operation_handles));
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));
}
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 55b2acb..1028518 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
@@ -222,6 +222,90 @@
size_t *remaining,
size_t *value);
+/** Return how much buffer space is needed by \c psasim_serialise_uint16_t()
+ * to serialise an `uint16_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_uint16_t() to serialise
+ * the given value.
+ */
+size_t psasim_serialise_uint16_t_needs(uint16_t value);
+
+/** Serialise an `uint16_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_uint16_t(uint8_t **pos,
+ size_t *remaining,
+ uint16_t value);
+
+/** Deserialise an `uint16_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 `uint16_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_uint16_t(uint8_t **pos,
+ size_t *remaining,
+ uint16_t *value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_uint64_t()
+ * to serialise an `uint64_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_uint64_t() to serialise
+ * the given value.
+ */
+size_t psasim_serialise_uint64_t_needs(uint64_t value);
+
+/** Serialise an `uint64_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_uint64_t(uint8_t **pos,
+ size_t *remaining,
+ uint64_t value);
+
+/** Deserialise an `uint64_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 `uint64_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_uint64_t(uint8_t **pos,
+ size_t *remaining,
+ uint64_t *value);
+
/** Return how much space is needed by \c psasim_serialise_buffer()
* to serialise a buffer: a (`uint8_t *`, `size_t`) pair.
*
@@ -289,6 +373,56 @@
int psasim_deserialise_return_buffer(uint8_t **pos, size_t *remaining,
uint8_t *buffer, size_t buffer_length);
+/** Return how much space is needed by \c psasim_serialise_psa_key_production_parameters_t()
+ * to serialise a psa_key_production_parameters_t (a structure with a flexible array member).
+ *
+ * \param params Pointer to the struct to be serialised
+ * (needed in case some serialisations are value-
+ * dependent).
+ * \param data_length Number of bytes in the data[] of the struct to be serialised.
+ *
+ * \return The number of bytes needed in the serialisation buffer by
+ * \c psasim_serialise_psa_key_production_parameters_t() to serialise
+ * the specified structure.
+ */
+size_t psasim_serialise_psa_key_production_parameters_t_needs(
+ const psa_key_production_parameters_t *params,
+ size_t buffer_size);
+
+/** Serialise a psa_key_production_parameters_t.
+ *
+ * \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 params Pointer to the structure to be serialised.
+ * \param data_length Number of bytes in the data[] of the struct to be serialised.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_psa_key_production_parameters_t(uint8_t **pos,
+ size_t *remaining,
+ const psa_key_production_parameters_t *params,
+ size_t data_length);
+
+/** Deserialise a psa_key_production_parameters_t.
+ *
+ * \param pos[in,out] Pointer to a `uint8_t *` holding current position
+ * in the serialisation buffer.
+ * \param remaining[in,out] Pointer to a `size_t` holding number of bytes
+ * remaining in the serialisation buffer.
+ * \param params Pointer to a `psa_key_production_parameters_t *` to
+ * receive the address of a newly-allocated structure,
+ * which the caller must `free()`.
+ * \param data_length Pointer to a `size_t` to receive the number of
+ * bytes in the data[] member of the structure deserialised.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_key_production_parameters_t(uint8_t **pos, size_t *remaining,
+ psa_key_production_parameters_t **params,
+ size_t *buffer_length);
+
/** Return how much buffer space is needed by \c psasim_serialise_psa_status_t()
* to serialise a `psa_status_t`.
*
@@ -373,6 +507,48 @@
size_t *remaining,
psa_algorithm_t *value);
+/** Return how much buffer space is needed by \c psasim_serialise_psa_key_derivation_step_t()
+ * to serialise a `psa_key_derivation_step_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_key_derivation_step_t() to serialise
+ * the given value.
+ */
+size_t psasim_serialise_psa_key_derivation_step_t_needs(psa_key_derivation_step_t value);
+
+/** Serialise a `psa_key_derivation_step_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_key_derivation_step_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_step_t value);
+
+/** Deserialise a `psa_key_derivation_step_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_key_derivation_step_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_key_derivation_step_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_step_t *value);
+
/** Return how much buffer space is needed by \c psasim_serialise_psa_hash_operation_t()
* to serialise a `psa_hash_operation_t`.
*
@@ -751,6 +927,90 @@
size_t *remaining,
psa_cipher_operation_t **value);
+/** Return how much buffer space is needed by \c psasim_serialise_psa_key_derivation_operation_t()
+ * to serialise a `psa_key_derivation_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_key_derivation_operation_t() to serialise
+ * the given value.
+ */
+size_t psasim_serialise_psa_key_derivation_operation_t_needs(psa_key_derivation_operation_t value);
+
+/** Serialise a `psa_key_derivation_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_key_derivation_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_operation_t value);
+
+/** Deserialise a `psa_key_derivation_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_key_derivation_operation_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_key_derivation_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_operation_t *value);
+
+/** Return how much buffer space is needed by \c psasim_server_serialise_psa_key_derivation_operation_t()
+ * to serialise a `psa_key_derivation_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_key_derivation_operation_t() to serialise
+ * the given value.
+ */
+size_t psasim_server_serialise_psa_key_derivation_operation_t_needs(psa_key_derivation_operation_t *value);
+
+/** Serialise a `psa_key_derivation_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_key_derivation_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_operation_t *value);
+
+/** Deserialise a `psa_key_derivation_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_key_derivation_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_key_derivation_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_derivation_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 6b23f5c..43ba661 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
@@ -36,13 +36,16 @@
# are).
#
my @types = qw(unsigned-int int size_t
+ uint16_t uint64_t
buffer
- psa_status_t psa_algorithm_t
+ psa_key_production_parameters_t
+ psa_status_t psa_algorithm_t psa_key_derivation_step_t
psa_hash_operation_t
psa_aead_operation_t
psa_key_attributes_t
psa_mac_operation_t
psa_cipher_operation_t
+ psa_key_derivation_operation_t
mbedtls_svc_key_id_t);
grep(s/-/ /g, @types);
@@ -51,6 +54,7 @@
my %isa = (
"psa_status_t" => "int",
"psa_algorithm_t" => "unsigned int",
+ "psa_key_derivation_step_t" => "uint16_t",
);
if ($which eq "h") {