Merge pull request #10027 from valeriosetti/md-psa-dispatch-development

[development] md: allow dispatch to PSA whenever CRYPTO_CLIENT is enabled
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 4be53c5..74746b6 100644
--- a/tests/psa-client-server/psasim/src/psa_functions_codes.h
+++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h
@@ -26,6 +26,7 @@
     PSA_AEAD_VERIFY,
     PSA_ASYMMETRIC_DECRYPT,
     PSA_ASYMMETRIC_ENCRYPT,
+    PSA_CAN_DO_HASH,
     PSA_CIPHER_ABORT,
     PSA_CIPHER_DECRYPT,
     PSA_CIPHER_DECRYPT_SETUP,
@@ -39,6 +40,10 @@
     PSA_DESTROY_KEY,
     PSA_EXPORT_KEY,
     PSA_EXPORT_PUBLIC_KEY,
+    PSA_EXPORT_PUBLIC_KEY_IOP_ABORT,
+    PSA_EXPORT_PUBLIC_KEY_IOP_COMPLETE,
+    PSA_EXPORT_PUBLIC_KEY_IOP_GET_NUM_OPS,
+    PSA_EXPORT_PUBLIC_KEY_IOP_SETUP,
     PSA_GENERATE_KEY,
     PSA_GENERATE_KEY_CUSTOM,
     PSA_GENERATE_KEY_IOP_ABORT,
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 f6efd62..635a705 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
@@ -1544,6 +1544,68 @@
 }
 
 
+int psa_can_do_hash(
+    psa_algorithm_t hash_alg
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    int value = 0;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_algorithm_t_needs(hash_alg);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        hash_alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_CAN_DO_HASH,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CAN_DO_HASH 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_int(
+        &rpos, &rremain,
+        &value);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return value;
+}
+
+
 psa_status_t psa_cipher_abort(
     psa_cipher_operation_t *operation
     )
@@ -2725,6 +2787,324 @@
 }
 
 
+psa_status_t psa_export_public_key_iop_abort(
+    psa_export_public_key_iop_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_export_public_key_iop_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_export_public_key_iop_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_EXPORT_PUBLIC_KEY_IOP_ABORT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_EXPORT_PUBLIC_KEY_IOP_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_export_public_key_iop_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_export_public_key_iop_complete(
+    psa_export_public_key_iop_t *operation,
+    uint8_t *data, size_t  data_size,
+    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_export_public_key_iop_t_needs(*operation) +
+        psasim_serialise_buffer_needs(data, data_size) +
+        psasim_serialise_size_t_needs(*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_export_public_key_iop_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        data, data_size);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *data_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_EXPORT_PUBLIC_KEY_IOP_COMPLETE,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_EXPORT_PUBLIC_KEY_IOP_COMPLETE server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_export_public_key_iop_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        data, data_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        data_length);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+uint32_t psa_export_public_key_iop_get_num_ops(
+    psa_export_public_key_iop_t *operation
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    uint32_t value = 0;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_export_public_key_iop_t_needs(*operation);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        value = 0;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_export_public_key_iop_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_EXPORT_PUBLIC_KEY_IOP_GET_NUM_OPS,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_EXPORT_PUBLIC_KEY_IOP_GET_NUM_OPS server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_uint32_t(
+        &rpos, &rremain,
+        &value);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_export_public_key_iop_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return value;
+}
+
+
+psa_status_t psa_export_public_key_iop_setup(
+    psa_export_public_key_iop_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_export_public_key_iop_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_export_public_key_iop_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_EXPORT_PUBLIC_KEY_IOP_SETUP,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_EXPORT_PUBLIC_KEY_IOP_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_export_public_key_iop_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
 psa_status_t psa_generate_key(
     const psa_key_attributes_t *attributes,
     mbedtls_svc_key_id_t *key
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 599e55f..bd121c5 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
@@ -1706,6 +1706,73 @@
 }
 
 // Returns 1 for success, 0 for failure
+int psa_can_do_hash_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    int value = 0;
+    psa_algorithm_t hash_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_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &hash_alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    value = psa_can_do_hash(
+        hash_alg
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_int_needs(value);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_int(
+        &rpos, &rremain,
+        value);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
 int psa_cipher_abort_wrapper(
     uint8_t *in_params, size_t in_params_len,
     uint8_t **out_params, size_t *out_params_len)
@@ -3036,6 +3103,354 @@
 }
 
 // Returns 1 for success, 0 for failure
+int psa_export_public_key_iop_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_export_public_key_iop_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_deserialise_psa_export_public_key_iop_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_export_public_key_iop_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_serialise_psa_export_public_key_iop_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_serialise_psa_export_public_key_iop_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_export_public_key_iop_complete_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_export_public_key_iop_t operation;
+    uint8_t *data = NULL;
+    size_t data_size;
+    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_deserialise_psa_export_public_key_iop_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &data, &data_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &data_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_export_public_key_iop_complete(
+        &operation,
+        data, data_size,
+        &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_serialise_psa_export_public_key_iop_t_needs(operation) +
+        psasim_serialise_buffer_needs(data, data_size) +
+        psasim_serialise_size_t_needs(data_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_psa_export_public_key_iop_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        data, data_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        data_length);
+    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_export_public_key_iop_get_num_ops_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    uint32_t value = 0;
+    psa_export_public_key_iop_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_deserialise_psa_export_public_key_iop_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    value = psa_export_public_key_iop_get_num_ops(
+        &operation
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_uint32_t_needs(value) +
+        psasim_serialise_psa_export_public_key_iop_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_uint32_t(
+        &rpos, &rremain,
+        value);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_export_public_key_iop_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_export_public_key_iop_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_export_public_key_iop_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_export_public_key_iop_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_export_public_key_iop_setup(
+        &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_serialise_psa_export_public_key_iop_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_serialise_psa_export_public_key_iop_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_generate_key_wrapper(
     uint8_t *in_params, size_t in_params_len,
     uint8_t **out_params, size_t *out_params_len)
@@ -8478,6 +8893,10 @@
             ok = psa_asymmetric_encrypt_wrapper(in_params, in_params_len,
                                                 &out_params, &out_params_len);
             break;
+        case PSA_CAN_DO_HASH:
+            ok = psa_can_do_hash_wrapper(in_params, in_params_len,
+                                         &out_params, &out_params_len);
+            break;
         case PSA_CIPHER_ABORT:
             ok = psa_cipher_abort_wrapper(in_params, in_params_len,
                                           &out_params, &out_params_len);
@@ -8530,6 +8949,22 @@
             ok = psa_export_public_key_wrapper(in_params, in_params_len,
                                                &out_params, &out_params_len);
             break;
+        case PSA_EXPORT_PUBLIC_KEY_IOP_ABORT:
+            ok = psa_export_public_key_iop_abort_wrapper(in_params, in_params_len,
+                                                         &out_params, &out_params_len);
+            break;
+        case PSA_EXPORT_PUBLIC_KEY_IOP_COMPLETE:
+            ok = psa_export_public_key_iop_complete_wrapper(in_params, in_params_len,
+                                                            &out_params, &out_params_len);
+            break;
+        case PSA_EXPORT_PUBLIC_KEY_IOP_GET_NUM_OPS:
+            ok = psa_export_public_key_iop_get_num_ops_wrapper(in_params, in_params_len,
+                                                               &out_params, &out_params_len);
+            break;
+        case PSA_EXPORT_PUBLIC_KEY_IOP_SETUP:
+            ok = psa_export_public_key_iop_setup_wrapper(in_params, in_params_len,
+                                                         &out_params, &out_params_len);
+            break;
         case PSA_GENERATE_KEY:
             ok = psa_generate_key_wrapper(in_params, in_params_len,
                                           &out_params, &out_params_len);
diff --git a/tests/psa-client-server/psasim/src/psa_sim_generate.pl b/tests/psa-client-server/psasim/src/psa_sim_generate.pl
index fbceddf..5490337 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl
@@ -1107,11 +1107,13 @@
                 my $ret_name = "";
                 $ret_name = "status" if $ret_type eq "psa_status_t";
                 $ret_name = "value" if $ret_type eq "uint32_t";
+                $ret_name = "value" if $ret_type eq "int";
                 $ret_name = "(void)" if $ret_type eq "void";
                 die("ret_name for $ret_type?") unless length($ret_name);
                 my $ret_default = "";
                 $ret_default = "PSA_ERROR_CORRUPTION_DETECTED" if $ret_type eq "psa_status_t";
                 $ret_default = "0" if $ret_type eq "uint32_t";
+                $ret_default = "0" if $ret_type eq "int";
                 $ret_default = "(void)" if $ret_type eq "void";
                 die("ret_default for $ret_type?") unless length($ret_default);
 
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 cd081e4..0dde934 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
@@ -1696,6 +1696,42 @@
     return 1;
 }
 
+size_t psasim_serialise_psa_export_public_key_iop_t_needs(
+    psa_export_public_key_iop_t value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_psa_export_public_key_iop_t(uint8_t **pos,
+                                                 size_t *remaining,
+                                                 psa_export_public_key_iop_t value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_psa_export_public_key_iop_t(uint8_t **pos,
+                                                   size_t *remaining,
+                                                   psa_export_public_key_iop_t *value)
+{
+    if (*remaining < sizeof(*value)) {
+        return 0;
+    }
+
+    memcpy(value, *pos, sizeof(*value));
+
+    *pos += sizeof(*value);
+    *remaining -= sizeof(*value);
+
+    return 1;
+}
+
 void psa_sim_serialize_reset(void)
 {
     memset(hash_operation_handles, 0,
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 a224d82..3b6f08e 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
@@ -1387,3 +1387,46 @@
 int psasim_deserialise_psa_generate_key_iop_t(uint8_t **pos,
                                               size_t *remaining,
                                               psa_generate_key_iop_t *value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_psa_export_public_key_iop_t()
+ *  to serialise a `psa_export_public_key_iop_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_export_public_key_iop_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_psa_export_public_key_iop_t_needs(
+    psa_export_public_key_iop_t value);
+
+/** Serialise a `psa_export_public_key_iop_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_export_public_key_iop_t(uint8_t **pos,
+                                                 size_t *remaining,
+                                                 psa_export_public_key_iop_t value);
+
+/** Deserialise a `psa_export_public_key_iop_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_export_public_key_iop_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_export_public_key_iop_t(uint8_t **pos,
+                                                   size_t *remaining,
+                                                   psa_export_public_key_iop_t *value);
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 0dba81e..0c9faf4 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
@@ -50,7 +50,8 @@
                psa_verify_hash_interruptible_operation_t
                mbedtls_svc_key_id_t
                psa_key_agreement_iop_t
-               sa_generate_key_iop_t);
+               psa_generate_key_iop_t
+               psa_export_public_key_iop_t);
 
 grep(s/-/ /g, @types);
 
diff --git a/tf-psa-crypto b/tf-psa-crypto
index 2cfed8e..2574203 160000
--- a/tf-psa-crypto
+++ b/tf-psa-crypto
@@ -1 +1 @@
-Subproject commit 2cfed8e711554ffc9432209caa62244938a7da7b
+Subproject commit 25742030e4eddfb29913cb82642703ee0fe5d0d7