Merge pull request #9310 from valeriosetti/psasim_more_aut_tests

psasim: complete support of PSA functions in `psasim` and add basic "smoke test" applications
diff --git a/tests/psa-client-server/psasim/Makefile b/tests/psa-client-server/psasim/Makefile
index a7e22e1..4b0c46e 100644
--- a/tests/psa-client-server/psasim/Makefile
+++ b/tests/psa-client-server/psasim/Makefile
@@ -1,5 +1,3 @@
-MAIN ?= src/client.c
-
 CFLAGS += -Wall -Werror -std=c99 -D_XOPEN_SOURCE=1 -D_POSIX_C_SOURCE=200809L
 
 ifeq ($(DEBUG),1)
@@ -16,11 +14,15 @@
 					include/psa_manifest/pid.h \
 					include/psa_manifest/sid.h
 
-PSA_CLIENT_SRC = src/psa_ff_client.c \
-		 $(MAIN) \
+PSA_CLIENT_COMMON_SRC = src/psa_ff_client.c \
 		 src/psa_sim_crypto_client.c \
 		 src/psa_sim_serialise.c
 
+PSA_CLIENT_BASE_SRC = $(PSA_CLIENT_COMMON_SRC) src/client.c
+
+PSA_CLIENT_FULL_SRC = $(PSA_CLIENT_COMMON_SRC) \
+				$(wildcard src/aut_*.c)
+
 PARTITION_SERVER_BOOTSTRAP = src/psa_ff_bootstrap_TEST_PARTITION.c
 
 PSA_SERVER_SRC = $(PARTITION_SERVER_BOOTSTRAP) \
@@ -35,8 +37,11 @@
 test/seedfile:
 	dd if=/dev/urandom of=./test/seedfile bs=64 count=1
 
-test/psa_client: $(PSA_CLIENT_SRC) $(GENERATED_H_FILES)
-	$(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_SRC) $(LIBPSACLIENT) $(LDFLAGS) -o $@
+test/psa_client_base: $(PSA_CLIENT_BASE_SRC) $(GENERATED_H_FILES)
+	$(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_BASE_SRC) $(LIBPSACLIENT) $(LDFLAGS) -o $@
+
+test/psa_client_full: $(PSA_CLIENT_FULL_SRC) $(GENERATED_H_FILES)
+	$(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_FULL_SRC) $(LIBPSACLIENT) $(LDFLAGS) -o $@
 
 test/psa_partition: $(PSA_SERVER_SRC) $(GENERATED_H_FILES) test/seedfile
 	$(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_SERVER_SRC) $(LIBPSASERVER) $(LDFLAGS) -o $@
@@ -56,7 +61,7 @@
 	$(MAKE) -C $(MBEDTLS_ROOT_PATH) clean
 
 clean:
-	rm -f test/psa_client test/psa_partition
+	rm -f test/psa_client_base test/psa_client_full test/psa_partition
 	rm -f $(PARTITION_SERVER_BOOTSTRAP)
 	rm -rf libpsaclient libpsaserver
 	rm -rf include/psa_manifest
diff --git a/tests/psa-client-server/psasim/src/aut_main.c b/tests/psa-client-server/psasim/src/aut_main.c
new file mode 100644
index 0000000..ed19879
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_main.c
@@ -0,0 +1,71 @@
+/**
+ * This is the base AUT that exectues all other AUTs meant to test PSA APIs
+ * through PSASIM.
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+/* First include Mbed TLS headers to get the Mbed TLS configuration and
+ * platform definitions that we'll use in this program. Also include
+ * standard C headers for functions we'll use here. */
+#include "mbedtls/build_info.h"
+
+#include "psa/crypto.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int psa_hash_compute_main(void);
+int psa_hash_main(void);
+int psa_aead_encrypt_main(char *cipher_name);
+int psa_aead_encrypt_decrypt_main(void);
+int psa_cipher_encrypt_decrypt_main(void);
+int psa_asymmetric_encrypt_decrypt_main(void);
+int psa_random_main(void);
+int psa_mac_main(void);
+int psa_key_agreement_main(void);
+int psa_sign_verify_main(void);
+int psa_hkdf_main(void);
+
+#define TEST_MODULE(main_func) \
+    do {    \
+        char title[128] = { 0 }; \
+        char separator[128] = { 0 }; \
+        int title_len = snprintf(title, sizeof(title), "=== Test: %s ===", #main_func); \
+        memset(separator, '=', title_len); \
+        printf("%s\n%s\n%s\n", separator, title, separator); \
+        ret = main_func; \
+        if (ret != 0) { \
+            goto exit; \
+        } \
+    } while (0)
+
+int main()
+{
+    int ret;
+
+    TEST_MODULE(psa_hash_compute_main());
+    TEST_MODULE(psa_hash_main());
+
+    TEST_MODULE(psa_aead_encrypt_main("aes128-gcm"));
+    TEST_MODULE(psa_aead_encrypt_main("aes256-gcm"));
+    TEST_MODULE(psa_aead_encrypt_main("aes128-gcm_8"));
+    TEST_MODULE(psa_aead_encrypt_main("chachapoly"));
+    TEST_MODULE(psa_aead_encrypt_decrypt_main());
+    TEST_MODULE(psa_cipher_encrypt_decrypt_main());
+    TEST_MODULE(psa_asymmetric_encrypt_decrypt_main());
+
+    TEST_MODULE(psa_random_main());
+
+    TEST_MODULE(psa_mac_main());
+    TEST_MODULE(psa_key_agreement_main());
+    TEST_MODULE(psa_sign_verify_main());
+    TEST_MODULE(psa_hkdf_main());
+
+exit:
+    return (ret != 0) ? 1 : 0;
+}
diff --git a/tests/psa-client-server/psasim/src/aut_psa_aead_demo.c b/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt.c
similarity index 76%
rename from tests/psa-client-server/psasim/src/aut_psa_aead_demo.c
rename to tests/psa-client-server/psasim/src/aut_psa_aead_encrypt.c
index 4a46c40..64463f5 100644
--- a/tests/psa-client-server/psasim/src/aut_psa_aead_demo.c
+++ b/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt.c
@@ -1,37 +1,8 @@
-/**
- * PSA API multi-part AEAD demonstration.
- *
- * This program AEAD-encrypts a message, using the algorithm and key size
- * specified on the command line, using the multi-part API.
- *
- * It comes with a companion program cipher/cipher_aead_demo.c, which does the
- * same operations with the legacy Cipher API. The goal is that comparing the
- * two programs will help people migrating to the PSA Crypto API.
- *
- * When used with multi-part AEAD operations, the `mbedtls_cipher_context`
- * serves a triple purpose (1) hold the key, (2) store the algorithm when no
- * operation is active, and (3) save progress information for the current
- * operation. With PSA those roles are held by disinct objects: (1) a
- * psa_key_id_t to hold the key, a (2) psa_algorithm_t to represent the
- * algorithm, and (3) a psa_operation_t for multi-part progress.
- *
- * On the other hand, with PSA, the algorithms encodes the desired tag length;
- * with Cipher the desired tag length needs to be tracked separately.
- *
- * This program and its companion cipher/cipher_aead_demo.c illustrate this by
- * doing the same sequence of multi-part AEAD computation with both APIs;
- * looking at the two side by side should make the differences and
- * similarities clear.
- */
-
 /*
  *  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-/* First include Mbed TLS headers to get the Mbed TLS configuration and
- * platform definitions that we'll use in this program. Also include
- * standard C headers for functions we'll use here. */
 #include "mbedtls/build_info.h"
 
 #include "psa/crypto.h"
@@ -40,25 +11,6 @@
 #include <stdio.h>
 #include <string.h>
 
-/* If the build options we need are not enabled, compile a placeholder. */
-#if !defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \
-    (!defined(MBEDTLS_PSA_CRYPTO_C) || \
-    !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_GCM_C) || \
-    !defined(MBEDTLS_CHACHAPOLY_C) || \
-    defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER))
-int main(void)
-{
-    printf("MBEDTLS_PSA_CRYPTO_CLIENT or "
-           "MBEDTLS_PSA_CRYPTO_C and/or "
-           "MBEDTLS_AES_C and/or MBEDTLS_GCM_C and/or "
-           "MBEDTLS_CHACHAPOLY_C not defined, and/or "
-           "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined\r\n");
-    return 0;
-}
-#else
-
-/* The real program starts here. */
-
 const char usage[] =
     "Usage: aead_demo [aes128-gcm|aes256-gcm|aes128-gcm_8|chachapoly]";
 
@@ -257,21 +209,15 @@
 /*
  * Main function
  */
-int main(int argc, char **argv)
+int psa_aead_encrypt_main(char *cipher_name)
 {
     psa_status_t status = PSA_SUCCESS;
 
-    /* Check usage */
-    if (argc != 2) {
-        puts(usage);
-        return EXIT_FAILURE;
-    }
-
     /* Initialize the PSA crypto library. */
     PSA_CHECK(psa_crypto_init());
 
     /* Run the demo */
-    PSA_CHECK(aead_demo(argv[1]));
+    PSA_CHECK(aead_demo(cipher_name));
 
     /* Deinitialize the PSA crypto library. */
     mbedtls_psa_crypto_free();
@@ -279,5 +225,3 @@
 exit:
     return status == PSA_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-
-#endif
diff --git a/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt_decrypt.c b/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt_decrypt.c
new file mode 100644
index 0000000..ca090cc
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt_decrypt.c
@@ -0,0 +1,109 @@
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "psa/crypto.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUFFER_SIZE 500
+
+static void print_bytestr(const uint8_t *bytes, size_t len)
+{
+    for (unsigned int idx = 0; idx < len; idx++) {
+        printf("%02X", bytes[idx]);
+    }
+}
+
+int psa_aead_encrypt_decrypt_main(void)
+{
+    psa_status_t status;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_id_t key_id = 0;
+    uint8_t encrypt[BUFFER_SIZE] = { 0 };
+    uint8_t decrypt[BUFFER_SIZE] = { 0 };
+    const uint8_t plaintext[] = "Hello World!";
+    const uint8_t key_bytes[32] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+    uint8_t nonce[PSA_AEAD_NONCE_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CCM)];
+    size_t nonce_length = sizeof(nonce);
+    size_t ciphertext_length;
+    size_t plaintext_length;
+
+    status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        printf("psa_crypto_init failed\n");
+        return EXIT_FAILURE;
+    }
+
+    psa_set_key_usage_flags(&attributes,
+                            PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+    psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
+    psa_set_key_bits(&attributes, 256);
+
+    status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
+    if (status != PSA_SUCCESS) {
+        printf("psa_import_key failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_generate_random(nonce, nonce_length);
+    if (status != PSA_SUCCESS) {
+        printf("psa_generate_random failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_aead_encrypt(key_id,                            // key
+                              PSA_ALG_CCM,                       // algorithm
+                              nonce, nonce_length,               // nonce
+                              NULL, 0,                           // additional data
+                              plaintext, sizeof(plaintext),      // plaintext
+                              encrypt, sizeof(encrypt),          // ciphertext
+                              &ciphertext_length);               // length of output
+    if (status != PSA_SUCCESS) {
+        printf("psa_aead_encrypt failed\n");
+        return EXIT_FAILURE;
+    }
+
+    printf("AES-CCM encryption:\n");
+    printf("- Plaintext: '%s':\n", plaintext);
+    printf("- Key: ");
+    print_bytestr(key_bytes, sizeof(key_bytes));
+    printf("\n- Nonce: ");
+    print_bytestr(nonce, nonce_length);
+    printf("\n- No additional data\n");
+    printf("- Ciphertext:\n");
+
+    for (size_t j = 0; j < ciphertext_length; j++) {
+        if (j % 8 == 0) {
+            printf("\n    ");
+        }
+        printf("%02x ", encrypt[j]);
+    }
+
+    printf("\n");
+
+    status = psa_aead_decrypt(key_id,                       // key
+                              PSA_ALG_CCM,                  // algorithm
+                              nonce, nonce_length,          // nonce
+                              NULL, 0,                      // additional data
+                              encrypt, ciphertext_length,   // ciphertext
+                              decrypt, sizeof(decrypt),     // plaintext
+                              &plaintext_length);           // length of output
+    if (status != PSA_SUCCESS) {
+        printf("psa_aead_decrypt failed\n");
+        return EXIT_FAILURE;
+    }
+
+    if (memcmp(plaintext, decrypt, sizeof(plaintext)) != 0) {
+        printf("\nEncryption/Decryption failed!\n");
+    } else {
+        printf("\nEncryption/Decryption successful!\n");
+    }
+
+    psa_destroy_key(key_id);
+    mbedtls_psa_crypto_free();
+    return 0;
+}
diff --git a/tests/psa-client-server/psasim/src/aut_psa_asymmetric_encrypt_decrypt.c b/tests/psa-client-server/psasim/src/aut_psa_asymmetric_encrypt_decrypt.c
new file mode 100644
index 0000000..02d8cf4
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_asymmetric_encrypt_decrypt.c
@@ -0,0 +1,81 @@
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "psa/crypto.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define KEY_BITS        4096
+#define BUFFER_SIZE     PSA_BITS_TO_BYTES(KEY_BITS)
+
+static void print_bytestr(const uint8_t *bytes, size_t len)
+{
+    for (unsigned int idx = 0; idx < len; idx++) {
+        printf("%02X", bytes[idx]);
+    }
+}
+
+int psa_asymmetric_encrypt_decrypt_main(void)
+{
+    psa_status_t status;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_id_t key_id = 0;
+    uint8_t original[BUFFER_SIZE/2] = { 0 };
+    uint8_t encrypt[BUFFER_SIZE] = { 0 };
+    uint8_t decrypt[BUFFER_SIZE] = { 0 };
+    size_t encrypted_length;
+    size_t decrypted_length;
+
+    status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        printf("psa_crypto_init failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_generate_random(original, sizeof(original));
+    if (status != PSA_SUCCESS) {
+        printf("psa_generate_random() failed\n");
+        return EXIT_FAILURE;
+    }
+
+    psa_set_key_usage_flags(&attributes,
+                            PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+    psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
+    psa_set_key_bits(&attributes, KEY_BITS);
+
+    status = psa_generate_key(&attributes, &key_id);
+    if (status != PSA_SUCCESS) {
+        printf("psa_generate_key failed (%d)\n", status);
+        return EXIT_FAILURE;
+    }
+
+    status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+                                    original, sizeof(original), NULL, 0,
+                                    encrypt, sizeof(encrypt), &encrypted_length);
+    if (status != PSA_SUCCESS) {
+        printf("psa_asymmetric_encrypt failed (%d)\n", status);
+        return EXIT_FAILURE;
+    }
+
+    status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+                                    encrypt, encrypted_length, NULL, 0,
+                                    decrypt, sizeof(decrypt), &decrypted_length);
+    if (status != PSA_SUCCESS) {
+        printf("psa_cipher_decrypt failed (%d)\n", status);
+        return EXIT_FAILURE;
+    }
+
+    if (memcmp(original, decrypt, sizeof(original)) != 0) {
+        printf("\nEncryption/Decryption failed!\n");
+    } else {
+        printf("\nEncryption/Decryption successful!\n");
+    }
+
+    psa_destroy_key(key_id);
+    mbedtls_psa_crypto_free();
+    return 0;
+}
diff --git a/tests/psa-client-server/psasim/src/aut_psa_cipher_encrypt_decrypt.c b/tests/psa-client-server/psasim/src/aut_psa_cipher_encrypt_decrypt.c
new file mode 100644
index 0000000..a923feb
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_cipher_encrypt_decrypt.c
@@ -0,0 +1,81 @@
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "psa/crypto.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUFFER_SIZE 4096
+
+static void print_bytestr(const uint8_t *bytes, size_t len)
+{
+    for (unsigned int idx = 0; idx < len; idx++) {
+        printf("%02X", bytes[idx]);
+    }
+}
+
+int psa_cipher_encrypt_decrypt_main(void)
+{
+    psa_status_t status;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_id_t key_id = 0;
+    uint8_t original[BUFFER_SIZE] = { 0 };
+    uint8_t encrypt[BUFFER_SIZE] = { 0 };
+    uint8_t decrypt[BUFFER_SIZE] = { 0 };
+    const uint8_t key_bytes[32] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+    size_t encrypted_length;
+    size_t decrypted_length;
+
+    status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        printf("psa_crypto_init failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_generate_random(original, sizeof(original));
+    if (status != PSA_SUCCESS) {
+        printf("psa_generate_random() failed\n");
+        return EXIT_FAILURE;
+    }
+
+    psa_set_key_usage_flags(&attributes,
+                            PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+    psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING);
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
+    psa_set_key_bits(&attributes, 256);
+
+    status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
+    if (status != PSA_SUCCESS) {
+        printf("psa_import_key failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
+                                original, sizeof(original),
+                                encrypt, sizeof(encrypt), &encrypted_length);
+    if (status != PSA_SUCCESS) {
+        printf("psa_cipher_encrypt failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_cipher_decrypt(key_id, PSA_ALG_ECB_NO_PADDING,
+                                encrypt, encrypted_length,
+                                decrypt, sizeof(decrypt), &decrypted_length);
+    if (status != PSA_SUCCESS) {
+        printf("psa_cipher_decrypt failed\n");
+        return EXIT_FAILURE;
+    }
+
+    if (memcmp(original, decrypt, sizeof(original)) != 0) {
+        printf("\nEncryption/Decryption failed!\n");
+    } else {
+        printf("\nEncryption/Decryption successful!\n");
+    }
+
+    psa_destroy_key(key_id);
+    mbedtls_psa_crypto_free();
+    return 0;
+}
diff --git a/tests/psa-client-server/psasim/src/aut_psa_hash.c b/tests/psa-client-server/psasim/src/aut_psa_hash.c
index 6c2c07e..0446e7a 100644
--- a/tests/psa-client-server/psasim/src/aut_psa_hash.c
+++ b/tests/psa-client-server/psasim/src/aut_psa_hash.c
@@ -1,13 +1,4 @@
 /*
- *  Example computing a SHA-256 hash using the PSA Crypto API
- *
- *  The example computes the SHA-256 hash of a test string using the
- *  one-shot API call psa_hash_compute() and the using multi-part
- *  operation, which requires psa_hash_setup(), psa_hash_update() and
- *  psa_hash_finish(). The multi-part operation is popular on embedded
- *  devices where a rolling hash needs to be computed.
- *
- *
  *  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
@@ -20,33 +11,13 @@
 #include "mbedtls/build_info.h"
 #include "mbedtls/platform.h"
 
-/* Information about hashing with the PSA API can be
- * found here:
- * https://arm-software.github.io/psa-api/crypto/1.1/api/ops/hashes.html
- *
- * The algorithm used by this demo is SHA 256.
- * Please see include/psa/crypto_values.h to see the other
- * algorithms that are supported by Mbed TLS.
- * If you switch to a different algorithm you will need to update
- * the hash data in the EXAMPLE_HASH_VALUE macro below. */
-
-#if !defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \
-    (!defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256))
-int main(void)
-{
-    mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256"
-                   "not defined, and not MBEDTLS_PSA_CRYPTO_CLIENT.\r\n");
-    return EXIT_SUCCESS;
-}
-#else
-
 #define HASH_ALG PSA_ALG_SHA_256
 
-const uint8_t sample_message[] = "Hello World!";
+static const uint8_t sample_message[] = "Hello World!";
 /* sample_message is terminated with a null byte which is not part of
  * the message itself so we make sure to subtract it in order to get
  * the message length. */
-const size_t sample_message_length = sizeof(sample_message) - 1;
+static const size_t sample_message_length = sizeof(sample_message) - 1;
 
 #define EXPECTED_HASH_VALUE {                                                    \
         0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \
@@ -54,10 +25,10 @@
         0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \
 }
 
-const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
-const size_t expected_hash_len = sizeof(expected_hash);
+static const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
+static const size_t expected_hash_len = sizeof(expected_hash);
 
-int main(void)
+int psa_hash_main(void)
 {
     psa_status_t status;
     uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)];
@@ -157,4 +128,3 @@
     psa_hash_abort(&cloned_hash_operation);
     return EXIT_FAILURE;
 }
-#endif /* !MBEDTLS_PSA_CRYPTO_C || !PSA_WANT_ALG_SHA_256 */
diff --git a/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c b/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c
index 70c3e5b..959e0c3 100644
--- a/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c
+++ b/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c
@@ -1,15 +1,4 @@
 /*
- *  API(s) under test: psa_hash_compute()
- *
- *  Taken from programs/psa/psa_hash.c, and calls to all hash APIs
- *  but psa_hash_compute() removed.
- *
- *  Example computing a SHA-256 hash using the PSA Crypto API
- *
- *  The example computes the SHA-256 hash of a test string using the
- *  one-shot API call psa_hash_compute().
- *
- *
  *  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
@@ -22,33 +11,13 @@
 #include "mbedtls/build_info.h"
 #include "mbedtls/platform.h"
 
-/* Information about hashing with the PSA API can be
- * found here:
- * https://arm-software.github.io/psa-api/crypto/1.1/api/ops/hashes.html
- *
- * The algorithm used by this demo is SHA 256.
- * Please see include/psa/crypto_values.h to see the other
- * algorithms that are supported by Mbed TLS.
- * If you switch to a different algorithm you will need to update
- * the hash data in the EXAMPLE_HASH_VALUE macro below. */
-
-#if !defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \
-    (!defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256))
-int main(void)
-{
-    mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256"
-                   "not defined, and not MBEDTLS_PSA_CRYPTO_CLIENT.\r\n");
-    return EXIT_SUCCESS;
-}
-#else
-
 #define HASH_ALG PSA_ALG_SHA_256
 
-const uint8_t sample_message[] = "Hello World!";
+static const uint8_t sample_message[] = "Hello World!";
 /* sample_message is terminated with a null byte which is not part of
  * the message itself so we make sure to subtract it in order to get
  * the message length. */
-const size_t sample_message_length = sizeof(sample_message) - 1;
+static const size_t sample_message_length = sizeof(sample_message) - 1;
 
 #define EXPECTED_HASH_VALUE {                                                    \
         0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \
@@ -56,10 +25,10 @@
         0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \
 }
 
-const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
-const size_t expected_hash_len = sizeof(expected_hash);
+static const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
+static const size_t expected_hash_len = sizeof(expected_hash);
 
-int main(void)
+int psa_hash_compute_main(void)
 {
     psa_status_t status;
     uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)];
@@ -110,4 +79,3 @@
 cleanup:
     return EXIT_FAILURE;
 }
-#endif /* !MBEDTLS_PSA_CRYPTO_C || !PSA_WANT_ALG_SHA_256 */
diff --git a/tests/psa-client-server/psasim/src/aut_psa_hkdf.c b/tests/psa-client-server/psasim/src/aut_psa_hkdf.c
new file mode 100644
index 0000000..891fdb3
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_hkdf.c
@@ -0,0 +1,121 @@
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "psa/crypto.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mbedtls/build_info.h"
+
+int psa_hkdf_main(void)
+{
+    psa_status_t status;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_id_t key_id = 0;
+    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+
+    /* Example test vector from RFC 5869 */
+
+    /* Input keying material (IKM) */
+    unsigned char ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+                            0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
+
+    unsigned char salt[] =
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
+
+    /* Context and application specific information, which can be of zero length */
+    unsigned char info[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 };
+
+    /* Expected OKM based on the RFC 5869-provided test vector */
+    unsigned char expected_okm[] = { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43,
+                                     0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90,
+                                     0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4,
+                                     0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
+                                     0x58, 0x65 };
+
+    /* The output size of the HKDF function depends on the hash function used.
+     * In our case we use SHA-256, which produces a 32 byte fingerprint.
+     * Therefore, we allocate a buffer of 32 bytes to hold the output keying
+     * material (OKM).
+     */
+    unsigned char output[32];
+
+    psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
+
+    printf("PSA Crypto API: HKDF SHA-256 example\n\n");
+
+    status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        printf("psa_crypto_init failed\n");
+        return EXIT_FAILURE;
+    }
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
+    psa_set_key_algorithm(&attributes, PSA_ALG_HKDF(PSA_ALG_SHA_256));
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
+
+    status = psa_import_key(&attributes, ikm, sizeof(ikm), &key_id);
+    if (status != PSA_SUCCESS) {
+        printf("psa_import_key failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_key_derivation_setup(&operation, alg);
+    if (status != PSA_SUCCESS) {
+        printf("psa_key_derivation_setup failed");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT,
+                                            salt, sizeof(salt));
+    if (status != PSA_SUCCESS) {
+        printf("psa_key_derivation_input_bytes (salt) failed");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_key_derivation_input_key(&operation, PSA_KEY_DERIVATION_INPUT_SECRET,
+                                          key_id);
+    if (status != PSA_SUCCESS) {
+        printf("psa_key_derivation_input_key failed");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_INFO,
+                                            info, sizeof(info));
+    if (status != PSA_SUCCESS) {
+        printf("psa_key_derivation_input_bytes (info) failed");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_key_derivation_output_bytes(&operation, output, sizeof(output));
+    if (status != PSA_SUCCESS) {
+        printf("psa_key_derivation_output_bytes failed");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_key_derivation_abort(&operation);
+    if (status != PSA_SUCCESS) {
+        printf("psa_key_derivation_abort failed");
+        return EXIT_FAILURE;
+    }
+
+    printf("OKM: \n");
+
+    for (size_t j = 0; j < sizeof(output); j++) {
+        if (output[j] != expected_okm[j]) {
+            printf("\n --- Unexpected outcome!\n");
+            return EXIT_FAILURE;
+        }
+
+        if (j % 8 == 0) {
+            printf("\n    ");
+        }
+        printf("%02x ", output[j]);
+    }
+
+    printf("\n");
+    mbedtls_psa_crypto_free();
+    return EXIT_SUCCESS;
+}
diff --git a/tests/psa-client-server/psasim/src/aut_psa_key_agreement.c b/tests/psa-client-server/psasim/src/aut_psa_key_agreement.c
new file mode 100644
index 0000000..4a0aab1
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_key_agreement.c
@@ -0,0 +1,146 @@
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+
+#include "psa/crypto.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mbedtls/build_info.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/platform.h"
+
+#define BUFFER_SIZE 500
+
+#define SERVER_PK_VALUE {                                     \
+        0x04, 0xde, 0xa5, 0xe4, 0x5d, 0x0e, 0xa3, 0x7f, 0xc5, \
+        0x66, 0x23, 0x2a, 0x50, 0x8f, 0x4a, 0xd2, 0x0e, 0xa1, \
+        0x3d, 0x47, 0xe4, 0xbf, 0x5f, 0xa4, 0xd5, 0x4a, 0x57, \
+        0xa0, 0xba, 0x01, 0x20, 0x42, 0x08, 0x70, 0x97, 0x49, \
+        0x6e, 0xfc, 0x58, 0x3f, 0xed, 0x8b, 0x24, 0xa5, 0xb9, \
+        0xbe, 0x9a, 0x51, 0xde, 0x06, 0x3f, 0x5a, 0x00, 0xa8, \
+        0xb6, 0x98, 0xa1, 0x6f, 0xd7, 0xf2, 0x9b, 0x54, 0x85, \
+        0xf3, 0x20                                            \
+}
+
+#define KEY_BITS 256
+
+int psa_key_agreement_main(void)
+{
+    psa_status_t status;
+    psa_key_attributes_t client_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t server_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_id_t client_key_id = 0;
+    psa_key_id_t server_key_id = 0;
+    uint8_t client_pk[BUFFER_SIZE] = { 0 };
+    size_t client_pk_len;
+    size_t key_bits;
+    psa_key_type_t key_type;
+
+    const uint8_t server_pk[] = SERVER_PK_VALUE;
+    uint8_t derived_key[BUFFER_SIZE] = { 0 };
+    size_t derived_key_len;
+
+    status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_crypto_init failed\n");
+        return EXIT_FAILURE;
+    }
+
+    psa_set_key_usage_flags(&client_attributes, PSA_KEY_USAGE_DERIVE);
+    psa_set_key_algorithm(&client_attributes, PSA_ALG_ECDH);
+    psa_set_key_type(&client_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+    psa_set_key_bits(&client_attributes, KEY_BITS);
+
+    /* Generate ephemeral key pair */
+    status = psa_generate_key(&client_attributes, &client_key_id);
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_generate_key failed\n");
+        return EXIT_FAILURE;
+    }
+    status = psa_export_public_key(client_key_id,
+                                   client_pk, sizeof(client_pk),
+                                   &client_pk_len);
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_export_public_key failed\n");
+        return EXIT_FAILURE;
+    }
+
+    mbedtls_printf("Client Public Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", client_pk_len);
+
+    for (size_t j = 0; j < client_pk_len; j++) {
+        if (j % 8 == 0) {
+            mbedtls_printf("\n    ");
+        }
+        mbedtls_printf("%02x ", client_pk[j]);
+    }
+    mbedtls_printf("\n\n");
+
+    psa_set_key_usage_flags(&server_attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
+    psa_set_key_algorithm(&server_attributes, PSA_ALG_ECDSA_ANY);
+    psa_set_key_type(&server_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
+
+    /* Import server public key */
+    status = psa_import_key(&server_attributes, server_pk, sizeof(server_pk), &server_key_id);
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_import_key failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_get_key_attributes(server_key_id, &check_attributes);
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_get_key_attributes failed\n");
+        return EXIT_FAILURE;
+    }
+
+    key_bits = psa_get_key_bits(&check_attributes);
+    if (key_bits != 256) {
+        mbedtls_printf("Incompatible key size!\n");
+        return EXIT_FAILURE;
+    }
+
+    key_type = psa_get_key_type(&check_attributes);
+    if (key_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) {
+        mbedtls_printf("Unsupported key type!\n");
+        return EXIT_FAILURE;
+    }
+
+    mbedtls_printf("Server Public Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", sizeof(server_pk));
+
+    for (size_t j = 0; j < sizeof(server_pk); j++) {
+        if (j % 8 == 0) {
+            mbedtls_printf("\n    ");
+        }
+        mbedtls_printf("%02x ", server_pk[j]);
+    }
+    mbedtls_printf("\n\n");
+
+    /* Generate ECDHE derived key */
+    status = psa_raw_key_agreement(PSA_ALG_ECDH,                        // algorithm
+                                   client_key_id,                   // client secret key
+                                   server_pk, sizeof(server_pk),        // server public key
+                                   derived_key, sizeof(derived_key),    // buffer to store derived key
+                                   &derived_key_len);
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_raw_key_agreement failed\n");
+        return EXIT_FAILURE;
+    }
+
+    mbedtls_printf("Derived Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", derived_key_len);
+
+    for (size_t j = 0; j < derived_key_len; j++) {
+        if (j % 8 == 0) {
+            mbedtls_printf("\n    ");
+        }
+        mbedtls_printf("%02x ", derived_key[j]);
+    }
+    mbedtls_printf("\n");
+
+    psa_destroy_key(server_key_id);
+    psa_destroy_key(client_key_id);
+    mbedtls_psa_crypto_free();
+    return EXIT_SUCCESS;
+}
diff --git a/tests/psa-client-server/psasim/src/aut_psa_mac.c b/tests/psa-client-server/psasim/src/aut_psa_mac.c
new file mode 100644
index 0000000..18b4b57
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_mac.c
@@ -0,0 +1,162 @@
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "psa/crypto.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mbedtls/build_info.h"
+
+/* constant-time buffer comparison */
+static inline int safer_memcmp(const void *a, const void *b, size_t n)
+{
+    size_t i;
+    volatile const unsigned char *A = (volatile const unsigned char *) a;
+    volatile const unsigned char *B = (volatile const unsigned char *) b;
+    volatile unsigned char diff = 0;
+
+    for (i = 0; i < n; i++) {
+        /* Read volatile data in order before computing diff.
+         * This avoids IAR compiler warning:
+         * 'the order of volatile accesses is undefined ..' */
+        unsigned char x = A[i], y = B[i];
+        diff |= x ^ y;
+    }
+
+    return diff;
+}
+
+
+int psa_mac_main(void)
+{
+    uint8_t input[] = "Hello World!";
+    psa_status_t status;
+    size_t mac_size_real = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_id_t key_id = 0;
+    uint8_t mac[PSA_MAC_MAX_SIZE];
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    const uint8_t key_bytes[16] = "kkkkkkkkkkkkkkkk";
+    const uint8_t mbedtls_test_hmac_sha256[] = {
+        0xae, 0x72, 0x34, 0x5a, 0x10, 0x36, 0xfb, 0x71,
+        0x35, 0x3c, 0x7d, 0x6c, 0x81, 0x98, 0x52, 0x86,
+        0x00, 0x4a, 0x43, 0x7c, 0x2d, 0xb3, 0x1a, 0xd8,
+        0x67, 0xb1, 0xad, 0x11, 0x4d, 0x18, 0x49, 0x8b
+    };
+
+    status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        printf("psa_crypto_init failed\n");
+        return EXIT_FAILURE;
+    }
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE |
+                            PSA_KEY_USAGE_SIGN_HASH |
+                            PSA_KEY_USAGE_SIGN_MESSAGE);
+    psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256));
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
+
+    status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
+    if (status != PSA_SUCCESS) {
+        printf("psa_import_key failed\n");
+        return EXIT_FAILURE;
+    }
+
+    /* Single-part MAC operation with psa_mac_compute() */
+    status = psa_mac_compute(key_id,
+                             PSA_ALG_HMAC(PSA_ALG_SHA_256),
+                             input,
+                             sizeof(input),
+                             mac,
+                             sizeof(mac),
+                             &mac_size_real);
+    if (status != PSA_SUCCESS) {
+        printf("psa_mac_compute failed\n");
+        return EXIT_FAILURE;
+    }
+
+    printf("HMAC-SHA-256(%s) with psa_mac_compute():\n", input);
+
+    for (size_t j = 0; j < mac_size_real; j++) {
+        if (j % 8 == 0) {
+            printf("\n    ");
+        }
+        printf("%02x ", mac[j]);
+    }
+
+    printf("\n");
+
+    if (safer_memcmp(mac,
+                     mbedtls_test_hmac_sha256,
+                     mac_size_real
+                     ) != 0) {
+        printf("\nMAC verified incorrectly!\n");
+    } else {
+        printf("\nMAC verified correctly!\n");
+    }
+
+    psa_destroy_key(key_id);
+
+    status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
+    if (status != PSA_SUCCESS) {
+        printf("psa_import_key failed\n");
+        return EXIT_FAILURE;
+    }
+
+    /* Single-part MAC operation with psa_mac_verify() */
+    status = psa_mac_verify(key_id,
+                            PSA_ALG_HMAC(PSA_ALG_SHA_256),
+                            input,
+                            sizeof(input),
+                            mbedtls_test_hmac_sha256,
+                            sizeof(mbedtls_test_hmac_sha256));
+    if (status != PSA_SUCCESS) {
+        printf("psa_mac_verify failed\n");
+        return EXIT_FAILURE;
+    } else {
+        printf("psa_mac_verify passed successfully\n");
+    }
+
+    psa_destroy_key(key_id);
+
+    status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
+    if (status != PSA_SUCCESS) {
+        printf("psa_import_key failed\n");
+        return EXIT_FAILURE;
+    }
+
+    /* Multi-part MAC operation */
+    status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256));
+    if (status != PSA_SUCCESS) {
+        printf("psa_mac_sign_setup failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_mac_update(&operation, input, sizeof(input));
+    if (status != PSA_SUCCESS) {
+        printf("psa_mac_update failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_mac_sign_finish(&operation, mac, sizeof(mac), &mac_size_real);
+    if (status != PSA_SUCCESS) {
+        printf("psa_mac_sign_finish failed\n");
+        return EXIT_FAILURE;
+    }
+
+    if (safer_memcmp(mac,
+                     mbedtls_test_hmac_sha256,
+                     mac_size_real
+                     ) != 0) {
+        printf("MAC, calculated with multi-part MAC operation, verified incorrectly!\n");
+    } else {
+        printf("MAC, calculated with multi-part MAC operation, verified correctly!\n");
+    }
+
+    psa_destroy_key(key_id);
+    mbedtls_psa_crypto_free();
+    return EXIT_SUCCESS;
+}
diff --git a/tests/psa-client-server/psasim/src/aut_psa_random.c b/tests/psa-client-server/psasim/src/aut_psa_random.c
new file mode 100644
index 0000000..5880c4d
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_random.c
@@ -0,0 +1,47 @@
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "mbedtls/build_info.h"
+
+#include <psa/crypto.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mbedtls/entropy.h"
+
+#define BUFFER_SIZE 100
+
+int psa_random_main(void)
+{
+    psa_status_t status;
+    uint8_t output[BUFFER_SIZE] = { 0 };
+
+    status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        printf("psa_crypto_init failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_generate_random(output, BUFFER_SIZE);
+    if (status != PSA_SUCCESS) {
+        printf("psa_generate_random failed\n");
+        return EXIT_FAILURE;
+    }
+
+    printf("Random bytes generated:\n");
+
+    for (size_t j = 0; j < BUFFER_SIZE; j++) {
+        if (j % 8 == 0) {
+            printf("\n    ");
+        }
+        printf("%02x ", output[j]);
+    }
+
+    printf("\n");
+
+    mbedtls_psa_crypto_free();
+    return 0;
+}
diff --git a/tests/psa-client-server/psasim/src/aut_psa_sign_verify.c b/tests/psa-client-server/psasim/src/aut_psa_sign_verify.c
new file mode 100644
index 0000000..98df9e5
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_sign_verify.c
@@ -0,0 +1,93 @@
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+
+#include "psa/crypto.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mbedtls/build_info.h"
+#include "mbedtls/platform.h"
+
+#define KEY_BYTES_VALUE {                                                       \
+        0x49, 0xc9, 0xa8, 0xc1, 0x8c, 0x4b, 0x88, 0x56, 0x38, 0xc4, 0x31, 0xcf, \
+        0x1d, 0xf1, 0xc9, 0x94, 0x13, 0x16, 0x09, 0xb5, 0x80, 0xd4, 0xfd, 0x43, \
+        0xa0, 0xca, 0xb1, 0x7d, 0xb2, 0xf1, 0x3e, 0xee                          \
+}
+
+#define PLAINTEXT_VALUE "Hello World!"
+
+/* SHA-256(plaintext) */
+#define HASH_VALUE {                                                            \
+        0x5a, 0x09, 0xe8, 0xfa, 0x9c, 0x77, 0x80, 0x7b, 0x24, 0xe9, 0x9c, 0x9c, \
+        0xf9, 0x99, 0xde, 0xbf, 0xad, 0x84, 0x41, 0xe2, 0x69, 0xeb, 0x96, 0x0e, \
+        0x20, 0x1f, 0x61, 0xfc, 0x3d, 0xe2, 0x0d, 0x5a                          \
+}
+
+int psa_sign_verify_main(void)
+{
+    psa_status_t status;
+    psa_key_id_t key_id = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    uint8_t signature[PSA_SIGNATURE_MAX_SIZE] = { 0 };
+    size_t signature_length;
+    const uint8_t key_bytes[] = KEY_BYTES_VALUE;
+    const uint8_t plaintext[] = PLAINTEXT_VALUE;
+    const uint8_t hash[] = HASH_VALUE;
+
+    status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_crypto_init failed\n");
+        return EXIT_FAILURE;
+    }
+
+    psa_set_key_usage_flags(&attributes,
+                            PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+
+    status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id);
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_import_key failed\n");
+        return EXIT_FAILURE;
+    }
+
+    status = psa_sign_hash(key_id,                          // key handle
+                           PSA_ALG_ECDSA(PSA_ALG_SHA_256),  // signature algorithm
+                           hash, sizeof(hash),              // hash of the message
+                           signature, sizeof(signature),    // signature (as output)
+                           &signature_length);              // length of signature output
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_sign_hash failed\n");
+        return EXIT_FAILURE;
+    }
+
+    mbedtls_printf("ECDSA-SHA256 signature of SHA-256('%s'):\n", plaintext);
+
+    for (size_t j = 0; j < signature_length; j++) {
+        if (j % 8 == 0) {
+            mbedtls_printf("\n    ");
+        }
+        mbedtls_printf("%02x ", signature[j]);
+    }
+
+    mbedtls_printf("\n");
+
+    status = psa_verify_hash(key_id,                          // key handle
+                             PSA_ALG_ECDSA(PSA_ALG_SHA_256),  // signature algorithm
+                             hash, sizeof(hash),              // hash of message
+                             signature, signature_length);    // signature
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_verify_hash failed\n");
+        return EXIT_FAILURE;
+    } else {
+        mbedtls_printf("\nSignature verification successful!\n");
+    }
+
+    psa_destroy_key(key_id);
+    mbedtls_psa_crypto_free();
+    return EXIT_SUCCESS;
+}
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 c68b416..bc1b844 100644
--- a/tests/psa-client-server/psasim/src/psa_functions_codes.h
+++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h
@@ -24,7 +24,24 @@
     PSA_AEAD_UPDATE,
     PSA_AEAD_UPDATE_AD,
     PSA_AEAD_VERIFY,
+    PSA_ASYMMETRIC_DECRYPT,
+    PSA_ASYMMETRIC_ENCRYPT,
+    PSA_CIPHER_ABORT,
+    PSA_CIPHER_DECRYPT,
+    PSA_CIPHER_DECRYPT_SETUP,
+    PSA_CIPHER_ENCRYPT,
+    PSA_CIPHER_ENCRYPT_SETUP,
+    PSA_CIPHER_FINISH,
+    PSA_CIPHER_GENERATE_IV,
+    PSA_CIPHER_SET_IV,
+    PSA_CIPHER_UPDATE,
+    PSA_COPY_KEY,
     PSA_DESTROY_KEY,
+    PSA_EXPORT_KEY,
+    PSA_EXPORT_PUBLIC_KEY,
+    PSA_GENERATE_KEY,
+    PSA_GENERATE_KEY_EXT,
+    PSA_GENERATE_RANDOM,
     PSA_GET_KEY_ATTRIBUTES,
     PSA_HASH_ABORT,
     PSA_HASH_CLONE,
@@ -35,6 +52,42 @@
     PSA_HASH_UPDATE,
     PSA_HASH_VERIFY,
     PSA_IMPORT_KEY,
+    PSA_INTERRUPTIBLE_GET_MAX_OPS,
+    PSA_INTERRUPTIBLE_SET_MAX_OPS,
+    PSA_KEY_DERIVATION_ABORT,
+    PSA_KEY_DERIVATION_GET_CAPACITY,
+    PSA_KEY_DERIVATION_INPUT_BYTES,
+    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,
+    PSA_MAC_SIGN_SETUP,
+    PSA_MAC_UPDATE,
+    PSA_MAC_VERIFY,
+    PSA_MAC_VERIFY_FINISH,
+    PSA_MAC_VERIFY_SETUP,
+    PSA_PURGE_KEY,
+    PSA_RAW_KEY_AGREEMENT,
+    PSA_RESET_KEY_ATTRIBUTES,
+    PSA_SIGN_HASH,
+    PSA_SIGN_HASH_ABORT,
+    PSA_SIGN_HASH_COMPLETE,
+    PSA_SIGN_HASH_GET_NUM_OPS,
+    PSA_SIGN_HASH_START,
+    PSA_SIGN_MESSAGE,
+    PSA_VERIFY_HASH,
+    PSA_VERIFY_HASH_ABORT,
+    PSA_VERIFY_HASH_COMPLETE,
+    PSA_VERIFY_HASH_GET_NUM_OPS,
+    PSA_VERIFY_HASH_START,
+    PSA_VERIFY_MESSAGE,
 };
 
 #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 758e9b2..28dff38 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
@@ -129,40 +129,43 @@
     psa_aead_operation_t *operation
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_ABORT,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_ABORT server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -170,19 +173,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -198,70 +205,85 @@
     size_t *plaintext_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_mbedtls_svc_key_id_t_needs(key) +
-                    psasim_serialise_psa_algorithm_t_needs(alg) +
-                    psasim_serialise_buffer_needs(nonce, nonce_length) +
-                    psasim_serialise_buffer_needs(additional_data, additional_data_length) +
-                    psasim_serialise_buffer_needs(ciphertext, ciphertext_length) +
-                    psasim_serialise_buffer_needs(plaintext, plaintext_size) +
-                    psasim_serialise_size_t_needs(*plaintext_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(nonce, nonce_length) +
+        psasim_serialise_buffer_needs(additional_data, additional_data_length) +
+        psasim_serialise_buffer_needs(ciphertext, ciphertext_length) +
+        psasim_serialise_buffer_needs(plaintext, plaintext_size) +
+        psasim_serialise_size_t_needs(*plaintext_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    uint8_t *pos = ser_params;
     size_t remaining = needed;
     int ok;
     ok = psasim_serialise_begin(&pos, &remaining);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key);
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, nonce, nonce_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        nonce, nonce_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, additional_data, additional_data_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        additional_data, additional_data_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, ciphertext, ciphertext_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        ciphertext, ciphertext_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, plaintext, plaintext_size);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        plaintext, plaintext_size);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, *plaintext_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *plaintext_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_DECRYPT,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_DECRYPT server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -269,24 +291,30 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, plaintext, plaintext_size);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        plaintext, plaintext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&rpos, &rremain, plaintext_length);
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        plaintext_length);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -298,50 +326,57 @@
     psa_algorithm_t alg
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation) +
-                    psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
-                    psasim_serialise_psa_algorithm_t_needs(alg);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key);
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_DECRYPT_SETUP,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_DECRYPT_SETUP server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -349,19 +384,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -377,70 +416,85 @@
     size_t *ciphertext_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_mbedtls_svc_key_id_t_needs(key) +
-                    psasim_serialise_psa_algorithm_t_needs(alg) +
-                    psasim_serialise_buffer_needs(nonce, nonce_length) +
-                    psasim_serialise_buffer_needs(additional_data, additional_data_length) +
-                    psasim_serialise_buffer_needs(plaintext, plaintext_length) +
-                    psasim_serialise_buffer_needs(ciphertext, ciphertext_size) +
-                    psasim_serialise_size_t_needs(*ciphertext_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(nonce, nonce_length) +
+        psasim_serialise_buffer_needs(additional_data, additional_data_length) +
+        psasim_serialise_buffer_needs(plaintext, plaintext_length) +
+        psasim_serialise_buffer_needs(ciphertext, ciphertext_size) +
+        psasim_serialise_size_t_needs(*ciphertext_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    uint8_t *pos = ser_params;
     size_t remaining = needed;
     int ok;
     ok = psasim_serialise_begin(&pos, &remaining);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key);
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, nonce, nonce_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        nonce, nonce_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, additional_data, additional_data_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        additional_data, additional_data_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, plaintext, plaintext_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        plaintext, plaintext_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, ciphertext, ciphertext_size);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        ciphertext, ciphertext_size);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, *ciphertext_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *ciphertext_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_ENCRYPT,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_ENCRYPT server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -448,24 +502,30 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, ciphertext, ciphertext_size);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        ciphertext, ciphertext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&rpos, &rremain, ciphertext_length);
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        ciphertext_length);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -477,50 +537,57 @@
     psa_algorithm_t alg
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation) +
-                    psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
-                    psasim_serialise_psa_algorithm_t_needs(alg);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key);
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_ENCRYPT_SETUP,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_ENCRYPT_SETUP server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -528,19 +595,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -554,60 +625,71 @@
     size_t *tag_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation) +
-                    psasim_serialise_buffer_needs(ciphertext, ciphertext_size) +
-                    psasim_serialise_size_t_needs(*ciphertext_length) +
-                    psasim_serialise_buffer_needs(tag, tag_size) +
-                    psasim_serialise_size_t_needs(*tag_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(ciphertext, ciphertext_size) +
+        psasim_serialise_size_t_needs(*ciphertext_length) +
+        psasim_serialise_buffer_needs(tag, tag_size) +
+        psasim_serialise_size_t_needs(*tag_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, ciphertext, ciphertext_size);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        ciphertext, ciphertext_size);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, *ciphertext_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *ciphertext_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, tag, tag_size);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        tag, tag_size);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, *tag_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *tag_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_FINISH,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_FINISH server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -615,39 +697,51 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, ciphertext, ciphertext_size);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        ciphertext, ciphertext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&rpos, &rremain, ciphertext_length);
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        ciphertext_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, tag, tag_size);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        tag, tag_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&rpos, &rremain, tag_length);
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        tag_length);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -659,50 +753,57 @@
     size_t *nonce_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation) +
-                    psasim_serialise_buffer_needs(nonce, nonce_size) +
-                    psasim_serialise_size_t_needs(*nonce_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(nonce, nonce_size) +
+        psasim_serialise_size_t_needs(*nonce_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, nonce, nonce_size);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        nonce, nonce_size);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, *nonce_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *nonce_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_GENERATE_NONCE,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_GENERATE_NONCE server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -710,29 +811,37 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, nonce, nonce_size);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        nonce, nonce_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&rpos, &rremain, nonce_length);
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        nonce_length);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -744,50 +853,57 @@
     size_t plaintext_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation) +
-                    psasim_serialise_size_t_needs(ad_length) +
-                    psasim_serialise_size_t_needs(plaintext_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation) +
+        psasim_serialise_size_t_needs(ad_length) +
+        psasim_serialise_size_t_needs(plaintext_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, ad_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        ad_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, plaintext_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        plaintext_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_SET_LENGTHS,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_SET_LENGTHS server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -795,19 +911,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -818,45 +938,50 @@
     const uint8_t *nonce, size_t  nonce_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation) +
-                    psasim_serialise_buffer_needs(nonce, nonce_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(nonce, nonce_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, nonce, nonce_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        nonce, nonce_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_SET_NONCE,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_SET_NONCE server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -864,19 +989,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -889,55 +1018,64 @@
     size_t *output_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation) +
-                    psasim_serialise_buffer_needs(input, input_length) +
-                    psasim_serialise_buffer_needs(output, output_size) +
-                    psasim_serialise_size_t_needs(*output_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(input, input_length) +
+        psasim_serialise_buffer_needs(output, output_size) +
+        psasim_serialise_size_t_needs(*output_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, output, output_size);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        output, output_size);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, *output_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *output_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_UPDATE,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_UPDATE server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -945,29 +1083,37 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, output, output_size);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        output, output_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&rpos, &rremain, output_length);
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        output_length);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -978,45 +1124,50 @@
     const uint8_t *input, size_t  input_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation) +
-                    psasim_serialise_buffer_needs(input, input_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(input, input_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_UPDATE_AD,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_UPDATE_AD server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1024,19 +1175,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1049,55 +1204,64 @@
     const uint8_t *tag, size_t  tag_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_aead_operation_t_needs(*operation) +
-                    psasim_serialise_buffer_needs(plaintext, plaintext_size) +
-                    psasim_serialise_size_t_needs(*plaintext_length) +
-                    psasim_serialise_buffer_needs(tag, tag_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_aead_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(plaintext, plaintext_size) +
+        psasim_serialise_size_t_needs(*plaintext_length) +
+        psasim_serialise_buffer_needs(tag, tag_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_aead_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_aead_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, plaintext, plaintext_size);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        plaintext, plaintext_size);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, *plaintext_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *plaintext_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, tag, tag_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        tag, tag_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_AEAD_VERIFY,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_AEAD_VERIFY server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1105,29 +1269,1203 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, plaintext, plaintext_size);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        plaintext, plaintext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&rpos, &rremain, plaintext_length);
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        plaintext_length);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_asymmetric_decrypt(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_length,
+    const uint8_t *salt, size_t  salt_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_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_length) +
+        psasim_serialise_buffer_needs(salt, salt_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        salt, salt_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_ASYMMETRIC_DECRYPT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_ASYMMETRIC_DECRYPT 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;
+}
+
+
+psa_status_t psa_asymmetric_encrypt(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_length,
+    const uint8_t *salt, size_t  salt_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_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_length) +
+        psasim_serialise_buffer_needs(salt, salt_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        salt, salt_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_ASYMMETRIC_ENCRYPT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_ASYMMETRIC_ENCRYPT 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;
+}
+
+
+psa_status_t psa_cipher_abort(
+    psa_cipher_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_cipher_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_cipher_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_CIPHER_ABORT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CIPHER_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_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_cipher_decrypt(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_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_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_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_CIPHER_DECRYPT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CIPHER_DECRYPT 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;
+}
+
+
+psa_status_t psa_cipher_decrypt_setup(
+    psa_cipher_operation_t *operation,
+    mbedtls_svc_key_id_t key,
+    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_cipher_operation_t_needs(*operation) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        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_cipher_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_CIPHER_DECRYPT_SETUP,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CIPHER_DECRYPT_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_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_cipher_encrypt(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_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_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_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_CIPHER_ENCRYPT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CIPHER_ENCRYPT 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;
+}
+
+
+psa_status_t psa_cipher_encrypt_setup(
+    psa_cipher_operation_t *operation,
+    mbedtls_svc_key_id_t key,
+    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_cipher_operation_t_needs(*operation) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        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_cipher_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_CIPHER_ENCRYPT_SETUP,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CIPHER_ENCRYPT_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_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_cipher_finish(
+    psa_cipher_operation_t *operation,
+    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_cipher_operation_t_needs(*operation) +
+        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_cipher_operation_t(
+        &pos, &remaining,
+        *operation);
+    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_CIPHER_FINISH,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CIPHER_FINISH 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_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    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;
+}
+
+
+psa_status_t psa_cipher_generate_iv(
+    psa_cipher_operation_t *operation,
+    uint8_t *iv, size_t  iv_size,
+    size_t *iv_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_cipher_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(iv, iv_size) +
+        psasim_serialise_size_t_needs(*iv_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_cipher_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        iv, iv_size);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *iv_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_CIPHER_GENERATE_IV,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CIPHER_GENERATE_IV 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_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        iv, iv_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        iv_length);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_cipher_set_iv(
+    psa_cipher_operation_t *operation,
+    const uint8_t *iv, size_t  iv_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_cipher_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(iv, iv_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_cipher_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        iv, iv_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_CIPHER_SET_IV,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CIPHER_SET_IV 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_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_cipher_update(
+    psa_cipher_operation_t *operation,
+    const uint8_t *input, size_t  input_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_cipher_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(input, input_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_cipher_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_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_CIPHER_UPDATE,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_CIPHER_UPDATE 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_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    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;
+}
+
+
+psa_status_t psa_copy_key(
+    mbedtls_svc_key_id_t source_key,
+    const psa_key_attributes_t *attributes,
+    mbedtls_svc_key_id_t *target_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_mbedtls_svc_key_id_t_needs(source_key) +
+        psasim_serialise_psa_key_attributes_t_needs(*attributes) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(*target_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        source_key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_key_attributes_t(
+        &pos, &remaining,
+        *attributes);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        *target_key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_COPY_KEY,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_COPY_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_mbedtls_svc_key_id_t(
+        &rpos, &rremain,
+        target_key);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1137,40 +2475,43 @@
     mbedtls_svc_key_id_t key
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_mbedtls_svc_key_id_t_needs(key);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    uint8_t *pos = ser_params;
     size_t remaining = needed;
     int ok;
     ok = psasim_serialise_begin(&pos, &remaining);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key);
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_DESTROY_KEY,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_DESTROY_KEY server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1178,14 +2519,436 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_export_key(
+    mbedtls_svc_key_id_t key,
+    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_mbedtls_svc_key_id_t_needs(key) +
+        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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    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_KEY,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_EXPORT_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_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;
+}
+
+
+psa_status_t psa_export_public_key(
+    mbedtls_svc_key_id_t key,
+    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_mbedtls_svc_key_id_t_needs(key) +
+        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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    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,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_EXPORT_PUBLIC_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_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;
+}
+
+
+psa_status_t psa_generate_key(
+    const psa_key_attributes_t *attributes,
+    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_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        *key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_GENERATE_KEY,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_GENERATE_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_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_generate_key_ext(
+    const psa_key_attributes_t *attributes,
+    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_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_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_GENERATE_KEY_EXT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_GENERATE_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_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_generate_random(
+    uint8_t *output, size_t  output_size
+    )
+{
+    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_buffer_needs(output, output_size);
+
+    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_buffer(
+        &pos, &remaining,
+        output, output_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_GENERATE_RANDOM,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_GENERATE_RANDOM 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;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1196,45 +2959,50 @@
     psa_key_attributes_t *attributes
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_mbedtls_svc_key_id_t_needs(key) +
-                    psasim_serialise_psa_key_attributes_t_needs(*attributes);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_key_attributes_t_needs(*attributes);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    uint8_t *pos = ser_params;
     size_t remaining = needed;
     int ok;
     ok = psasim_serialise_begin(&pos, &remaining);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key);
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_psa_key_attributes_t(&pos, &remaining, *attributes);
+    ok = psasim_serialise_psa_key_attributes_t(
+        &pos, &remaining,
+        *attributes);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_GET_KEY_ATTRIBUTES,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_GET_KEY_ATTRIBUTES server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1242,19 +3010,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_key_attributes_t(&rpos, &rremain, attributes);
+    ok = psasim_deserialise_psa_key_attributes_t(
+        &rpos, &rremain,
+        attributes);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1264,40 +3036,43 @@
     psa_hash_operation_t *operation
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_hash_operation_t_needs(*operation);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_hash_operation_t_needs(*operation);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_hash_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_hash_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_HASH_ABORT,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_HASH_ABORT server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1305,19 +3080,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1328,45 +3107,50 @@
     psa_hash_operation_t *target_operation
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_hash_operation_t_needs(*source_operation) +
-                    psasim_serialise_psa_hash_operation_t_needs(*target_operation);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_hash_operation_t_needs(*source_operation) +
+        psasim_serialise_psa_hash_operation_t_needs(*target_operation);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_hash_operation_t(&pos, &remaining, *source_operation);
+    ok = psasim_serialise_psa_hash_operation_t(
+        &pos, &remaining,
+        *source_operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *target_operation);
+    ok = psasim_serialise_psa_hash_operation_t(
+        &pos, &remaining,
+        *target_operation);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_HASH_CLONE,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_HASH_CLONE server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1374,19 +3158,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, target_operation);
+    ok = psasim_deserialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        target_operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1398,50 +3186,57 @@
     const uint8_t *hash, size_t  hash_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_buffer_needs(input, input_length) +
-                    psasim_serialise_buffer_needs(hash, hash_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_length) +
+        psasim_serialise_buffer_needs(hash, hash_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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);
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        hash, hash_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_HASH_COMPARE,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_HASH_COMPARE server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1449,14 +3244,16 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1469,55 +3266,64 @@
     size_t *hash_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_buffer_needs(input, input_length) +
-                    psasim_serialise_buffer_needs(hash, hash_size) +
-                    psasim_serialise_size_t_needs(*hash_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_length) +
+        psasim_serialise_buffer_needs(hash, hash_size) +
+        psasim_serialise_size_t_needs(*hash_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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);
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_size);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        hash, hash_size);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, *hash_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *hash_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_HASH_COMPUTE,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_HASH_COMPUTE server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1525,24 +3331,30 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, hash, hash_size);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        hash, hash_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&rpos, &rremain, hash_length);
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        hash_length);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1554,50 +3366,57 @@
     size_t *hash_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_hash_operation_t_needs(*operation) +
-                    psasim_serialise_buffer_needs(hash, hash_size) +
-                    psasim_serialise_size_t_needs(*hash_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_hash_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(hash, hash_size) +
+        psasim_serialise_size_t_needs(*hash_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_hash_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_hash_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_size);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        hash, hash_size);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_size_t(&pos, &remaining, *hash_length);
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *hash_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_HASH_FINISH,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_HASH_FINISH server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1605,29 +3424,37 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, hash, hash_size);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        hash, hash_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&rpos, &rremain, hash_length);
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        hash_length);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1638,45 +3465,50 @@
     psa_algorithm_t alg
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_hash_operation_t_needs(*operation) +
-                    psasim_serialise_psa_algorithm_t_needs(alg);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_hash_operation_t_needs(*operation) +
+        psasim_serialise_psa_algorithm_t_needs(alg);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_hash_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_hash_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_HASH_SETUP,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_HASH_SETUP server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1684,19 +3516,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1707,45 +3543,50 @@
     const uint8_t *input, size_t  input_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_hash_operation_t_needs(*operation) +
-                    psasim_serialise_buffer_needs(input, input_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_hash_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(input, input_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_hash_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_hash_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_HASH_UPDATE,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_HASH_UPDATE server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1753,19 +3594,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1776,45 +3621,50 @@
     const uint8_t *hash, size_t  hash_length
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_hash_operation_t_needs(*operation) +
-                    psasim_serialise_buffer_needs(hash, hash_length);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_hash_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(hash, hash_length);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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_hash_operation_t(&pos, &remaining, *operation);
+    ok = psasim_serialise_psa_hash_operation_t(
+        &pos, &remaining,
+        *operation);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        hash, hash_length);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_HASH_VERIFY,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_HASH_VERIFY server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1822,19 +3672,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_deserialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
 
     return status;
 }
@@ -1846,50 +3700,57 @@
     mbedtls_svc_key_id_t *key
     )
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    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_buffer_needs(data, data_length) +
-                    psasim_serialise_mbedtls_svc_key_id_t_needs(*key);
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_key_attributes_t_needs(*attributes) +
+        psasim_serialise_buffer_needs(data, data_length) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(*key);
 
-    params = malloc(needed);
-    if (params == NULL) {
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
         status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    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);
+    ok = psasim_serialise_psa_key_attributes_t(
+        &pos, &remaining,
+        *attributes);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_buffer(&pos, &remaining, data, data_length);
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        data, data_length);
     if (!ok) {
         goto fail;
     }
-    ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, *key);
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        *key);
     if (!ok) {
         goto fail;
     }
 
     ok = psa_crypto_call(PSA_IMPORT_KEY,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("PSA_IMPORT_KEY server call failed\n");
         goto fail;
     }
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -1897,19 +3758,3016 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_mbedtls_svc_key_id_t(&rpos, &rremain, key);
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &rpos, &rremain,
+        key);
     if (!ok) {
         goto fail;
     }
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+uint32_t psa_interruptible_get_max_ops(
+    void
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    uint32_t value = 0;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        0;
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        value = 0;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_INTERRUPTIBLE_GET_MAX_OPS,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_INTERRUPTIBLE_GET_MAX_OPS server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_uint32_t(
+        &rpos, &rremain,
+        &value);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return value;
+}
+
+
+void psa_interruptible_set_max_ops(
+    uint32_t max_ops
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_uint32_t_needs(max_ops);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_uint32_t(
+        &pos, &remaining,
+        max_ops);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_INTERRUPTIBLE_SET_MAX_OPS,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_INTERRUPTIBLE_SET_MAX_OPS server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+}
+
+
+psa_status_t psa_key_derivation_abort(
+    psa_key_derivation_operation_t *operation
+    )
+{
+    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
+    )
+{
+    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_mac_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_mac_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_MAC_ABORT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_MAC_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_mac_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_mac_compute(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_length,
+    uint8_t *mac, size_t  mac_size,
+    size_t *mac_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_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_length) +
+        psasim_serialise_buffer_needs(mac, mac_size) +
+        psasim_serialise_size_t_needs(*mac_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        mac, mac_size);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_MAC_COMPUTE,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_MAC_COMPUTE 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,
+        mac, mac_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_mac_sign_finish(
+    psa_mac_operation_t *operation,
+    uint8_t *mac, size_t  mac_size,
+    size_t *mac_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_mac_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(mac, mac_size) +
+        psasim_serialise_size_t_needs(*mac_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_mac_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        mac, mac_size);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_MAC_SIGN_FINISH,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_MAC_SIGN_FINISH 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_mac_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        mac, mac_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_mac_sign_setup(
+    psa_mac_operation_t *operation,
+    mbedtls_svc_key_id_t key,
+    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_mac_operation_t_needs(*operation) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        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_mac_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_MAC_SIGN_SETUP,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_MAC_SIGN_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_mac_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_mac_update(
+    psa_mac_operation_t *operation,
+    const uint8_t *input, size_t  input_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_mac_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(input, input_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_mac_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_MAC_UPDATE,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_MAC_UPDATE 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_mac_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_mac_verify(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_length,
+    const uint8_t *mac, size_t  mac_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_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_length) +
+        psasim_serialise_buffer_needs(mac, mac_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        mac, mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_MAC_VERIFY,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_MAC_VERIFY 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;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_mac_verify_finish(
+    psa_mac_operation_t *operation,
+    const uint8_t *mac, size_t  mac_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_mac_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(mac, mac_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_mac_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        mac, mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_MAC_VERIFY_FINISH,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_MAC_VERIFY_FINISH 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_mac_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_mac_verify_setup(
+    psa_mac_operation_t *operation,
+    mbedtls_svc_key_id_t key,
+    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_mac_operation_t_needs(*operation) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        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_mac_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_MAC_VERIFY_SETUP,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_MAC_VERIFY_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_mac_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_purge_key(
+    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_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_PURGE_KEY,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_PURGE_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;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    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;
+}
+
+
+void psa_reset_key_attributes(
+    psa_key_attributes_t *attributes
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_key_attributes_t_needs(*attributes);
+
+    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_key_attributes_t(
+        &pos, &remaining,
+        *attributes);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_RESET_KEY_ATTRIBUTES,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_RESET_KEY_ATTRIBUTES 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_key_attributes_t(
+        &rpos, &rremain,
+        attributes);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+}
+
+
+psa_status_t psa_sign_hash(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t  hash_length,
+    uint8_t *signature, size_t  signature_size,
+    size_t *signature_length
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(hash, hash_length) +
+        psasim_serialise_buffer_needs(signature, signature_size) +
+        psasim_serialise_size_t_needs(*signature_length);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        hash, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        signature, signature_size);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_SIGN_HASH,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_SIGN_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_psa_status_t(
+        &rpos, &rremain,
+        &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        signature, signature_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *operation
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_sign_hash_interruptible_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_SIGN_HASH_ABORT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_SIGN_HASH_ABORT server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_sign_hash_complete(
+    psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature, size_t  signature_size,
+    size_t *signature_length
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation) +
+        psasim_serialise_buffer_needs(signature, signature_size) +
+        psasim_serialise_size_t_needs(*signature_length);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_sign_hash_interruptible_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        signature, signature_size);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_SIGN_HASH_COMPLETE,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_SIGN_HASH_COMPLETE server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        signature, signature_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+uint32_t psa_sign_hash_get_num_ops(
+    const psa_sign_hash_interruptible_operation_t *operation
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    uint32_t value = 0;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        value = 0;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_sign_hash_interruptible_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_SIGN_HASH_GET_NUM_OPS,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_SIGN_HASH_GET_NUM_OPS server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_uint32_t(
+        &rpos, &rremain,
+        &value);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return value;
+}
+
+
+psa_status_t psa_sign_hash_start(
+    psa_sign_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t  hash_length
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(hash, hash_length);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_sign_hash_interruptible_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        hash, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_SIGN_HASH_START,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_SIGN_HASH_START server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_sign_message(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_length,
+    uint8_t *signature, size_t  signature_size,
+    size_t *signature_length
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_length) +
+        psasim_serialise_buffer_needs(signature, signature_size) +
+        psasim_serialise_size_t_needs(*signature_length);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        signature, signature_size);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_size_t(
+        &pos, &remaining,
+        *signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_SIGN_MESSAGE,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_SIGN_MESSAGE 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,
+        signature, signature_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &rpos, &rremain,
+        signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_verify_hash(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t  hash_length,
+    const uint8_t *signature, size_t  signature_length
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(hash, hash_length) +
+        psasim_serialise_buffer_needs(signature, signature_length);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        hash, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        signature, signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_VERIFY_HASH,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_VERIFY_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_psa_status_t(
+        &rpos, &rremain,
+        &status);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *operation
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_verify_hash_interruptible_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_VERIFY_HASH_ABORT,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_VERIFY_HASH_ABORT server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *operation
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_verify_hash_interruptible_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_VERIFY_HASH_COMPLETE,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_VERIFY_HASH_COMPLETE server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+uint32_t psa_verify_hash_get_num_ops(
+    const psa_verify_hash_interruptible_operation_t *operation
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    uint32_t value = 0;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        value = 0;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_verify_hash_interruptible_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_VERIFY_HASH_GET_NUM_OPS,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_VERIFY_HASH_GET_NUM_OPS server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_uint32_t(
+        &rpos, &rremain,
+        &value);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return value;
+}
+
+
+psa_status_t psa_verify_hash_start(
+    psa_verify_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t  hash_length,
+    const uint8_t *signature, size_t  signature_length
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation) +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(hash, hash_length) +
+        psasim_serialise_buffer_needs(signature, signature_length);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_verify_hash_interruptible_operation_t(
+        &pos, &remaining,
+        *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        hash, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        signature, signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_VERIFY_HASH_START,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_VERIFY_HASH_START server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = ser_result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(
+        &rpos, &rremain,
+        &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(ser_params);
+    free(ser_result);
+
+    return status;
+}
+
+
+psa_status_t psa_verify_message(
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_length,
+    const uint8_t *signature, size_t  signature_length
+    )
+{
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_mbedtls_svc_key_id_t_needs(key) +
+        psasim_serialise_psa_algorithm_t_needs(alg) +
+        psasim_serialise_buffer_needs(input, input_length) +
+        psasim_serialise_buffer_needs(signature, signature_length);
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = ser_params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        key);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(
+        &pos, &remaining,
+        alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(
+        &pos, &remaining,
+        signature, signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_VERIFY_MESSAGE,
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
+    if (!ok) {
+        printf("PSA_VERIFY_MESSAGE 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;
+    }
+
+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 30d4b26..5259751 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
@@ -54,7 +54,9 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
@@ -88,7 +90,9 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
@@ -118,12 +122,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -167,37 +175,51 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &nonce, &nonce_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &additional_data, &additional_data_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &additional_data, &additional_data_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &ciphertext, &ciphertext_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &ciphertext, &ciphertext_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &plaintext, &plaintext_size);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &plaintext, &plaintext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &plaintext_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &plaintext_length);
     if (!ok) {
         goto fail;
     }
@@ -234,17 +256,23 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, plaintext, plaintext_size);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        plaintext, plaintext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_size_t(&rpos, &rremain, plaintext_length);
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        plaintext_length);
     if (!ok) {
         goto fail;
     }
@@ -290,17 +318,23 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
     if (!ok) {
         goto fail;
     }
@@ -332,12 +366,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -381,37 +419,51 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &nonce, &nonce_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &additional_data, &additional_data_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &additional_data, &additional_data_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &plaintext, &plaintext_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &plaintext, &plaintext_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &ciphertext, &ciphertext_size);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &ciphertext, &ciphertext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &ciphertext_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &ciphertext_length);
     if (!ok) {
         goto fail;
     }
@@ -448,17 +500,23 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, ciphertext, ciphertext_size);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        ciphertext, ciphertext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_size_t(&rpos, &rremain, ciphertext_length);
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        ciphertext_length);
     if (!ok) {
         goto fail;
     }
@@ -504,17 +562,23 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
     if (!ok) {
         goto fail;
     }
@@ -546,12 +610,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -591,27 +659,37 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &ciphertext, &ciphertext_size);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &ciphertext, &ciphertext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &ciphertext_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &ciphertext_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &tag, &tag_size);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &tag, &tag_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &tag_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &tag_length);
     if (!ok) {
         goto fail;
     }
@@ -649,32 +727,44 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, ciphertext, ciphertext_size);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        ciphertext, ciphertext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_size_t(&rpos, &rremain, ciphertext_length);
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        ciphertext_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, tag, tag_size);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        tag, tag_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_size_t(&rpos, &rremain, tag_length);
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        tag_length);
     if (!ok) {
         goto fail;
     }
@@ -717,17 +807,23 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_size);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &nonce, &nonce_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &nonce_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &nonce_length);
     if (!ok) {
         goto fail;
     }
@@ -761,22 +857,30 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, nonce, nonce_size);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        nonce, nonce_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_size_t(&rpos, &rremain, nonce_length);
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        nonce_length);
     if (!ok) {
         goto fail;
     }
@@ -816,17 +920,23 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &ad_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &ad_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &plaintext_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &plaintext_length);
     if (!ok) {
         goto fail;
     }
@@ -858,12 +968,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -899,12 +1013,16 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &nonce, &nonce_length);
     if (!ok) {
         goto fail;
     }
@@ -935,12 +1053,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -983,22 +1105,30 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &output, &output_size);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &output, &output_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &output_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &output_length);
     if (!ok) {
         goto fail;
     }
@@ -1033,22 +1163,30 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, output, output_size);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        output, output_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_size_t(&rpos, &rremain, output_length);
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        output_length);
     if (!ok) {
         goto fail;
     }
@@ -1090,12 +1228,16 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
     if (!ok) {
         goto fail;
     }
@@ -1126,12 +1268,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -1174,22 +1320,30 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_aead_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &plaintext, &plaintext_size);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &plaintext, &plaintext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &plaintext_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &plaintext_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &tag, &tag_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &tag, &tag_length);
     if (!ok) {
         goto fail;
     }
@@ -1224,22 +1378,30 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_aead_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, plaintext, plaintext_size);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        plaintext, plaintext_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_size_t(&rpos, &rremain, plaintext_length);
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        plaintext_length);
     if (!ok) {
         goto fail;
     }
@@ -1262,6 +1424,1335 @@
 }
 
 // Returns 1 for success, 0 for failure
+int psa_asymmetric_decrypt_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;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_length;
+    uint8_t *salt = NULL;
+    size_t salt_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &salt, &salt_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_asymmetric_decrypt(
+        key,
+        alg,
+        input, input_length,
+        salt, salt_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(input);
+    free(salt);
+    free(output);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(salt);
+    free(output);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_asymmetric_encrypt_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;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_length;
+    uint8_t *salt = NULL;
+    size_t salt_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &salt, &salt_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_asymmetric_encrypt(
+        key,
+        alg,
+        input, input_length,
+        salt, salt_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(input);
+    free(salt);
+    free(output);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(salt);
+    free(output);
+
+    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)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_cipher_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_cipher_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_cipher_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_cipher_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_cipher_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_cipher_decrypt_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;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_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_cipher_decrypt(
+        key,
+        alg,
+        input, input_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(input);
+    free(output);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(output);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_cipher_decrypt_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_cipher_operation_t *operation;
+    mbedtls_svc_key_id_t key;
+    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_cipher_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_cipher_decrypt_setup(
+        operation,
+        key,
+        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_cipher_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_cipher_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_cipher_encrypt_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;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_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_cipher_encrypt(
+        key,
+        alg,
+        input, input_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(input);
+    free(output);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(output);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_cipher_encrypt_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_cipher_operation_t *operation;
+    mbedtls_svc_key_id_t key;
+    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_cipher_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_cipher_encrypt_setup(
+        operation,
+        key,
+        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_cipher_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_cipher_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_cipher_finish_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_cipher_operation_t *operation;
+    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_server_deserialise_psa_cipher_operation_t(
+        &pos, &remaining,
+        &operation);
+    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_cipher_finish(
+        operation,
+        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_server_serialise_psa_cipher_operation_t_needs(operation) +
+        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_server_serialise_psa_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    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(output);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(output);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_cipher_generate_iv_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_cipher_operation_t *operation;
+    uint8_t *iv = NULL;
+    size_t iv_size;
+    size_t iv_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_cipher_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &iv, &iv_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &iv_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_cipher_generate_iv(
+        operation,
+        iv, iv_size,
+        &iv_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_cipher_operation_t_needs(operation) +
+        psasim_serialise_buffer_needs(iv, iv_size) +
+        psasim_serialise_size_t_needs(iv_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_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        iv, iv_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        iv_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(iv);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(iv);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_cipher_set_iv_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_cipher_operation_t *operation;
+    uint8_t *iv = NULL;
+    size_t iv_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_cipher_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &iv, &iv_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_cipher_set_iv(
+        operation,
+        iv, iv_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_cipher_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_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(iv);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(iv);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_cipher_update_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_cipher_operation_t *operation;
+    uint8_t *input = NULL;
+    size_t input_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_server_deserialise_psa_cipher_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_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_cipher_update(
+        operation,
+        input, input_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_server_serialise_psa_cipher_operation_t_needs(operation) +
+        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_server_serialise_psa_cipher_operation_t(
+        &rpos, &rremain,
+        operation);
+    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(input);
+    free(output);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(output);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_copy_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;
+    mbedtls_svc_key_id_t source_key;
+    psa_key_attributes_t attributes;
+    mbedtls_svc_key_id_t target_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &source_key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_key_attributes_t(
+        &pos, &remaining,
+        &attributes);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &target_key);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_copy_key(
+        source_key,
+        &attributes,
+        &target_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_mbedtls_svc_key_id_t_needs(target_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_serialise_mbedtls_svc_key_id_t(
+        &rpos, &rremain,
+        target_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_destroy_key_wrapper(
     uint8_t *in_params, size_t in_params_len,
     uint8_t **out_params, size_t *out_params_len)
@@ -1279,7 +2770,9 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
     if (!ok) {
         goto fail;
     }
@@ -1308,7 +2801,9 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
@@ -1325,6 +2820,480 @@
 }
 
 // Returns 1 for success, 0 for failure
+int psa_export_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;
+    mbedtls_svc_key_id_t key;
+    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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    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_key(
+        key,
+        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_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_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_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;
+    mbedtls_svc_key_id_t key;
+    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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    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(
+        key,
+        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_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_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_generate_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;
+    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_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_generate_key(
+        &attributes,
+        &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_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_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_generate_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_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_deserialise_psa_key_production_parameters_t(
+        &pos, &remaining,
+        &params, &params_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_generate_key_ext(
+        &attributes,
+        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_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_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_generate_random_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;
+    uint8_t *output = NULL;
+    size_t output_size;
+
+    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_buffer(
+        &pos, &remaining,
+        &output, &output_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_generate_random(
+        output, output_size
+        );
+
+    // 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);
+
+    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;
+    }
+
+    *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_get_key_attributes_wrapper(
     uint8_t *in_params, size_t in_params_len,
     uint8_t **out_params, size_t *out_params_len)
@@ -1343,12 +3312,16 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_key_attributes_t(&pos, &remaining, &attributes);
+    ok = psasim_deserialise_psa_key_attributes_t(
+        &pos, &remaining,
+        &attributes);
     if (!ok) {
         goto fail;
     }
@@ -1379,12 +3352,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_psa_key_attributes_t(&rpos, &rremain, attributes);
+    ok = psasim_serialise_psa_key_attributes_t(
+        &rpos, &rremain,
+        attributes);
     if (!ok) {
         goto fail;
     }
@@ -1418,7 +3395,9 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
@@ -1448,12 +3427,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -1488,12 +3471,16 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &source_operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(
+        &pos, &remaining,
+        &source_operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &target_operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(
+        &pos, &remaining,
+        &target_operation);
     if (!ok) {
         goto fail;
     }
@@ -1524,12 +3511,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, target_operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        target_operation);
     if (!ok) {
         goto fail;
     }
@@ -1567,17 +3558,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &hash, &hash_length);
     if (!ok) {
         goto fail;
     }
@@ -1608,7 +3605,9 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
@@ -1653,22 +3652,30 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_size);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &hash, &hash_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &hash_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &hash_length);
     if (!ok) {
         goto fail;
     }
@@ -1702,17 +3709,23 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, hash, hash_size);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        hash, hash_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_size_t(&rpos, &rremain, hash_length);
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        hash_length);
     if (!ok) {
         goto fail;
     }
@@ -1755,17 +3768,23 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_size);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &hash, &hash_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_size_t(&pos, &remaining, &hash_length);
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &hash_length);
     if (!ok) {
         goto fail;
     }
@@ -1799,22 +3818,30 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, hash, hash_size);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        hash, hash_size);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_size_t(&rpos, &rremain, hash_length);
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        hash_length);
     if (!ok) {
         goto fail;
     }
@@ -1853,12 +3880,16 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
     if (!ok) {
         goto fail;
     }
@@ -1889,12 +3920,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -1930,12 +3965,16 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
     if (!ok) {
         goto fail;
     }
@@ -1966,12 +4005,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -2011,12 +4054,16 @@
         goto fail;
     }
 
-    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(
+        &pos, &remaining,
+        &operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &hash, &hash_length);
     if (!ok) {
         goto fail;
     }
@@ -2047,12 +4094,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(
+        &rpos, &rremain,
+        operation);
     if (!ok) {
         goto fail;
     }
@@ -2093,17 +4144,23 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_key_attributes_t(&pos, &remaining, &attributes);
+    ok = psasim_deserialise_psa_key_attributes_t(
+        &pos, &remaining,
+        &attributes);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_buffer(&pos, &remaining, &data, &data_length);
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &data, &data_length);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
     if (!ok) {
         goto fail;
     }
@@ -2135,12 +4192,16 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_serialise_mbedtls_svc_key_id_t(&rpos, &rremain, key);
+    ok = psasim_serialise_mbedtls_svc_key_id_t(
+        &rpos, &rremain,
+        key);
     if (!ok) {
         goto fail;
     }
@@ -2160,6 +4221,3345 @@
     return 0;       // This shouldn't happen!
 }
 
+// Returns 1 for success, 0 for failure
+int psa_interruptible_get_max_ops_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    uint32_t value = 0;
+
+    uint8_t *result = NULL;
+    int ok;
+
+    // Now we call the actual target function
+
+    value = psa_interruptible_get_max_ops(
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_uint32_t_needs(value);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_uint32_t(
+        &rpos, &rremain,
+        value);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_interruptible_set_max_ops_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    uint32_t max_ops;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_uint32_t(
+        &pos, &remaining,
+        &max_ops);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    psa_interruptible_set_max_ops(
+        max_ops
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs();
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_key_derivation_abort_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    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,
+        &params, &params_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)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_mac_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_mac_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_mac_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_mac_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_mac_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_compute_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;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_length;
+    uint8_t *mac = NULL;
+    size_t mac_size;
+    size_t mac_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &mac, &mac_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_mac_compute(
+        key,
+        alg,
+        input, input_length,
+        mac, mac_size,
+        &mac_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(mac, mac_size) +
+        psasim_serialise_size_t_needs(mac_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,
+        mac, mac_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(input);
+    free(mac);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(mac);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_mac_sign_finish_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_mac_operation_t *operation;
+    uint8_t *mac = NULL;
+    size_t mac_size;
+    size_t mac_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_mac_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &mac, &mac_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_mac_sign_finish(
+        operation,
+        mac, mac_size,
+        &mac_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_mac_operation_t_needs(operation) +
+        psasim_serialise_buffer_needs(mac, mac_size) +
+        psasim_serialise_size_t_needs(mac_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_mac_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        mac, mac_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(mac);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(mac);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_mac_sign_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_mac_operation_t *operation;
+    mbedtls_svc_key_id_t key;
+    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_mac_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_mac_sign_setup(
+        operation,
+        key,
+        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_mac_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_mac_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_update_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_mac_operation_t *operation;
+    uint8_t *input = NULL;
+    size_t input_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_mac_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_mac_update(
+        operation,
+        input, input_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_mac_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_mac_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(input);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_mac_verify_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;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_length;
+    uint8_t *mac = NULL;
+    size_t mac_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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &mac, &mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_mac_verify(
+        key,
+        alg,
+        input, input_length,
+        mac, mac_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);
+
+    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;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(input);
+    free(mac);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(mac);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_mac_verify_finish_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_mac_operation_t *operation;
+    uint8_t *mac = NULL;
+    size_t mac_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_mac_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &mac, &mac_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_mac_verify_finish(
+        operation,
+        mac, mac_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_mac_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_mac_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(mac);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(mac);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_mac_verify_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_mac_operation_t *operation;
+    mbedtls_svc_key_id_t key;
+    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_mac_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_mac_verify_setup(
+        operation,
+        key,
+        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_mac_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_mac_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_purge_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;
+    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_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_purge_key(
+        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);
+
+    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;
+    }
+
+    *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_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!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_reset_key_attributes_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_key_attributes_t attributes;
+
+    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;
+    }
+
+    // Now we call the actual target function
+
+    psa_reset_key_attributes(
+        &attributes
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_key_attributes_t_needs(attributes);
+
+    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_key_attributes_t(
+        &rpos, &rremain,
+        attributes);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_sign_hash_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;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *hash = NULL;
+    size_t hash_length;
+    uint8_t *signature = NULL;
+    size_t signature_size;
+    size_t signature_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &hash, &hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &signature, &signature_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_sign_hash(
+        key,
+        alg,
+        hash, hash_length,
+        signature, signature_size,
+        &signature_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_serialise_buffer_needs(signature, signature_size) +
+        psasim_serialise_size_t_needs(signature_length);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        signature, signature_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(hash);
+    free(signature);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(hash);
+    free(signature);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_sign_hash_abort_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_sign_hash_interruptible_operation_t *operation;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_sign_hash_abort(
+        operation
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_sign_hash_complete_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_sign_hash_interruptible_operation_t *operation;
+    uint8_t *signature = NULL;
+    size_t signature_size;
+    size_t signature_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &signature, &signature_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_sign_hash_complete(
+        operation,
+        signature, signature_size,
+        &signature_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation) +
+        psasim_serialise_buffer_needs(signature, signature_size) +
+        psasim_serialise_size_t_needs(signature_length);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        signature, signature_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(signature);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(signature);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_sign_hash_get_num_ops_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    uint32_t value = 0;
+    psa_sign_hash_interruptible_operation_t *operation;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    value = psa_sign_hash_get_num_ops(
+        operation
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_uint32_t_needs(value);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_uint32_t(
+        &rpos, &rremain,
+        value);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_sign_hash_start_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_sign_hash_interruptible_operation_t *operation;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *hash = NULL;
+    size_t hash_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &hash, &hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_sign_hash_start(
+        operation,
+        key,
+        alg,
+        hash, hash_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(hash);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(hash);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_sign_message_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_length;
+    uint8_t *signature = NULL;
+    size_t signature_size;
+    size_t signature_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &signature, &signature_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(
+        &pos, &remaining,
+        &signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_sign_message(
+        key,
+        alg,
+        input, input_length,
+        signature, signature_size,
+        &signature_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_serialise_buffer_needs(signature, signature_size) +
+        psasim_serialise_size_t_needs(signature_length);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        signature, signature_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_size_t(
+        &rpos, &rremain,
+        signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(input);
+    free(signature);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(signature);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_verify_hash_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;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *hash = NULL;
+    size_t hash_length;
+    uint8_t *signature = NULL;
+    size_t signature_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &hash, &hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &signature, &signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_verify_hash(
+        key,
+        alg,
+        hash, hash_length,
+        signature, signature_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status);
+
+    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;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(hash);
+    free(signature);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(hash);
+    free(signature);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_verify_hash_abort_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_verify_hash_interruptible_operation_t *operation;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_verify_hash_abort(
+        operation
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_verify_hash_complete_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_verify_hash_interruptible_operation_t *operation;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_verify_hash_complete(
+        operation
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_verify_hash_get_num_ops_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    uint32_t value = 0;
+    psa_verify_hash_interruptible_operation_t *operation;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    value = psa_verify_hash_get_num_ops(
+        operation
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_uint32_t_needs(value);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_uint32_t(
+        &rpos, &rremain,
+        value);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_verify_hash_start_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_verify_hash_interruptible_operation_t *operation;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *hash = NULL;
+    size_t hash_length;
+    uint8_t *signature = NULL;
+    size_t signature_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(
+        &pos, &remaining,
+        &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &hash, &hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &signature, &signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_verify_hash_start(
+        operation,
+        key,
+        alg,
+        hash, hash_length,
+        signature, signature_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(
+        &rpos, &rremain,
+        status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t(
+        &rpos, &rremain,
+        operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(hash);
+    free(signature);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(hash);
+    free(signature);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_verify_message_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_svc_key_id_t key;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_length;
+    uint8_t *signature = NULL;
+    size_t signature_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_mbedtls_svc_key_id_t(
+        &pos, &remaining,
+        &key);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(
+        &pos, &remaining,
+        &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(
+        &pos, &remaining,
+        &signature, &signature_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_verify_message(
+        key,
+        alg,
+        input, input_length,
+        signature, signature_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status);
+
+    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;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(input);
+    free(signature);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(signature);
+
+    return 0;       // This shouldn't happen!
+}
+
 psa_status_t psa_crypto_call(psa_msg_t msg)
 {
     int ok = 0;
@@ -2248,10 +7648,78 @@
             ok = psa_aead_verify_wrapper(in_params, in_params_len,
                                          &out_params, &out_params_len);
             break;
+        case PSA_ASYMMETRIC_DECRYPT:
+            ok = psa_asymmetric_decrypt_wrapper(in_params, in_params_len,
+                                                &out_params, &out_params_len);
+            break;
+        case PSA_ASYMMETRIC_ENCRYPT:
+            ok = psa_asymmetric_encrypt_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);
+            break;
+        case PSA_CIPHER_DECRYPT:
+            ok = psa_cipher_decrypt_wrapper(in_params, in_params_len,
+                                            &out_params, &out_params_len);
+            break;
+        case PSA_CIPHER_DECRYPT_SETUP:
+            ok = psa_cipher_decrypt_setup_wrapper(in_params, in_params_len,
+                                                  &out_params, &out_params_len);
+            break;
+        case PSA_CIPHER_ENCRYPT:
+            ok = psa_cipher_encrypt_wrapper(in_params, in_params_len,
+                                            &out_params, &out_params_len);
+            break;
+        case PSA_CIPHER_ENCRYPT_SETUP:
+            ok = psa_cipher_encrypt_setup_wrapper(in_params, in_params_len,
+                                                  &out_params, &out_params_len);
+            break;
+        case PSA_CIPHER_FINISH:
+            ok = psa_cipher_finish_wrapper(in_params, in_params_len,
+                                           &out_params, &out_params_len);
+            break;
+        case PSA_CIPHER_GENERATE_IV:
+            ok = psa_cipher_generate_iv_wrapper(in_params, in_params_len,
+                                                &out_params, &out_params_len);
+            break;
+        case PSA_CIPHER_SET_IV:
+            ok = psa_cipher_set_iv_wrapper(in_params, in_params_len,
+                                           &out_params, &out_params_len);
+            break;
+        case PSA_CIPHER_UPDATE:
+            ok = psa_cipher_update_wrapper(in_params, in_params_len,
+                                           &out_params, &out_params_len);
+            break;
+        case PSA_COPY_KEY:
+            ok = psa_copy_key_wrapper(in_params, in_params_len,
+                                      &out_params, &out_params_len);
+            break;
         case PSA_DESTROY_KEY:
             ok = psa_destroy_key_wrapper(in_params, in_params_len,
                                          &out_params, &out_params_len);
             break;
+        case PSA_EXPORT_KEY:
+            ok = psa_export_key_wrapper(in_params, in_params_len,
+                                        &out_params, &out_params_len);
+            break;
+        case PSA_EXPORT_PUBLIC_KEY:
+            ok = psa_export_public_key_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);
+            break;
+        case PSA_GENERATE_KEY_EXT:
+            ok = psa_generate_key_ext_wrapper(in_params, in_params_len,
+                                              &out_params, &out_params_len);
+            break;
+        case PSA_GENERATE_RANDOM:
+            ok = psa_generate_random_wrapper(in_params, in_params_len,
+                                             &out_params, &out_params_len);
+            break;
         case PSA_GET_KEY_ATTRIBUTES:
             ok = psa_get_key_attributes_wrapper(in_params, in_params_len,
                                                 &out_params, &out_params_len);
@@ -2292,6 +7760,150 @@
             ok = psa_import_key_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
             break;
+        case PSA_INTERRUPTIBLE_GET_MAX_OPS:
+            ok = psa_interruptible_get_max_ops_wrapper(in_params, in_params_len,
+                                                       &out_params, &out_params_len);
+            break;
+        case PSA_INTERRUPTIBLE_SET_MAX_OPS:
+            ok = psa_interruptible_set_max_ops_wrapper(in_params, in_params_len,
+                                                       &out_params, &out_params_len);
+            break;
+        case PSA_KEY_DERIVATION_ABORT:
+            ok = psa_key_derivation_abort_wrapper(in_params, in_params_len,
+                                                  &out_params, &out_params_len);
+            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);
+            break;
+        case PSA_MAC_COMPUTE:
+            ok = psa_mac_compute_wrapper(in_params, in_params_len,
+                                         &out_params, &out_params_len);
+            break;
+        case PSA_MAC_SIGN_FINISH:
+            ok = psa_mac_sign_finish_wrapper(in_params, in_params_len,
+                                             &out_params, &out_params_len);
+            break;
+        case PSA_MAC_SIGN_SETUP:
+            ok = psa_mac_sign_setup_wrapper(in_params, in_params_len,
+                                            &out_params, &out_params_len);
+            break;
+        case PSA_MAC_UPDATE:
+            ok = psa_mac_update_wrapper(in_params, in_params_len,
+                                        &out_params, &out_params_len);
+            break;
+        case PSA_MAC_VERIFY:
+            ok = psa_mac_verify_wrapper(in_params, in_params_len,
+                                        &out_params, &out_params_len);
+            break;
+        case PSA_MAC_VERIFY_FINISH:
+            ok = psa_mac_verify_finish_wrapper(in_params, in_params_len,
+                                               &out_params, &out_params_len);
+            break;
+        case PSA_MAC_VERIFY_SETUP:
+            ok = psa_mac_verify_setup_wrapper(in_params, in_params_len,
+                                              &out_params, &out_params_len);
+            break;
+        case PSA_PURGE_KEY:
+            ok = psa_purge_key_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;
+        case PSA_RESET_KEY_ATTRIBUTES:
+            ok = psa_reset_key_attributes_wrapper(in_params, in_params_len,
+                                                  &out_params, &out_params_len);
+            break;
+        case PSA_SIGN_HASH:
+            ok = psa_sign_hash_wrapper(in_params, in_params_len,
+                                       &out_params, &out_params_len);
+            break;
+        case PSA_SIGN_HASH_ABORT:
+            ok = psa_sign_hash_abort_wrapper(in_params, in_params_len,
+                                             &out_params, &out_params_len);
+            break;
+        case PSA_SIGN_HASH_COMPLETE:
+            ok = psa_sign_hash_complete_wrapper(in_params, in_params_len,
+                                                &out_params, &out_params_len);
+            break;
+        case PSA_SIGN_HASH_GET_NUM_OPS:
+            ok = psa_sign_hash_get_num_ops_wrapper(in_params, in_params_len,
+                                                   &out_params, &out_params_len);
+            break;
+        case PSA_SIGN_HASH_START:
+            ok = psa_sign_hash_start_wrapper(in_params, in_params_len,
+                                             &out_params, &out_params_len);
+            break;
+        case PSA_SIGN_MESSAGE:
+            ok = psa_sign_message_wrapper(in_params, in_params_len,
+                                          &out_params, &out_params_len);
+            break;
+        case PSA_VERIFY_HASH:
+            ok = psa_verify_hash_wrapper(in_params, in_params_len,
+                                         &out_params, &out_params_len);
+            break;
+        case PSA_VERIFY_HASH_ABORT:
+            ok = psa_verify_hash_abort_wrapper(in_params, in_params_len,
+                                               &out_params, &out_params_len);
+            break;
+        case PSA_VERIFY_HASH_COMPLETE:
+            ok = psa_verify_hash_complete_wrapper(in_params, in_params_len,
+                                                  &out_params, &out_params_len);
+            break;
+        case PSA_VERIFY_HASH_GET_NUM_OPS:
+            ok = psa_verify_hash_get_num_ops_wrapper(in_params, in_params_len,
+                                                     &out_params, &out_params_len);
+            break;
+        case PSA_VERIFY_HASH_START:
+            ok = psa_verify_hash_start_wrapper(in_params, in_params_len,
+                                               &out_params, &out_params_len);
+            break;
+        case PSA_VERIFY_MESSAGE:
+            ok = psa_verify_message_wrapper(in_params, in_params_len,
+                                            &out_params, &out_params_len);
+            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 43de1db..ac23807 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl
@@ -18,6 +18,16 @@
 my %functions = get_functions();
 my @functions = sort keys %functions;
 
+# We don't want these functions (e.g. because they are not implemented, etc)
+my @skip_functions = qw(
+    psa_key_derivation_verify_bytes
+    psa_key_derivation_verify_key
+);
+
+# Remove @skip_functions from @functions
+my %skip_functions = map { $_ => 1 } @skip_functions;
+@functions = grep(!exists($skip_functions{$_}), @functions);
+
 # get_functions(), called above, returns a data structure for each function
 # that we need to create client and server stubs for. In this example Perl script,
 # the function declarations we want are in the data section (after __END__ at
@@ -519,6 +529,9 @@
     uint8_t *in_params, size_t in_params_len,
     uint8_t **out_params, size_t *out_params_len)
 {
+EOF
+
+    print $fh <<EOF unless $ret_type eq "void";
     $ret_type $ret_name = $ret_default;
 EOF
     # Output the variables we will need when we call the target function
@@ -538,6 +551,13 @@
     size_t $n2;
 EOF
             push(@buffers, $n1);        # Add to the list to be free()d at end
+        } elsif ($argtype =~ /^(const )?psa_key_production_parameters_t$/) {
+            my ($n1, $n2) = split(/,\s*/, $argname);
+            print $fh <<EOF;
+    psa_key_production_parameters_t *$n1 = NULL;
+    size_t $n2;
+EOF
+            push(@buffers, $n1);        # Add to the list to be free()d at end
         } else {
             $argname =~ s/^\*//;        # Remove any leading *
             my $pointer = ($argtype =~ /^psa_\w+_operation_t/) ? "*" : "";
@@ -586,7 +606,20 @@
             my ($n1, $n2) = split(/,\s*/, $argname);
             print $fh <<EOF;
 
-    ok = psasim_deserialise_${argtype}(&pos, &remaining, &$n1, &$n2);
+    ok = psasim_deserialise_${argtype}(
+        &pos, &remaining,
+        &$n1, &$n2);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+        } elsif ($argtype =~ /^(const )?psa_key_production_parameters_t$/) {
+            my ($n1, $n2) = split(/,\s*/, $argname);
+            print $fh <<EOF;
+
+    ok = psasim_deserialise_${argtype}(
+        &pos, &remaining,
+        &$n1, &$n2);
     if (!ok) {
         goto fail;
     }
@@ -596,7 +629,9 @@
             my $server_specific = ($argtype =~ /^psa_\w+_operation_t/) ? "server_" : "";
             print $fh <<EOF;
 
-    ok = psasim_${server_specific}deserialise_${argtype}(&pos, &remaining, &$argname);
+    ok = psasim_${server_specific}deserialise_${argtype}(
+        &pos, &remaining,
+        &$argname);
     if (!ok) {
         goto fail;
     }
@@ -612,7 +647,7 @@
 
     my @outputs = grep($_->{is_output}, @$args);
 
-    my $sep1 = ($ret_type eq "void") ? ";" : " +";
+    my $sep1 = (($ret_type eq "void") and ($#outputs < 0)) ? ";" : " +";
 
     print $fh <<EOF;
 
@@ -662,7 +697,9 @@
     if ($ret_type ne "void") {
         print $fh <<EOF;
 
-    ok = psasim_serialise_${ret_type}(&rpos, &rremain, $ret_name);
+    ok = psasim_serialise_${ret_type}(
+        &rpos, &rremain,
+        $ret_name);
     if (!ok) {
         goto fail;
     }
@@ -682,7 +719,19 @@
         if ($argtype eq "buffer") {
             print $fh <<EOF;
 
-    ok = psasim_serialise_buffer(&rpos, &rremain, $argname);
+    ok = psasim_serialise_buffer(
+        &rpos, &rremain,
+        $argname);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+        } elsif ($argtype eq "psa_key_production_parameters_t") {
+            print $fh <<EOF;
+
+    ok = psasim_serialise_psa_key_production_parameters_t(
+        &rpos, &rremain,
+        $argname);
     if (!ok) {
         goto fail;
     }
@@ -698,7 +747,9 @@
 
             print $fh <<EOF;
 
-    ok = psasim_${server_specific}serialise_${argtype}(&rpos, &rremain, $argname);
+    ok = psasim_${server_specific}serialise_${argtype}(
+        &rpos, &rremain,
+        $argname);
     if (!ok) {
         goto fail;
     }
@@ -738,9 +789,11 @@
 
     print $fh <<EOF;
 {
-    uint8_t *params = NULL;
-    uint8_t *result = NULL;
+    uint8_t *ser_params = NULL;
+    uint8_t *ser_result = NULL;
     size_t result_length;
+EOF
+    print $fh <<EOF unless $ret_type eq "void";
     $ret_type $ret_name = $ret_default;
 EOF
 
@@ -751,7 +804,8 @@
 
     print $fh <<EOF;
 
-    size_t needed = psasim_serialise_begin_needs() +
+    size_t needed =
+        psasim_serialise_begin_needs() +
 EOF
 
     my $args = $f->{args};
@@ -764,19 +818,35 @@
         $argtype =~ s/^const //;
 
         print $fh <<EOF;
-                    psasim_serialise_${argtype}_needs($argname)$sep
+        psasim_serialise_${argtype}_needs($argname)$sep
+EOF
+    }
+
+    print $fh <<EOF if $#$args < 0;
+        0;
+EOF
+
+    print $fh <<EOF;
+
+    ser_params = malloc(needed);
+    if (ser_params == NULL) {
+EOF
+
+    if ($ret_type eq "psa_status_t") {
+        print $fh <<EOF if $;
+        $ret_name = PSA_ERROR_INSUFFICIENT_MEMORY;
+EOF
+    } elsif ($ret_type eq "uint32_t") {
+        print $fh <<EOF if $;
+        $ret_name = 0;
 EOF
     }
 
     print $fh <<EOF;
-
-    params = malloc(needed);
-    if (params == NULL) {
-        status = PSA_ERROR_INSUFFICIENT_MEMORY;
         goto fail;
     }
 
-    uint8_t *pos = params;
+    uint8_t *pos = ser_params;
     size_t remaining = needed;
     int ok;
     ok = psasim_serialise_begin(&pos, &remaining);
@@ -793,7 +863,9 @@
         $argtype =~ s/^const //;
 
         print $fh <<EOF;
-    ok = psasim_serialise_${argtype}(&pos, &remaining, $argname);
+    ok = psasim_serialise_${argtype}(
+        &pos, &remaining,
+        $argname);
     if (!ok) {
         goto fail;
     }
@@ -802,8 +874,8 @@
 
     print $fh <<EOF if $debug;
 
-    printf("client sending %d:\\n", (int)(pos - params));
-    dump_buffer(params, (size_t)(pos - params));
+    printf("client sending %d:\\n", (int)(pos - ser_params));
+    dump_buffer(ser_params, (size_t)(pos - ser_params));
 EOF
 
     my $enum = uc($name);
@@ -811,7 +883,7 @@
     print $fh <<EOF;
 
     ok = psa_crypto_call($enum,
-                         params, (size_t) (pos - params), &result, &result_length);
+                         ser_params, (size_t) (pos - ser_params), &ser_result, &result_length);
     if (!ok) {
         printf("$enum server call failed\\n");
         goto fail;
@@ -821,12 +893,12 @@
     print $fh <<EOF if $debug;
 
     printf("client receiving %d:\\n", (int)result_length);
-    dump_buffer(result, result_length);
+    dump_buffer(ser_result, result_length);
 EOF
 
     print $fh <<EOF;
 
-    uint8_t *rpos = result;
+    uint8_t *rpos = ser_result;
     size_t rremain = result_length;
 
     ok = psasim_deserialise_begin(&rpos, &rremain);
@@ -835,9 +907,11 @@
     }
 EOF
 
-    print $fh <<EOF;
+    print $fh <<EOF if $ret_type ne "void";
 
-    ok = psasim_deserialise_$ret_type(&rpos, &rremain, &$ret_name);
+    ok = psasim_deserialise_$ret_type(
+        &rpos, &rremain,
+        &$ret_name);
     if (!ok) {
         goto fail;
     }
@@ -856,7 +930,9 @@
         if ($argtype eq "buffer") {
             print $fh <<EOF;
 
-    ok = psasim_deserialise_return_buffer(&rpos, &rremain, $argname);
+    ok = psasim_deserialise_return_buffer(
+        &rpos, &rremain,
+        $argname);
     if (!ok) {
         goto fail;
     }
@@ -870,7 +946,9 @@
 
             print $fh <<EOF;
 
-    ok = psasim_deserialise_${argtype}(&rpos, &rremain, $argname);
+    ok = psasim_deserialise_${argtype}(
+        &rpos, &rremain,
+        $argname);
     if (!ok) {
         goto fail;
     }
@@ -880,10 +958,16 @@
     print $fh <<EOF;
 
 fail:
-    free(params);
-    free(result);
+    free(ser_params);
+    free(ser_result);
+EOF
+
+    print $fh <<EOF if $ret_type ne "void";
 
     return $ret_name;
+EOF
+
+    print $fh <<EOF;
 }
 EOF
 }
@@ -906,10 +990,15 @@
 {
     my ($fh, $f, $name, $is_server) = @_;
 
+    my $ret_type = $f->{return}->{type};
     my $ret_name = $f->{return}->{name};
     my $args = $f->{args};
 
-    print $fh "\n    $ret_name = $name(\n";
+    if ($ret_type eq "void") {
+        print $fh "\n    $name(\n";
+    } else {
+        print $fh "\n    $ret_name = $name(\n";
+    }
 
     print $fh "        );\n" if $#$args < 0; # If no arguments, empty arg list
 
@@ -921,6 +1010,9 @@
         if ($argtype =~ /^(const )?buffer$/) {
             my ($n1, $n2) = split(/,\s*/, $argname);
             print $fh "        $n1, $n2";
+        } elsif ($argtype =~ /^(const )?psa_key_production_parameters_t$/) {
+            my ($n1, $n2) = split(/,\s*/, $argname);
+            print $fh "        $n1, $n2";
         } else {
             $argname =~ s/^\*/\&/;      # Replace leading * with &
             if ($is_server && $argtype =~ /^psa_\w+_operation_t/) {
@@ -944,7 +1036,7 @@
 
     print $fh "\n$ret_type $name(\n";
 
-    print $fh "    void\n)\n" if $#$args < 0;   # No arguments
+    print $fh "    void\n    )\n" if $#$args < 0;   # No arguments
 
     for my $i (0 .. $#$args) {
         my $arg = $args->[$i];
@@ -956,6 +1048,10 @@
             my $const = length($1) ? "const " : "";
             my ($n1, $n2) = split(/,/, $argname);
             print $fh "    ${const}uint8_t *$n1, size_t $n2";
+        } elsif ($argtype =~ /^(const )?psa_key_production_parameters_t$/) {
+            my $const = length($1) ? "const " : "";
+            my ($n1, $n2) = split(/,/, $argname);
+            print $fh "    ${const}psa_key_production_parameters_t *$n1, size_t $n2";
         } else {
             print $fh "    $ctypename$argname";
         }
@@ -984,7 +1080,7 @@
     my %funcs = ();
     for (my $i = 0; $i <= $#src; $i++) {
         my $line = $src[$i];
-        if ($line =~ /^psa_status_t (psa_\w*)\(/) { # begin function definition
+        if ($line =~ /^(psa_status_t|uint32_t|void) (psa_\w*)\(/) { # begin function definition
             #print "have one $line\n";
             while ($line !~ /;/) {
                 $line .= $src[$i + 1];
@@ -1003,9 +1099,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 = "(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 = "(void)" if $ret_type eq "void";
                 die("ret_default for $ret_type?") unless length($ret_default);
 
                 #print "FUNC $func RET_NAME $ret_name RET_TYPE $ret_type ARGS (", join("; ", @args), ")\n";
@@ -1037,10 +1137,28 @@
                         #print("$arg: $name: might be a buffer?\n");
                         die("$arg: not a buffer 1!\n") if $i == $#args;
                         my $next = $args[$i + 1];
+                        if ($func eq "psa_key_derivation_verify_bytes" &&
+                            $arg eq "const uint8_t *expected_output" &&
+                            $next eq "size_t output_length") {
+                            $next = "size_t expected_output_length";    # doesn't follow naming convention, so override
+                        }
                         die("$arg: not a buffer 2!\n") if $next !~ /^size_t\s+(${name}_\w+)$/;
                         $i++;                   # We're using the next param here
                         my $nname = $1;
                         $name .= ", " . $nname;
+                    } elsif ($arg =~ /^((const)\s+)?psa_key_production_parameters_t\s*\*\s*(\w+)$/) {
+                        $type = "psa_key_production_parameters_t";
+                        $is_output = (length($1) == 0) ? 1 : 0;
+                        $type = "const psa_key_production_parameters_t" if !$is_output;
+                        $ctype = "";
+                        $name = $3;
+                        #print("$arg: $name: might be a psa_key_production_parameters_t?\n");
+                        die("$arg: not a psa_key_production_parameters_t 1!\n") if $i == $#args;
+                        my $next = $args[$i + 1];
+                        die("$arg: $func: $name: $next: not a psa_key_production_parameters_t 2!\n") if $next !~ /^size_t\s+(${name}_\w+)$/;
+                        $i++;                   # We're using the next param here
+                        my $nname = $1;
+                        $name .= ", " . $nname;
                     } elsif ($arg =~ /^((const)\s+)?(\w+)\s*\*(\w+)$/) {
                         ($type, $name) = ($3, "*" . $4);
                         $ctype = $1 . $type . " ";
@@ -2371,3 +2489,3068 @@
  *         results in this error code.
  */
 psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key);
+
+/**
+ * \brief Generate random bytes.
+ *
+ * \warning This function **can** fail! Callers MUST check the return status
+ *          and MUST NOT use the content of the output buffer if the return
+ *          status is not #PSA_SUCCESS.
+ *
+ * \note    To generate a key, use psa_generate_key() instead.
+ *
+ * \param[out] output       Output buffer for the generated data.
+ * \param output_size       Number of bytes to generate and output.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_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_generate_random(uint8_t *output,
+                                 size_t output_size);
+
+/** Calculate the MAC (message authentication code) of a message.
+ *
+ * \note To verify the MAC of a message against an
+ *       expected value, use psa_mac_verify() instead.
+ *       Beware that comparing integrity or authenticity data such as
+ *       MAC values with a function such as \c memcmp is risky
+ *       because the time taken by the comparison may leak information
+ *       about the MAC value which could allow an attacker to guess
+ *       a valid MAC and thereby bypass security controls.
+ *
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE.
+ * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
+ * \param[in] input         Buffer containing the input message.
+ * \param input_length      Size of the \p input buffer in bytes.
+ * \param[out] mac          Buffer where the MAC value is to be written.
+ * \param mac_size          Size of the \p mac buffer in bytes.
+ * \param[out] mac_length   On success, the number of bytes
+ *                          that make up the MAC value.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a MAC algorithm.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p mac_size is too small
+ * \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
+ *         The key could not be retrieved from storage.
+ * \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_mac_compute(mbedtls_svc_key_id_t key,
+                             psa_algorithm_t alg,
+                             const uint8_t *input,
+                             size_t input_length,
+                             uint8_t *mac,
+                             size_t mac_size,
+                             size_t *mac_length);
+
+/** Calculate the MAC of a message and compare it with a reference value.
+ *
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must allow the usage PSA_KEY_USAGE_VERIFY_MESSAGE.
+ * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
+ * \param[in] input         Buffer containing the input message.
+ * \param input_length      Size of the \p input buffer in bytes.
+ * \param[in] mac           Buffer containing the expected MAC value.
+ * \param mac_length        Size of the \p mac buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The expected MAC is identical to the actual MAC of the input.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The MAC of the message was calculated successfully, but it
+ *         differs from the expected value.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a MAC 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
+ *         The key could not be retrieved from storage.
+ * \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_mac_verify(mbedtls_svc_key_id_t key,
+                            psa_algorithm_t alg,
+                            const uint8_t *input,
+                            size_t input_length,
+                            const uint8_t *mac,
+                            size_t mac_length);
+
+/** The type of the state data structure for multipart MAC operations.
+ *
+ * Before calling any function on a MAC operation object, the application must
+ * initialize it by any of the following means:
+ * - Set the structure to all-bits-zero, for example:
+ *   \code
+ *   psa_mac_operation_t operation;
+ *   memset(&operation, 0, sizeof(operation));
+ *   \endcode
+ * - Initialize the structure to logical zero values, for example:
+ *   \code
+ *   psa_mac_operation_t operation = {0};
+ *   \endcode
+ * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT,
+ *   for example:
+ *   \code
+ *   psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+ *   \endcode
+ * - Assign the result of the function psa_mac_operation_init()
+ *   to the structure, for example:
+ *   \code
+ *   psa_mac_operation_t operation;
+ *   operation = psa_mac_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_mac_operation_s psa_mac_operation_t;
+
+/** \def PSA_MAC_OPERATION_INIT
+ *
+ * This macro returns a suitable initializer for a MAC operation object of type
+ * #psa_mac_operation_t.
+ */
+
+/** Return an initial value for a MAC operation object.
+ */
+static psa_mac_operation_t psa_mac_operation_init(void);
+
+/** Set up a multipart MAC calculation operation.
+ *
+ * This function sets up the calculation of the MAC
+ * (message authentication code) of a byte string.
+ * To verify the MAC of a message against an
+ * expected value, use psa_mac_verify_setup() instead.
+ *
+ * The sequence of operations to calculate a MAC is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Initialize the operation object with one of the methods described in the
+ *    documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT.
+ * -# Call psa_mac_sign_setup() to specify the algorithm and key.
+ * -# Call psa_mac_update() zero, one or more times, passing a fragment
+ *    of the message each time. The MAC that is calculated is the MAC
+ *    of the concatenation of these messages in order.
+ * -# At the end of the message, call psa_mac_sign_finish() to finish
+ *    calculating the MAC value and retrieve it.
+ *
+ * If an error occurs at any step after a call to psa_mac_sign_setup(), the
+ * operation will need to be reset by a call to psa_mac_abort(). The
+ * application may call psa_mac_abort() at any time after the operation
+ * has been initialized.
+ *
+ * After a successful call to psa_mac_sign_setup(), the application must
+ * eventually terminate the operation through one of the following methods:
+ * - A successful call to psa_mac_sign_finish().
+ * - A call to psa_mac_abort().
+ *
+ * \param[in,out] operation The operation object to set up. It must have
+ *                          been initialized as per the documentation for
+ *                          #psa_mac_operation_t and not yet in use.
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must remain valid until the operation terminates.
+ *                          It must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE.
+ * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a MAC 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
+ *         The key could not be retrieved from storage.
+ * \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_mac_sign_setup(psa_mac_operation_t *operation,
+                                mbedtls_svc_key_id_t key,
+                                psa_algorithm_t alg);
+
+/** Set up a multipart MAC verification operation.
+ *
+ * This function sets up the verification of the MAC
+ * (message authentication code) of a byte string against an expected value.
+ *
+ * The sequence of operations to verify a MAC is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Initialize the operation object with one of the methods described in the
+ *    documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT.
+ * -# Call psa_mac_verify_setup() to specify the algorithm and key.
+ * -# Call psa_mac_update() zero, one or more times, passing a fragment
+ *    of the message each time. The MAC that is calculated is the MAC
+ *    of the concatenation of these messages in order.
+ * -# At the end of the message, call psa_mac_verify_finish() to finish
+ *    calculating the actual MAC of the message and verify it against
+ *    the expected value.
+ *
+ * If an error occurs at any step after a call to psa_mac_verify_setup(), the
+ * operation will need to be reset by a call to psa_mac_abort(). The
+ * application may call psa_mac_abort() at any time after the operation
+ * has been initialized.
+ *
+ * After a successful call to psa_mac_verify_setup(), the application must
+ * eventually terminate the operation through one of the following methods:
+ * - A successful call to psa_mac_verify_finish().
+ * - A call to psa_mac_abort().
+ *
+ * \param[in,out] operation The operation object to set up. It must have
+ *                          been initialized as per the documentation for
+ *                          #psa_mac_operation_t and not yet in use.
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must remain valid until the operation terminates.
+ *                          It must allow the usage
+ *                          PSA_KEY_USAGE_VERIFY_MESSAGE.
+ * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \c key is not compatible with \c alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \c alg is not supported or is not a MAC 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
+ *         The key could not be retrieved from storage.
+ * \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_mac_verify_setup(psa_mac_operation_t *operation,
+                                  mbedtls_svc_key_id_t key,
+                                  psa_algorithm_t alg);
+
+/** Add a message fragment to a multipart MAC operation.
+ *
+ * The application must call psa_mac_sign_setup() or psa_mac_verify_setup()
+ * before calling this function.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_mac_abort().
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] input         Buffer containing the message fragment to add to
+ *                          the MAC calculation.
+ * \param input_length      Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \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), 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_mac_update(psa_mac_operation_t *operation,
+                            const uint8_t *input,
+                            size_t input_length);
+
+/** Finish the calculation of the MAC of a message.
+ *
+ * The application must call psa_mac_sign_setup() before calling this function.
+ * This function calculates the MAC of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_mac_update().
+ *
+ * When this function returns successfully, the operation becomes inactive.
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_mac_abort().
+ *
+ * \warning Applications should not call this function if they expect
+ *          a specific value for the MAC. Call psa_mac_verify_finish() instead.
+ *          Beware that comparing integrity or authenticity data such as
+ *          MAC values with a function such as \c memcmp is risky
+ *          because the time taken by the comparison may leak information
+ *          about the MAC value which could allow an attacker to guess
+ *          a valid MAC and thereby bypass security controls.
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[out] mac          Buffer where the MAC value is to be written.
+ * \param mac_size          Size of the \p mac buffer in bytes.
+ * \param[out] mac_length   On success, the number of bytes
+ *                          that make up the MAC value. This is always
+ *                          #PSA_MAC_LENGTH(\c key_type, \c key_bits, \c alg)
+ *                          where \c key_type and \c key_bits are the type and
+ *                          bit-size respectively of the key and \c alg is the
+ *                          MAC algorithm that is calculated.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p mac buffer is too small. You can determine a
+ *         sufficient buffer size by calling PSA_MAC_LENGTH().
+ * \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 an active mac sign
+ *         operation), 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_mac_sign_finish(psa_mac_operation_t *operation,
+                                 uint8_t *mac,
+                                 size_t mac_size,
+                                 size_t *mac_length);
+
+/** Finish the calculation of the MAC of a message and compare it with
+ * an expected value.
+ *
+ * The application must call psa_mac_verify_setup() before calling this function.
+ * This function calculates the MAC of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_mac_update(). It then
+ * compares the calculated MAC with the expected MAC passed as a
+ * parameter to this function.
+ *
+ * When this function returns successfully, the operation becomes inactive.
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_mac_abort().
+ *
+ * \note Implementations shall make the best effort to ensure that the
+ * comparison between the actual MAC and the expected MAC is performed
+ * in constant time.
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] mac           Buffer containing the expected MAC value.
+ * \param mac_length        Size of the \p mac buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The expected MAC is identical to the actual MAC of the message.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The MAC of the message was calculated successfully, but it
+ *         differs from the expected MAC.
+ * \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 an active mac verify
+ *         operation), 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_mac_verify_finish(psa_mac_operation_t *operation,
+                                   const uint8_t *mac,
+                                   size_t mac_length);
+
+/** Abort a MAC operation.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * psa_mac_sign_setup() or psa_mac_verify_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized by one of the methods described in #psa_mac_operation_t.
+ *
+ * In particular, calling psa_mac_abort() after the operation has been
+ * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or
+ * psa_mac_verify_finish() is safe and has no effect.
+ *
+ * \param[in,out] operation Initialized MAC 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 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_mac_abort(psa_mac_operation_t *operation);
+
+/** Encrypt a message using a symmetric cipher.
+ *
+ * This function encrypts a message with a random IV (initialization
+ * vector). Use the multipart operation interface with a
+ * #psa_cipher_operation_t object to provide other forms of IV.
+ *
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must allow the usage #PSA_KEY_USAGE_ENCRYPT.
+ * \param alg                   The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ * \param[in] input             Buffer containing the message to encrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[out] output           Buffer where the output is to be written.
+ *                              The output contains the IV followed by
+ *                              the ciphertext proper.
+ * \param output_size           Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the output.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a cipher algorithm.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_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_cipher_encrypt(mbedtls_svc_key_id_t key,
+                                psa_algorithm_t alg,
+                                const uint8_t *input,
+                                size_t input_length,
+                                uint8_t *output,
+                                size_t output_size,
+                                size_t *output_length);
+
+/** Decrypt a message using a symmetric cipher.
+ *
+ * This function decrypts a message encrypted with a symmetric cipher.
+ *
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must remain valid until the operation
+ *                              terminates. It must allow the usage
+ *                              #PSA_KEY_USAGE_DECRYPT.
+ * \param alg                   The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ * \param[in] input             Buffer containing the message to decrypt.
+ *                              This consists of the IV followed by the
+ *                              ciphertext proper.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[out] output           Buffer where the plaintext is to be written.
+ * \param output_size           Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the output.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a cipher algorithm.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_STORAGE_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_cipher_decrypt(mbedtls_svc_key_id_t key,
+                                psa_algorithm_t alg,
+                                const uint8_t *input,
+                                size_t input_length,
+                                uint8_t *output,
+                                size_t output_size,
+                                size_t *output_length);
+
+/** The type of the state data structure for multipart cipher operations.
+ *
+ * Before calling any function on a cipher operation object, the application
+ * must initialize it by any of the following means:
+ * - Set the structure to all-bits-zero, for example:
+ *   \code
+ *   psa_cipher_operation_t operation;
+ *   memset(&operation, 0, sizeof(operation));
+ *   \endcode
+ * - Initialize the structure to logical zero values, for example:
+ *   \code
+ *   psa_cipher_operation_t operation = {0};
+ *   \endcode
+ * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT,
+ *   for example:
+ *   \code
+ *   psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+ *   \endcode
+ * - Assign the result of the function psa_cipher_operation_init()
+ *   to the structure, for example:
+ *   \code
+ *   psa_cipher_operation_t operation;
+ *   operation = psa_cipher_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_cipher_operation_s psa_cipher_operation_t;
+
+/** \def PSA_CIPHER_OPERATION_INIT
+ *
+ * This macro returns a suitable initializer for a cipher operation object of
+ * type #psa_cipher_operation_t.
+ */
+
+/** Return an initial value for a cipher operation object.
+ */
+static psa_cipher_operation_t psa_cipher_operation_init(void);
+
+/** Set the key for a multipart symmetric encryption operation.
+ *
+ * The sequence of operations to encrypt a message with a symmetric cipher
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Initialize the operation object with one of the methods described in the
+ *    documentation for #psa_cipher_operation_t, e.g.
+ *    #PSA_CIPHER_OPERATION_INIT.
+ * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key.
+ * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to
+ *    generate or set the IV (initialization vector). You should use
+ *    psa_cipher_generate_iv() unless the protocol you are implementing
+ *    requires a specific IV value.
+ * -# Call psa_cipher_update() zero, one or more times, passing a fragment
+ *    of the message each time.
+ * -# Call psa_cipher_finish().
+ *
+ * If an error occurs at any step after a call to psa_cipher_encrypt_setup(),
+ * the operation will need to be reset by a call to psa_cipher_abort(). The
+ * application may call psa_cipher_abort() at any time after the operation
+ * has been initialized.
+ *
+ * After a successful call to psa_cipher_encrypt_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A successful call to psa_cipher_finish().
+ * - A call to psa_cipher_abort().
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized as per the documentation for
+ *                              #psa_cipher_operation_t and not yet in use.
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must remain valid until the operation
+ *                              terminates. It must allow the usage
+ *                              #PSA_KEY_USAGE_ENCRYPT.
+ * \param alg                   The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a cipher 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_cipher_encrypt_setup(psa_cipher_operation_t *operation,
+                                      mbedtls_svc_key_id_t key,
+                                      psa_algorithm_t alg);
+
+/** Set the key for a multipart symmetric decryption operation.
+ *
+ * The sequence of operations to decrypt a message with a symmetric cipher
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Initialize the operation object with one of the methods described in the
+ *    documentation for #psa_cipher_operation_t, e.g.
+ *    #PSA_CIPHER_OPERATION_INIT.
+ * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key.
+ * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the
+ *    decryption. If the IV is prepended to the ciphertext, you can call
+ *    psa_cipher_update() on a buffer containing the IV followed by the
+ *    beginning of the message.
+ * -# Call psa_cipher_update() zero, one or more times, passing a fragment
+ *    of the message each time.
+ * -# Call psa_cipher_finish().
+ *
+ * If an error occurs at any step after a call to psa_cipher_decrypt_setup(),
+ * the operation will need to be reset by a call to psa_cipher_abort(). The
+ * application may call psa_cipher_abort() at any time after the operation
+ * has been initialized.
+ *
+ * After a successful call to psa_cipher_decrypt_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A successful call to psa_cipher_finish().
+ * - A call to psa_cipher_abort().
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized as per the documentation for
+ *                              #psa_cipher_operation_t and not yet in use.
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must remain valid until the operation
+ *                              terminates. It must allow the usage
+ *                              #PSA_KEY_USAGE_DECRYPT.
+ * \param alg                   The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a cipher 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_cipher_decrypt_setup(psa_cipher_operation_t *operation,
+                                      mbedtls_svc_key_id_t key,
+                                      psa_algorithm_t alg);
+
+/** Generate an IV for a symmetric encryption operation.
+ *
+ * This function generates a random IV (initialization vector), nonce
+ * or initial counter value for the encryption operation as appropriate
+ * for the chosen algorithm, key type and key size.
+ *
+ * The application must call psa_cipher_encrypt_setup() before
+ * calling this function.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_cipher_abort().
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[out] iv               Buffer where the generated IV is to be written.
+ * \param iv_size               Size of the \p iv buffer in bytes.
+ * \param[out] iv_length        On success, the number of bytes of the
+ *                              generated IV.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p iv buffer is too small.
+ * \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, with no IV set),
+ *         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_cipher_generate_iv(psa_cipher_operation_t *operation,
+                                    uint8_t *iv,
+                                    size_t iv_size,
+                                    size_t *iv_length);
+
+/** Set the IV for a symmetric encryption or decryption operation.
+ *
+ * This function sets the IV (initialization vector), nonce
+ * or initial counter value for the encryption or decryption operation.
+ *
+ * The application must call psa_cipher_encrypt_setup() before
+ * calling this function.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_cipher_abort().
+ *
+ * \note When encrypting, applications should use psa_cipher_generate_iv()
+ * instead of this function, unless implementing a protocol that requires
+ * a non-random IV.
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[in] iv                Buffer containing the IV to use.
+ * \param iv_length             Size of the IV in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size of \p iv is not acceptable for the chosen algorithm,
+ *         or the chosen algorithm does not use an IV.
+ * \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 an active cipher
+ *         encrypt operation, with no IV set), 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_cipher_set_iv(psa_cipher_operation_t *operation,
+                               const uint8_t *iv,
+                               size_t iv_length);
+
+/** Encrypt or decrypt a message fragment in an active cipher operation.
+ *
+ * Before calling this function, you must:
+ * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup().
+ *    The choice of setup function determines whether this function
+ *    encrypts or decrypts its input.
+ * 2. If the algorithm requires an IV, call psa_cipher_generate_iv()
+ *    (recommended when encrypting) or psa_cipher_set_iv().
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_cipher_abort().
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[in] input             Buffer containing the message fragment to
+ *                              encrypt or decrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[out] output           Buffer where the output is to be written.
+ * \param output_size           Size of the \p 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_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \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, with an IV set
+ *         if required for the algorithm), 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_cipher_update(psa_cipher_operation_t *operation,
+                               const uint8_t *input,
+                               size_t input_length,
+                               uint8_t *output,
+                               size_t output_size,
+                               size_t *output_length);
+
+/** Finish encrypting or decrypting a message in a cipher operation.
+ *
+ * The application must call psa_cipher_encrypt_setup() or
+ * psa_cipher_decrypt_setup() before calling this function. The choice
+ * of setup function determines whether this function encrypts or
+ * decrypts its input.
+ *
+ * This function finishes the encryption or decryption of the message
+ * formed by concatenating the inputs passed to preceding calls to
+ * psa_cipher_update().
+ *
+ * When this function returns successfully, the operation becomes inactive.
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_cipher_abort().
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[out] output           Buffer where the output is to be written.
+ * \param output_size           Size of the \p 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_ARGUMENT
+ *         The total input size passed to this operation is not valid for
+ *         this particular algorithm. For example, the algorithm is a based
+ *         on block cipher and requires a whole number of blocks, but the
+ *         total input size is not a multiple of the block size.
+ * \retval #PSA_ERROR_INVALID_PADDING
+ *         This is a decryption operation for an algorithm that includes
+ *         padding, and the ciphertext does not contain valid padding.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \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, with an IV set
+ *         if required for the algorithm), 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_cipher_finish(psa_cipher_operation_t *operation,
+                               uint8_t *output,
+                               size_t output_size,
+                               size_t *output_length);
+
+/** Abort a cipher operation.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized as described in #psa_cipher_operation_t.
+ *
+ * In particular, calling psa_cipher_abort() after the operation has been
+ * terminated by a call to psa_cipher_abort() or psa_cipher_finish()
+ * is safe and has no effect.
+ *
+ * \param[in,out] operation     Initialized cipher 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 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_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 &sect;5.
+ *     - Curve448 (#PSA_ECC_FAMILY_MONTGOMERY, 448 bits): draw a 56-byte
+ *       string and process it as specified in RFC 7748 &sect;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 &sect;5.6.1.1.4 for Diffie-Hellman,
+ *       in FIPS 186-4 &sect;B.1.2 for DSA, and
+ *       in NIST SP 800-56A &sect;5.6.1.2.2 or
+ *       FIPS 186-4 &sect;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);
+
+/**
+ * \brief Generate a key or key pair.
+ *
+ * The key is generated randomly.
+ * Its location, usage policy, type and size are taken from \p attributes.
+ *
+ * Implementations must reject an attempt to generate a key of size 0.
+ *
+ * The following type-specific considerations apply:
+ * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR),
+ *   the public exponent is 65537.
+ *   The modulus is a product of two probabilistic primes
+ *   between 2^{n-1} and 2^n where n is the bit size specified in the
+ *   attributes.
+ *
+ * \note This function is equivalent to calling psa_generate_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.
+ * \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_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \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 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_generate_key(const psa_key_attributes_t *attributes,
+                              mbedtls_svc_key_id_t *key);
+
+/**
+ * \brief Generate a key or key pair using custom production parameters.
+ *
+ * See the description of psa_generate_key() for the operation of this
+ * function with the default production parameters. In addition, this function
+ * supports the following production customizations, described in more detail
+ * in the documentation of ::psa_key_production_parameters_t:
+ *
+ * - RSA keys: generation with a custom public exponent.
+ *
+ * \note This function is experimental and may change in future minor
+ *       versions of Mbed TLS.
+ *
+ * \param[in] attributes    The attributes for the new key.
+ * \param[in] params        Customization parameters for the key generation.
+ *                          When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ *                          with \p params_data_length = 0,
+ *                          this function is equivalent to
+ *                          psa_generate_key().
+ * \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_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \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 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_generate_key_ext(const psa_key_attributes_t *attributes,
+                                  const psa_key_production_parameters_t *params,
+                                  size_t params_data_length,
+                                  mbedtls_svc_key_id_t *key);
+
+/**
+ * \brief Sign a message with a private key. For hash-and-sign algorithms,
+ *        this includes the hashing step.
+ *
+ * \note To perform a multi-part hash-and-sign signature algorithm, first use
+ *       a multi-part hash operation and then pass the resulting hash to
+ *       psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the
+ *       hash algorithm to use.
+ *
+ * \param[in]  key              Identifier of the key to use for the operation.
+ *                              It must be an asymmetric key pair. The key must
+ *                              allow the usage #PSA_KEY_USAGE_SIGN_MESSAGE.
+ * \param[in]  alg              An asymmetric signature algorithm (PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg)
+ *                              is true), that is compatible with the type of
+ *                              \p key.
+ * \param[in]  input            The input message to sign.
+ * \param[in]  input_length     Size of the \p input buffer in bytes.
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param[in]  signature_size   Size of the \p signature buffer in bytes. This
+ *                              must be appropriate for the selected
+ *                              algorithm and key:
+ *                              - The required signature size is
+ *                                #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *                                where \c key_type and \c key_bits are the type and
+ *                                bit-size respectively of key.
+ *                              - #PSA_SIGNATURE_MAX_SIZE evaluates to the
+ *                                maximum signature size of any supported
+ *                                signature algorithm.
+ * \param[out] signature_length On success, the number of bytes that make up
+ *                              the returned signature value.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,
+ *         or it does not permit the requested algorithm.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_sign_message(mbedtls_svc_key_id_t key,
+                              psa_algorithm_t alg,
+                              const uint8_t *input,
+                              size_t input_length,
+                              uint8_t *signature,
+                              size_t signature_size,
+                              size_t *signature_length);
+
+/** \brief Verify the signature of a message with a public key, using
+ *         a hash-and-sign verification algorithm.
+ *
+ * \note To perform a multi-part hash-and-sign signature verification
+ *       algorithm, first use a multi-part hash operation to hash the message
+ *       and then pass the resulting hash to psa_verify_hash().
+ *       PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm
+ *       to use.
+ *
+ * \param[in]  key              Identifier of the key to use for the operation.
+ *                              It must be a public key or an asymmetric key
+ *                              pair. The key must allow the usage
+ *                              #PSA_KEY_USAGE_VERIFY_MESSAGE.
+ * \param[in]  alg              An asymmetric signature algorithm (PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg)
+ *                              is true), that is compatible with the type of
+ *                              \p key.
+ * \param[in]  input            The message whose signature is to be verified.
+ * \param[in]  input_length     Size of the \p input buffer in bytes.
+ * \param[in] signature         Buffer containing the signature to verify.
+ * \param[in]  signature_length Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,
+ *         or it does not permit the requested algorithm.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed signature
+ *         is not a valid signature.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_verify_message(mbedtls_svc_key_id_t key,
+                                psa_algorithm_t alg,
+                                const uint8_t *input,
+                                size_t input_length,
+                                const uint8_t *signature,
+                                size_t signature_length);
+
+/**
+ * \brief Sign a hash or short message with a private key.
+ *
+ * Note that to perform a hash-and-sign signature algorithm, you must
+ * first calculate the hash by calling psa_hash_setup(), psa_hash_update()
+ * and psa_hash_finish(), or alternatively by calling psa_hash_compute().
+ * Then pass the resulting hash as the \p hash
+ * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
+ * to determine the hash algorithm to use.
+ *
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must be an asymmetric key pair. The key must
+ *                              allow the usage #PSA_KEY_USAGE_SIGN_HASH.
+ * \param alg                   A signature algorithm (PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ *                              is true), that is compatible with
+ *                              the type of \p key.
+ * \param[in] hash              The hash or message to sign.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param signature_size        Size of the \p signature buffer in bytes.
+ * \param[out] signature_length On success, the number of bytes
+ *                              that make up the returned signature value.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key,
+                           psa_algorithm_t alg,
+                           const uint8_t *hash,
+                           size_t hash_length,
+                           uint8_t *signature,
+                           size_t signature_size,
+                           size_t *signature_length);
+
+/**
+ * \brief Verify the signature of a hash or short message using a public key.
+ *
+ * Note that to perform a hash-and-sign signature algorithm, you must
+ * first calculate the hash by calling psa_hash_setup(), psa_hash_update()
+ * and psa_hash_finish(), or alternatively by calling psa_hash_compute().
+ * Then pass the resulting hash as the \p hash
+ * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
+ * to determine the hash algorithm to use.
+ *
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must be a public key or an asymmetric key pair. The
+ *                          key must allow the usage
+ *                          #PSA_KEY_USAGE_VERIFY_HASH.
+ * \param alg               A signature algorithm (PSA_ALG_XXX
+ *                          value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ *                          is true), that is compatible with
+ *                          the type of \p key.
+ * \param[in] hash          The hash or message whose signature is to be
+ *                          verified.
+ * \param hash_length       Size of the \p hash buffer in bytes.
+ * \param[in] signature     Buffer containing the signature to verify.
+ * \param signature_length  Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The signature is valid.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed
+ *         signature is not a valid signature.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key,
+                             psa_algorithm_t alg,
+                             const uint8_t *hash,
+                             size_t hash_length,
+                             const uint8_t *signature,
+                             size_t signature_length);
+
+/**
+ * \brief Encrypt a short message with a public key.
+ *
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must be a public key or an asymmetric key
+ *                              pair. It must allow the usage
+ *                              #PSA_KEY_USAGE_ENCRYPT.
+ * \param alg                   An asymmetric encryption algorithm that is
+ *                              compatible with the type of \p key.
+ * \param[in] input             The message to encrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[in] salt              A salt or label, if supported by the
+ *                              encryption algorithm.
+ *                              If the algorithm does not support a
+ *                              salt, pass \c NULL.
+ *                              If the algorithm supports an optional
+ *                              salt and you do not want to pass a salt,
+ *                              pass \c NULL.
+ *
+ *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
+ *                                supported.
+ * \param salt_length           Size of the \p salt buffer in bytes.
+ *                              If \p salt is \c NULL, pass 0.
+ * \param[out] output           Buffer where the encrypted message is to
+ *                              be written.
+ * \param output_size           Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key,
+                                    psa_algorithm_t alg,
+                                    const uint8_t *input,
+                                    size_t input_length,
+                                    const uint8_t *salt,
+                                    size_t salt_length,
+                                    uint8_t *output,
+                                    size_t output_size,
+                                    size_t *output_length);
+
+/**
+ * \brief Decrypt a short message with a private key.
+ *
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must be an asymmetric key pair. It must
+ *                              allow the usage #PSA_KEY_USAGE_DECRYPT.
+ * \param alg                   An asymmetric encryption algorithm that is
+ *                              compatible with the type of \p key.
+ * \param[in] input             The message to decrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[in] salt              A salt or label, if supported by the
+ *                              encryption algorithm.
+ *                              If the algorithm does not support a
+ *                              salt, pass \c NULL.
+ *                              If the algorithm supports an optional
+ *                              salt and you do not want to pass a salt,
+ *                              pass \c NULL.
+ *
+ *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
+ *                                supported.
+ * \param salt_length           Size of the \p salt buffer in bytes.
+ *                              If \p salt is \c NULL, pass 0.
+ * \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 \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_INVALID_PADDING \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_asymmetric_decrypt(mbedtls_svc_key_id_t key,
+                                    psa_algorithm_t alg,
+                                    const uint8_t *input,
+                                    size_t input_length,
+                                    const uint8_t *salt,
+                                    size_t salt_length,
+                                    uint8_t *output,
+                                    size_t output_size,
+                                    size_t *output_length);
+
+/** Remove non-essential copies of key material from memory.
+ *
+ * If the key identifier designates a volatile key, this functions does not do
+ * anything and returns successfully.
+ *
+ * If the key identifier designates a persistent key, then this function will
+ * free all resources associated with the key in volatile memory. The key
+ * data in persistent storage is not affected and the key can still be used.
+ *
+ * \param key Identifier of the key to purge.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key material will have been removed from memory if it is not
+ *         currently required.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not a valid key identifier.
+ * \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_purge_key(mbedtls_svc_key_id_t key);
+
+/**
+ * \brief Export a key in binary format.
+ *
+ * The output of this function can be passed to psa_import_key() to
+ * create an equivalent object.
+ *
+ * If the implementation of psa_import_key() supports other formats
+ * beyond the format specified here, the output from psa_export_key()
+ * must use the representation specified here, not the original
+ * representation.
+ *
+ * For standard key types, the output format is as follows:
+ *
+ * - For symmetric keys (including MAC keys), the format is the
+ *   raw bytes of the key.
+ * - For DES, the key data consists of 8 bytes. The parity bits must be
+ *   correct.
+ * - For Triple-DES, the format is the concatenation of the
+ *   two or three DES keys.
+ * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format
+ *   is the non-encrypted DER encoding of the representation defined by
+ *   PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0.
+ *   ```
+ *   RSAPrivateKey ::= SEQUENCE {
+ *       version             INTEGER,  -- must be 0
+ *       modulus             INTEGER,  -- n
+ *       publicExponent      INTEGER,  -- e
+ *       privateExponent     INTEGER,  -- d
+ *       prime1              INTEGER,  -- p
+ *       prime2              INTEGER,  -- q
+ *       exponent1           INTEGER,  -- d mod (p-1)
+ *       exponent2           INTEGER,  -- d mod (q-1)
+ *       coefficient         INTEGER,  -- (inverse of q) mod p
+ *   }
+ *   ```
+ * - For elliptic curve key pairs (key types for which
+ *   #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is
+ *   a representation of the private value as a `ceiling(m/8)`-byte string
+ *   where `m` is the bit size associated with the curve, i.e. the bit size
+ *   of the order of the curve's coordinate field. This byte string is
+ *   in little-endian order for Montgomery curves (curve types
+ *   `PSA_ECC_FAMILY_CURVEXXX`), and in big-endian order for Weierstrass
+ *   curves (curve types `PSA_ECC_FAMILY_SECTXXX`, `PSA_ECC_FAMILY_SECPXXX`
+ *   and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`).
+ *   For Weierstrass curves, this is the content of the `privateKey` field of
+ *   the `ECPrivateKey` format defined by RFC 5915.  For Montgomery curves,
+ *   the format is defined by RFC 7748, and output is masked according to §5.
+ *   For twisted Edwards curves, the private key is as defined by RFC 8032
+ *   (a 32-byte string for Edwards25519, a 57-byte string for Edwards448).
+ * - For Diffie-Hellman key exchange key pairs (key types for which
+ *   #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the
+ *   format is the representation of the private key `x` as a big-endian byte
+ *   string. The length of the byte string is the private key size in bytes
+ *   (leading zeroes are not stripped).
+ * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is
+ *   true), the format is the same as for psa_export_public_key().
+ *
+ * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set.
+ *
+ * \param key               Identifier of the key to export. It must allow the
+ *                          usage #PSA_KEY_USAGE_EXPORT, unless it is a public
+ *                          key.
+ * \param[out] data         Buffer where the key data is to be written.
+ * \param data_size         Size of the \p data buffer in bytes.
+ * \param[out] data_length  On success, the number of bytes
+ *                          that make up the key data.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_EXPORT flag.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p data buffer is too small. You can determine a
+ *         sufficient buffer size by calling
+ *         #PSA_EXPORT_KEY_OUTPUT_SIZE(\c type, \c bits)
+ *         where \c type is the key type
+ *         and \c bits is the key size in bits.
+ * \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_INSUFFICIENT_MEMORY \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_export_key(mbedtls_svc_key_id_t key,
+                            uint8_t *data,
+                            size_t data_size,
+                            size_t *data_length);
+
+/**
+ * \brief Export a public key or the public part of a key pair in binary format.
+ *
+ * The output of this function can be passed to psa_import_key() to
+ * create an object that is equivalent to the public key.
+ *
+ * This specification supports a single format for each key type.
+ * Implementations may support other formats as long as the standard
+ * format is supported. Implementations that support other formats
+ * should ensure that the formats are clearly unambiguous so as to
+ * minimize the risk that an invalid input is accidentally interpreted
+ * according to a different format.
+ *
+ * For standard key types, the output format is as follows:
+ * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of
+ *   the representation defined by RFC 3279 &sect;2.3.1 as `RSAPublicKey`.
+ *   ```
+ *   RSAPublicKey ::= SEQUENCE {
+ *      modulus            INTEGER,    -- n
+ *      publicExponent     INTEGER  }  -- e
+ *   ```
+ * - For elliptic curve keys on a twisted Edwards curve (key types for which
+ *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_ECC_GET_FAMILY
+ *   returns #PSA_ECC_FAMILY_TWISTED_EDWARDS), the public key is as defined
+ *   by RFC 8032
+ *   (a 32-byte string for Edwards25519, a 57-byte string for Edwards448).
+ * - For other elliptic curve public keys (key types for which
+ *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed
+ *   representation defined by SEC1 &sect;2.3.3 as the content of an ECPoint.
+ *   Let `m` be the bit size associated with the curve, i.e. the bit size of
+ *   `q` for a curve over `F_q`. The representation consists of:
+ *      - The byte 0x04;
+ *      - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
+ *      - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
+ * - For Diffie-Hellman key exchange public keys (key types for which
+ *   #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true),
+ *   the format is the representation of the public key `y = g^x mod p` as a
+ *   big-endian byte string. The length of the byte string is the length of the
+ *   base prime `p` in bytes.
+ *
+ * Exporting a public key object or the public part of a key pair is
+ * always permitted, regardless of the key's usage flags.
+ *
+ * \param key               Identifier of the key to export.
+ * \param[out] data         Buffer where the key data is to be written.
+ * \param data_size         Size of the \p data buffer in bytes.
+ * \param[out] data_length  On success, the number of bytes
+ *                          that make up the key data.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key is neither a public key nor a key pair.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p data buffer is too small. You can determine a
+ *         sufficient buffer size by calling
+ *         #PSA_EXPORT_KEY_OUTPUT_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits)
+ *         where \c type is the key type
+ *         and \c bits is the key size in bits.
+ * \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_INSUFFICIENT_MEMORY \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_export_public_key(mbedtls_svc_key_id_t key,
+                                   uint8_t *data,
+                                   size_t data_size,
+                                   size_t *data_length);
+
+/**
+ * \brief                       Set the maximum number of ops allowed to be
+ *                              executed by an interruptible function in a
+ *                              single call.
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ * \note                        The time taken to execute a single op is
+ *                              implementation specific and depends on
+ *                              software, hardware, the algorithm, key type and
+ *                              curve chosen. Even within a single operation,
+ *                              successive ops can take differing amounts of
+ *                              time. The only guarantee is that lower values
+ *                              for \p max_ops means functions will block for a
+ *                              lesser maximum amount of time. The functions
+ *                              \c psa_sign_interruptible_get_num_ops() and
+ *                              \c psa_verify_interruptible_get_num_ops() are
+ *                              provided to help with tuning this value.
+ *
+ * \note                        This value defaults to
+ *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, which
+ *                              means the whole operation will be done in one
+ *                              go, regardless of the number of ops required.
+ *
+ * \note                        If more ops are needed to complete a
+ *                              computation, #PSA_OPERATION_INCOMPLETE will be
+ *                              returned by the function performing the
+ *                              computation. It is then the caller's
+ *                              responsibility to either call again with the
+ *                              same operation context until it returns 0 or an
+ *                              error code; or to call the relevant abort
+ *                              function if the answer is no longer required.
+ *
+ * \note                        The interpretation of \p max_ops is also
+ *                              implementation defined. On a hard real time
+ *                              system, this can indicate a hard deadline, as a
+ *                              real-time system needs a guarantee of not
+ *                              spending more than X time, however care must be
+ *                              taken in such an implementation to avoid the
+ *                              situation whereby calls just return, not being
+ *                              able to do any actual work within the allotted
+ *                              time.  On a non-real-time system, the
+ *                              implementation can be more relaxed, but again
+ *                              whether this number should be interpreted as as
+ *                              hard or soft limit or even whether a less than
+ *                              or equals as regards to ops executed in a
+ *                              single call is implementation defined.
+ *
+ * \note                        For keys in local storage when no accelerator
+ *                              driver applies, please see also the
+ *                              documentation for \c mbedtls_ecp_set_max_ops(),
+ *                              which is the internal implementation in these
+ *                              cases.
+ *
+ * \warning                     With implementations that interpret this number
+ *                              as a hard limit, setting this number too small
+ *                              may result in an infinite loop, whereby each
+ *                              call results in immediate return with no ops
+ *                              done (as there is not enough time to execute
+ *                              any), and thus no result will ever be achieved.
+ *
+ * \note                        This only applies to functions whose
+ *                              documentation mentions they may return
+ *                              #PSA_OPERATION_INCOMPLETE.
+ *
+ * \param max_ops               The maximum number of ops to be executed in a
+ *                              single call. This can be a number from 0 to
+ *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0
+ *                              is the least amount of work done per call.
+ */
+void psa_interruptible_set_max_ops(uint32_t max_ops);
+
+/**
+ * \brief                       Get the maximum number of ops allowed to be
+ *                              executed by an interruptible function in a
+ *                              single call. This will return the last
+ *                              value set by
+ *                              \c psa_interruptible_set_max_ops() or
+ *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED if
+ *                              that function has never been called.
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ * \return                      Maximum number of ops allowed to be
+ *                              executed by an interruptible function in a
+ *                              single call.
+ */
+uint32_t psa_interruptible_get_max_ops(void);
+
+/**
+ * \brief                       Get the number of ops that a hash signing
+ *                              operation has taken so far. If the operation
+ *                              has completed, then this will represent the
+ *                              number of ops required for the entire
+ *                              operation. After initialization or calling
+ *                              \c psa_sign_hash_interruptible_abort() on
+ *                              the operation, a value of 0 will be returned.
+ *
+ * \note                        This interface is guaranteed re-entrant and
+ *                              thus may be called from driver code.
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ *                              This is a helper provided to help you tune the
+ *                              value passed to \c
+ *                              psa_interruptible_set_max_ops().
+ *
+ * \param operation             The \c psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \return                      Number of ops that the operation has taken so
+ *                              far.
+ */
+uint32_t psa_sign_hash_get_num_ops(
+    const psa_sign_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief                       Get the number of ops that a hash verification
+ *                              operation has taken so far. If the operation
+ *                              has completed, then this will represent the
+ *                              number of ops required for the entire
+ *                              operation. After initialization or calling \c
+ *                              psa_verify_hash_interruptible_abort() on the
+ *                              operation, a value of 0 will be returned.
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ *                              This is a helper provided to help you tune the
+ *                              value passed to \c
+ *                              psa_interruptible_set_max_ops().
+ *
+ * \param operation             The \c
+ *                              psa_verify_hash_interruptible_operation_t to
+ *                              use. This must be initialized first.
+ *
+ * \return                      Number of ops that the operation has taken so
+ *                              far.
+ */
+uint32_t psa_verify_hash_get_num_ops(
+    const psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief                       Start signing a hash or short message with a
+ *                              private key, in an interruptible manner.
+ *
+ * \see                         \c psa_sign_hash_complete()
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ * \note                        This function combined with \c
+ *                              psa_sign_hash_complete() is equivalent to
+ *                              \c psa_sign_hash() but
+ *                              \c psa_sign_hash_complete() can return early and
+ *                              resume according to the limit set with \c
+ *                              psa_interruptible_set_max_ops() to reduce the
+ *                              maximum time spent in a function call.
+ *
+ * \note                        Users should call \c psa_sign_hash_complete()
+ *                              repeatedly on the same context after a
+ *                              successful call to this function until \c
+ *                              psa_sign_hash_complete() either returns 0 or an
+ *                              error. \c psa_sign_hash_complete() will return
+ *                              #PSA_OPERATION_INCOMPLETE if there is more work
+ *                              to do. Alternatively users can call
+ *                              \c psa_sign_hash_abort() at any point if they no
+ *                              longer want the result.
+ *
+ * \note                        If this function returns an error status, the
+ *                              operation enters an error state and must be
+ *                              aborted by calling \c psa_sign_hash_abort().
+ *
+ * \param[in, out] operation    The \c psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must be an asymmetric key pair. The key must
+ *                              allow the usage #PSA_KEY_USAGE_SIGN_HASH.
+ * \param alg                   A signature algorithm (\c PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ *                              is true), that is compatible with
+ *                              the type of \p key.
+ * \param[in] hash              The hash or message to sign.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation started successfully - call \c psa_sign_hash_complete()
+ *         with the same context to complete the operation
+ *
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_SIGN_HASH flag, or it does
+ *         not permit the requested algorithm.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         An operation has previously been started on this context, and is
+ *         still in progress.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_sign_hash_start(
+    psa_sign_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key, psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length);
+
+/**
+ * \brief                       Continue and eventually complete the action of
+ *                              signing a hash or short message with a private
+ *                              key, in an interruptible manner.
+ *
+ * \see                         \c psa_sign_hash_start()
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ * \note                        This function combined with \c
+ *                              psa_sign_hash_start() is equivalent to
+ *                              \c psa_sign_hash() but this function can return
+ *                              early and resume according to the limit set with
+ *                              \c psa_interruptible_set_max_ops() to reduce the
+ *                              maximum time spent in a function call.
+ *
+ * \note                        Users should call this function on the same
+ *                              operation object repeatedly until it either
+ *                              returns 0 or an error. This function will return
+ *                              #PSA_OPERATION_INCOMPLETE if there is more work
+ *                              to do. Alternatively users can call
+ *                              \c psa_sign_hash_abort() at any point if they no
+ *                              longer want the result.
+ *
+ * \note                        When this function returns successfully, the
+ *                              operation becomes inactive. If this function
+ *                              returns an error status, the operation enters an
+ *                              error state and must be aborted by calling
+ *                              \c psa_sign_hash_abort().
+ *
+ * \param[in, out] operation    The \c psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first, and have
+ *                              had \c psa_sign_hash_start() called with it
+ *                              first.
+ *
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param signature_size        Size of the \p signature buffer in bytes. This
+ *                              must be appropriate for the selected
+ *                              algorithm and key:
+ *                              - The required signature size is
+ *                                #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c
+ *                                key_bits, \c alg) where \c key_type and \c
+ *                                key_bits are the type and bit-size
+ *                                respectively of key.
+ *                              - #PSA_SIGNATURE_MAX_SIZE evaluates to the
+ *                                maximum signature size of any supported
+ *                                signature algorithm.
+ * \param[out] signature_length On success, the number of bytes that make up
+ *                              the returned signature value.
+ *
+ * \retval #PSA_SUCCESS
+ *         Operation completed successfully
+ *
+ * \retval #PSA_OPERATION_INCOMPLETE
+ *         Operation was interrupted due to the setting of \c
+ *         psa_interruptible_set_max_ops(). There is still work to be done.
+ *         Call this function again with the same operation object.
+ *
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \c alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \c key.
+ *
+ * \retval #PSA_ERROR_BAD_STATE
+ *         An operation was not previously started on this context via
+ *         \c psa_sign_hash_start().
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has either not been previously initialized by
+ *         psa_crypto_init() or you did not previously call
+ *         psa_sign_hash_start() with this operation object. It is
+ *         implementation-dependent whether a failure to initialize results in
+ *         this error code.
+ */
+psa_status_t psa_sign_hash_complete(
+    psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature, size_t signature_size,
+    size_t *signature_length);
+
+/**
+ * \brief                       Abort a sign hash operation.
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ * \note                        This function is the only function that clears
+ *                              the number of ops completed as part of the
+ *                              operation. Please ensure you copy this value via
+ *                              \c psa_sign_hash_get_num_ops() if required
+ *                              before calling.
+ *
+ * \note                        Aborting an operation frees all associated
+ *                              resources except for the \p operation structure
+ *                              itself. Once aborted, the operation object can
+ *                              be reused for another operation by calling \c
+ *                              psa_sign_hash_start() again.
+ *
+ * \note                        You may call this function any time after the
+ *                              operation object has been initialized. In
+ *                              particular, calling \c psa_sign_hash_abort()
+ *                              after the operation has already been terminated
+ *                              by a call to \c psa_sign_hash_abort() or
+ *                              psa_sign_hash_complete() is safe.
+ *
+ * \param[in,out] operation     Initialized sign hash operation.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation was aborted successfully.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief                       Start reading and verifying a hash or short
+ *                              message, in an interruptible manner.
+ *
+ * \see                         \c psa_verify_hash_complete()
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ * \note                        This function combined with \c
+ *                              psa_verify_hash_complete() is equivalent to
+ *                              \c psa_verify_hash() but \c
+ *                              psa_verify_hash_complete() can return early and
+ *                              resume according to the limit set with \c
+ *                              psa_interruptible_set_max_ops() to reduce the
+ *                              maximum time spent in a function.
+ *
+ * \note                        Users should call \c psa_verify_hash_complete()
+ *                              repeatedly on the same operation object after a
+ *                              successful call to this function until \c
+ *                              psa_verify_hash_complete() either returns 0 or
+ *                              an error. \c psa_verify_hash_complete() will
+ *                              return #PSA_OPERATION_INCOMPLETE if there is
+ *                              more work to do. Alternatively users can call
+ *                              \c psa_verify_hash_abort() at any point if they
+ *                              no longer want the result.
+ *
+ * \note                        If this function returns an error status, the
+ *                              operation enters an error state and must be
+ *                              aborted by calling \c psa_verify_hash_abort().
+ *
+ * \param[in, out] operation    The \c psa_verify_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \param key                   Identifier of the key to use for the operation.
+ *                              The key must allow the usage
+ *                              #PSA_KEY_USAGE_VERIFY_HASH.
+ * \param alg                   A signature algorithm (\c PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ *                              is true), that is compatible with
+ *                              the type of \p key.
+ * \param[in] hash              The hash whose signature is to be verified.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ * \param[in] signature         Buffer containing the signature to verify.
+ * \param signature_length      Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation started successfully - please call \c
+ *         psa_verify_hash_complete() with the same context to complete the
+ *         operation.
+ *
+ * \retval #PSA_ERROR_BAD_STATE
+ *         Another operation has already been started on this context, and is
+ *         still in progress.
+ *
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_VERIFY_HASH flag, or it does
+ *         not permit the requested algorithm.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_verify_hash_start(
+    psa_verify_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key, psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length);
+
+/**
+ * \brief                       Continue and eventually complete the action of
+ *                              reading and verifying a hash or short message
+ *                              signed with a private key, in an interruptible
+ *                              manner.
+ *
+ * \see                         \c psa_verify_hash_start()
+ *
+ * \warning                     This is a beta API, and thus subject to change
+ *                              at any point. It is not bound by the usual
+ *                              interface stability promises.
+ *
+ * \note                        This function combined with \c
+ *                              psa_verify_hash_start() is equivalent to
+ *                              \c psa_verify_hash() but this function can
+ *                              return early and resume according to the limit
+ *                              set with \c psa_interruptible_set_max_ops() to
+ *                              reduce the maximum time spent in a function
+ *                              call.
+ *
+ * \note                        Users should call this function on the same
+ *                              operation object repeatedly until it either
+ *                              returns 0 or an error. This function will return
+ *                              #PSA_OPERATION_INCOMPLETE if there is more work
+ *                              to do. Alternatively users can call
+ *                              \c psa_verify_hash_abort() at any point if they
+ *                              no longer want the result.
+ *
+ * \note                        When this function returns successfully, the
+ *                              operation becomes inactive. If this function
+ *                              returns an error status, the operation enters an
+ *                              error state and must be aborted by calling
+ *                              \c psa_verify_hash_abort().
+ *
+ * \param[in, out] operation    The \c psa_verify_hash_interruptible_operation_t
+ *                              to use. This must be initialized first, and have
+ *                              had \c psa_verify_hash_start() called with it
+ *                              first.
+ *
+ * \retval #PSA_SUCCESS
+ *         Operation completed successfully, and the passed signature is valid.
+ *
+ * \retval #PSA_OPERATION_INCOMPLETE
+ *         Operation was interrupted due to the setting of \c
+ *         psa_interruptible_set_max_ops(). There is still work to be done.
+ *         Call this function again with the same operation object.
+ *
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed
+ *         signature is not a valid signature.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         An operation was not previously started on this context via
+ *         \c psa_verify_hash_start().
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has either not been previously initialized by
+ *         psa_crypto_init() or you did not previously call
+ *         psa_verify_hash_start() on this object. It is
+ *         implementation-dependent whether a failure to initialize results in
+ *         this error code.
+ */
+psa_status_t psa_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief                     Abort a verify hash operation.
+ *
+ * \warning                   This is a beta API, and thus subject to change at
+ *                            any point. It is not bound by the usual interface
+ *                            stability promises.
+ *
+ * \note                      This function is the only function that clears the
+ *                            number of ops completed as part of the operation.
+ *                            Please ensure you copy this value via
+ *                            \c psa_verify_hash_get_num_ops() if required
+ *                            before calling.
+ *
+ * \note                      Aborting an operation frees all associated
+ *                            resources except for the operation structure
+ *                            itself. Once aborted, the operation object can be
+ *                            reused for another operation by calling \c
+ *                            psa_verify_hash_start() again.
+ *
+ * \note                      You may call this function any time after the
+ *                            operation object has been initialized.
+ *                            In particular, calling \c psa_verify_hash_abort()
+ *                            after the operation has already been terminated by
+ *                            a call to \c psa_verify_hash_abort() or
+ *                            psa_verify_hash_complete() is safe.
+ *
+ * \param[in,out] operation   Initialized verify hash operation.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation was aborted successfully.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *operation);
+
+/** Make a copy of a key.
+ *
+ * Copy key material from one location to another.
+ *
+ * This function is primarily useful to copy a key from one location
+ * to another, since it populates a key using the material from
+ * another key which may have a different lifetime.
+ *
+ * This function may be used to share a key with a different party,
+ * subject to implementation-defined restrictions on key sharing.
+ *
+ * The policy on the source key must have the usage flag
+ * #PSA_KEY_USAGE_COPY set.
+ * This flag is sufficient to permit the copy if the key has the lifetime
+ * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT.
+ * Some secure elements do not provide a way to copy a key without
+ * making it extractable from the secure element. If a key is located
+ * in such a secure element, then the key must have both usage flags
+ * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make
+ * a copy of the key outside the secure element.
+ *
+ * The resulting key may only be used in a way that conforms to
+ * both the policy of the original key and the policy specified in
+ * the \p attributes parameter:
+ * - The usage flags on the resulting key are the bitwise-and of the
+ *   usage flags on the source policy and the usage flags in \p attributes.
+ * - If both allow the same algorithm or wildcard-based
+ *   algorithm policy, the resulting key has the same algorithm policy.
+ * - If either of the policies allows an algorithm and the other policy
+ *   allows a wildcard-based algorithm policy that includes this algorithm,
+ *   the resulting key allows the same algorithm.
+ * - If the policies do not allow any algorithm in common, this function
+ *   fails with the status #PSA_ERROR_INVALID_ARGUMENT.
+ *
+ * The effect of this function on implementation-defined attributes is
+ * implementation-defined.
+ *
+ * \param source_key        The key to copy. It must allow the usage
+ *                          #PSA_KEY_USAGE_COPY. If a private or secret key is
+ *                          being copied outside of a secure element it must
+ *                          also allow #PSA_KEY_USAGE_EXPORT.
+ * \param[in] attributes    The attributes for the new key.
+ *                          They are used as follows:
+ *                          - The key type and size may be 0. If either is
+ *                            nonzero, it must match the corresponding
+ *                            attribute of the source key.
+ *                          - The key location (the lifetime and, for
+ *                            persistent keys, the key identifier) is
+ *                            used directly.
+ *                          - The policy constraints (usage flags and
+ *                            algorithm policy) are combined from
+ *                            the source key and \p attributes so that
+ *                            both sets of restrictions apply, as
+ *                            described in the documentation of this function.
+ * \param[out] target_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 \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ *         \p source_key is invalid.
+ * \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_INVALID_ARGUMENT
+ *         The lifetime or identifier in \p attributes are invalid, or
+ *         the policy constraints on the source and specified in
+ *         \p attributes are incompatible, or
+ *         \p attributes specifies a key type or key size
+ *         which does not match the attributes of the source key.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The source key does not have the #PSA_KEY_USAGE_COPY usage flag, or
+ *         the source key is not exportable and its lifetime does not
+ *         allow copying it to the target's lifetime.
+ * \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_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_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_copy_key(mbedtls_svc_key_id_t source_key,
+                          const psa_key_attributes_t *attributes,
+                          mbedtls_svc_key_id_t *target_key);
+
+/** Reset a key attribute structure to a freshly initialized state.
+ *
+ * You must initialize the attribute structure as described in the
+ * documentation of the type #psa_key_attributes_t before calling this
+ * function. Once the structure has been initialized, you may call this
+ * function at any time.
+ *
+ * This function frees any auxiliary resources that the structure
+ * may contain.
+ *
+ * \param[in,out] attributes    The attribute structure to reset.
+ */
+void psa_reset_key_attributes(psa_key_attributes_t *attributes);
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 651e046..e655e07 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
@@ -63,8 +63,10 @@
 
 #define MAX_LIVE_HANDLES_PER_CLASS   100        /* this many slots */
 
-static psa_hash_operation_t hash_operations[MAX_LIVE_HANDLES_PER_CLASS];
-static psasim_client_handle_t hash_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
+static psa_hash_operation_t hash_operations[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t hash_operation_handles[
+    MAX_LIVE_HANDLES_PER_CLASS];
 static psasim_client_handle_t next_hash_operation_handle = 1;
 
 /* Get a free slot */
@@ -101,8 +103,10 @@
     return -1;  /* not found */
 }
 
-static psa_aead_operation_t aead_operations[MAX_LIVE_HANDLES_PER_CLASS];
-static psasim_client_handle_t aead_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
+static psa_aead_operation_t aead_operations[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t aead_operation_handles[
+    MAX_LIVE_HANDLES_PER_CLASS];
 static psasim_client_handle_t next_aead_operation_handle = 1;
 
 /* Get a free slot */
@@ -139,6 +143,206 @@
     return -1;  /* not found */
 }
 
+static psa_mac_operation_t mac_operations[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t mac_operation_handles[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t next_mac_operation_handle = 1;
+
+/* Get a free slot */
+static ssize_t allocate_mac_operation_slot(void)
+{
+    psasim_client_handle_t handle = next_mac_operation_handle++;
+    if (next_mac_operation_handle == 0) {      /* wrapped around */
+        FATAL("Mac operation handle wrapped");
+    }
+
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (mac_operation_handles[i] == 0) {
+            mac_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_mac_slot_by_handle(psasim_client_handle_t handle)
+{
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (mac_operation_handles[i] == handle) {
+            return i;
+        }
+    }
+
+    ERROR("Unable to find slot by handle %u", handle);
+
+    return -1;  /* not found */
+}
+
+static psa_cipher_operation_t cipher_operations[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t cipher_operation_handles[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t next_cipher_operation_handle = 1;
+
+/* Get a free slot */
+static ssize_t allocate_cipher_operation_slot(void)
+{
+    psasim_client_handle_t handle = next_cipher_operation_handle++;
+    if (next_cipher_operation_handle == 0) {      /* wrapped around */
+        FATAL("Cipher operation handle wrapped");
+    }
+
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (cipher_operation_handles[i] == 0) {
+            cipher_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_cipher_slot_by_handle(psasim_client_handle_t handle)
+{
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (cipher_operation_handles[i] == handle) {
+            return i;
+        }
+    }
+
+    ERROR("Unable to find slot by handle %u", handle);
+
+    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 */
+}
+
+static psa_sign_hash_interruptible_operation_t sign_hash_interruptible_operations[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t sign_hash_interruptible_operation_handles[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t next_sign_hash_interruptible_operation_handle = 1;
+
+/* Get a free slot */
+static ssize_t allocate_sign_hash_interruptible_operation_slot(void)
+{
+    psasim_client_handle_t handle = next_sign_hash_interruptible_operation_handle++;
+    if (next_sign_hash_interruptible_operation_handle == 0) {      /* wrapped around */
+        FATAL("Sign_hash_interruptible operation handle wrapped");
+    }
+
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (sign_hash_interruptible_operation_handles[i] == 0) {
+            sign_hash_interruptible_operation_handles[i] = handle;
+            return i;
+        }
+    }
+
+    ERROR("All slots are currently used. Unable to allocate a new one.");
+
+    return -1;  /* all in use */
+}
+
+/* Find the slot given the handle */
+static ssize_t find_sign_hash_interruptible_slot_by_handle(psasim_client_handle_t handle)
+{
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (sign_hash_interruptible_operation_handles[i] == handle) {
+            return i;
+        }
+    }
+
+    ERROR("Unable to find slot by handle %u", handle);
+
+    return -1;  /* not found */
+}
+
+static psa_verify_hash_interruptible_operation_t verify_hash_interruptible_operations[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t verify_hash_interruptible_operation_handles[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t next_verify_hash_interruptible_operation_handle = 1;
+
+/* Get a free slot */
+static ssize_t allocate_verify_hash_interruptible_operation_slot(void)
+{
+    psasim_client_handle_t handle = next_verify_hash_interruptible_operation_handle++;
+    if (next_verify_hash_interruptible_operation_handle == 0) {      /* wrapped around */
+        FATAL("Verify_hash_interruptible operation handle wrapped");
+    }
+
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (verify_hash_interruptible_operation_handles[i] == 0) {
+            verify_hash_interruptible_operation_handles[i] = handle;
+            return i;
+        }
+    }
+
+    ERROR("All slots are currently used. Unable to allocate a new one.");
+
+    return -1;  /* all in use */
+}
+
+/* Find the slot given the handle */
+static ssize_t find_verify_hash_interruptible_slot_by_handle(psasim_client_handle_t handle)
+{
+    for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+        if (verify_hash_interruptible_operation_handles[i] == handle) {
+            return i;
+        }
+    }
+
+    ERROR("Unable to find slot by handle %u", handle);
+
+    return -1;  /* not found */
+}
+
 size_t psasim_serialise_begin_needs(void)
 {
     /* The serialisation buffer will
@@ -213,7 +417,8 @@
     return 1;
 }
 
-size_t psasim_serialise_unsigned_int_needs(unsigned int value)
+size_t psasim_serialise_unsigned_int_needs(
+    unsigned int value)
 {
     return sizeof(value);
 }
@@ -248,7 +453,8 @@
     return 1;
 }
 
-size_t psasim_serialise_int_needs(int value)
+size_t psasim_serialise_int_needs(
+    int value)
 {
     return sizeof(value);
 }
@@ -283,7 +489,8 @@
     return 1;
 }
 
-size_t psasim_serialise_size_t_needs(size_t value)
+size_t psasim_serialise_size_t_needs(
+    size_t value)
 {
     return sizeof(value);
 }
@@ -318,6 +525,114 @@
     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_uint32_t_needs(
+    uint32_t value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_uint32_t(uint8_t **pos,
+                              size_t *remaining,
+                              uint32_t value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_uint32_t(uint8_t **pos,
+                                size_t *remaining,
+                                uint32_t *value)
+{
+    if (*remaining < sizeof(*value)) {
+        return 0;
+    }
+
+    memcpy(value, *pos, sizeof(*value));
+
+    *pos += sizeof(*value);
+    *remaining -= sizeof(*value);
+
+    return 1;
+}
+
+size_t psasim_serialise_uint64_t_needs(
+    uint64_t value)
+{
+    return sizeof(value);
+}
+
+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;
@@ -420,7 +735,102 @@
     return 1;
 }
 
-size_t psasim_serialise_psa_status_t_needs(psa_status_t value)
+#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);
 }
@@ -439,7 +849,8 @@
     return psasim_deserialise_int(pos, remaining, value);
 }
 
-size_t psasim_serialise_psa_algorithm_t_needs(psa_algorithm_t value)
+size_t psasim_serialise_psa_algorithm_t_needs(
+    psa_algorithm_t value)
 {
     return psasim_serialise_unsigned_int_needs(value);
 }
@@ -458,7 +869,28 @@
     return psasim_deserialise_unsigned_int(pos, remaining, value);
 }
 
-size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t 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);
 }
@@ -493,7 +925,8 @@
     return 1;
 }
 
-size_t psasim_server_serialise_psa_hash_operation_t_needs(psa_hash_operation_t *operation)
+size_t psasim_server_serialise_psa_hash_operation_t_needs(
+    psa_hash_operation_t *operation)
 {
     (void) operation;
 
@@ -551,7 +984,8 @@
     return 1;
 }
 
-size_t psasim_serialise_psa_aead_operation_t_needs(psa_aead_operation_t value)
+size_t psasim_serialise_psa_aead_operation_t_needs(
+    psa_aead_operation_t value)
 {
     return sizeof(value);
 }
@@ -586,7 +1020,8 @@
     return 1;
 }
 
-size_t psasim_server_serialise_psa_aead_operation_t_needs(psa_aead_operation_t *operation)
+size_t psasim_server_serialise_psa_aead_operation_t_needs(
+    psa_aead_operation_t *operation)
 {
     (void) operation;
 
@@ -644,7 +1079,8 @@
     return 1;
 }
 
-size_t psasim_serialise_psa_key_attributes_t_needs(psa_key_attributes_t value)
+size_t psasim_serialise_psa_key_attributes_t_needs(
+    psa_key_attributes_t value)
 {
     return sizeof(value);
 }
@@ -679,7 +1115,483 @@
     return 1;
 }
 
-size_t psasim_serialise_mbedtls_svc_key_id_t_needs(mbedtls_svc_key_id_t value)
+size_t psasim_serialise_psa_mac_operation_t_needs(
+    psa_mac_operation_t value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_psa_mac_operation_t(uint8_t **pos,
+                                         size_t *remaining,
+                                         psa_mac_operation_t value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_psa_mac_operation_t(uint8_t **pos,
+                                           size_t *remaining,
+                                           psa_mac_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_mac_operation_t_needs(
+    psa_mac_operation_t *operation)
+{
+    (void) operation;
+
+    /* We will actually return a handle */
+    return sizeof(psasim_operation_t);
+}
+
+int psasim_server_serialise_psa_mac_operation_t(uint8_t **pos,
+                                                size_t *remaining,
+                                                psa_mac_operation_t *operation)
+{
+    psasim_operation_t client_operation;
+
+    if (*remaining < sizeof(client_operation)) {
+        return 0;
+    }
+
+    ssize_t slot = operation - mac_operations;
+
+    client_operation.handle = mac_operation_handles[slot];
+
+    memcpy(*pos, &client_operation, sizeof(client_operation));
+    *pos += sizeof(client_operation);
+
+    return 1;
+}
+
+int psasim_server_deserialise_psa_mac_operation_t(uint8_t **pos,
+                                                  size_t *remaining,
+                                                  psa_mac_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_mac_operation_slot();
+    } else {
+        slot = find_mac_slot_by_handle(client_operation.handle);
+    }
+
+    if (slot < 0) {
+        return 0;
+    }
+
+    *operation = &mac_operations[slot];
+
+    return 1;
+}
+
+size_t psasim_serialise_psa_cipher_operation_t_needs(
+    psa_cipher_operation_t value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_psa_cipher_operation_t(uint8_t **pos,
+                                            size_t *remaining,
+                                            psa_cipher_operation_t value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_psa_cipher_operation_t(uint8_t **pos,
+                                              size_t *remaining,
+                                              psa_cipher_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_cipher_operation_t_needs(
+    psa_cipher_operation_t *operation)
+{
+    (void) operation;
+
+    /* We will actually return a handle */
+    return sizeof(psasim_operation_t);
+}
+
+int psasim_server_serialise_psa_cipher_operation_t(uint8_t **pos,
+                                                   size_t *remaining,
+                                                   psa_cipher_operation_t *operation)
+{
+    psasim_operation_t client_operation;
+
+    if (*remaining < sizeof(client_operation)) {
+        return 0;
+    }
+
+    ssize_t slot = operation - cipher_operations;
+
+    client_operation.handle = cipher_operation_handles[slot];
+
+    memcpy(*pos, &client_operation, sizeof(client_operation));
+    *pos += sizeof(client_operation);
+
+    return 1;
+}
+
+int psasim_server_deserialise_psa_cipher_operation_t(uint8_t **pos,
+                                                     size_t *remaining,
+                                                     psa_cipher_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_cipher_operation_slot();
+    } else {
+        slot = find_cipher_slot_by_handle(client_operation.handle);
+    }
+
+    if (slot < 0) {
+        return 0;
+    }
+
+    *operation = &cipher_operations[slot];
+
+    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_psa_sign_hash_interruptible_operation_t_needs(
+    psa_sign_hash_interruptible_operation_t value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+                                                             size_t *remaining,
+                                                             psa_sign_hash_interruptible_operation_t value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+                                                               size_t *remaining,
+                                                               psa_sign_hash_interruptible_operation_t *value)
+{
+    if (*remaining < sizeof(*value)) {
+        return 0;
+    }
+
+    memcpy(value, *pos, sizeof(*value));
+
+    *pos += sizeof(*value);
+    *remaining -= sizeof(*value);
+
+    return 1;
+}
+
+size_t psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(
+    psa_sign_hash_interruptible_operation_t *operation)
+{
+    (void) operation;
+
+    /* We will actually return a handle */
+    return sizeof(psasim_operation_t);
+}
+
+int psasim_server_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+                                                                    size_t *remaining,
+                                                                    psa_sign_hash_interruptible_operation_t *operation)
+{
+    psasim_operation_t client_operation;
+
+    if (*remaining < sizeof(client_operation)) {
+        return 0;
+    }
+
+    ssize_t slot = operation - sign_hash_interruptible_operations;
+
+    client_operation.handle = sign_hash_interruptible_operation_handles[slot];
+
+    memcpy(*pos, &client_operation, sizeof(client_operation));
+    *pos += sizeof(client_operation);
+
+    return 1;
+}
+
+int psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+                                                                      size_t *remaining,
+                                                                      psa_sign_hash_interruptible_operation_t **operation)
+{
+    psasim_operation_t client_operation;
+
+    if (*remaining < sizeof(psasim_operation_t)) {
+        return 0;
+    }
+
+    memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
+    *pos += sizeof(psasim_operation_t);
+    *remaining -= sizeof(psasim_operation_t);
+
+    ssize_t slot;
+    if (client_operation.handle == 0) {         /* We need a new handle */
+        slot = allocate_sign_hash_interruptible_operation_slot();
+    } else {
+        slot = find_sign_hash_interruptible_slot_by_handle(client_operation.handle);
+    }
+
+    if (slot < 0) {
+        return 0;
+    }
+
+    *operation = &sign_hash_interruptible_operations[slot];
+
+    return 1;
+}
+
+size_t psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(
+    psa_verify_hash_interruptible_operation_t value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+                                                               size_t *remaining,
+                                                               psa_verify_hash_interruptible_operation_t value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+                                                                 size_t *remaining,
+                                                                 psa_verify_hash_interruptible_operation_t *value)
+{
+    if (*remaining < sizeof(*value)) {
+        return 0;
+    }
+
+    memcpy(value, *pos, sizeof(*value));
+
+    *pos += sizeof(*value);
+    *remaining -= sizeof(*value);
+
+    return 1;
+}
+
+size_t psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(
+    psa_verify_hash_interruptible_operation_t *operation)
+{
+    (void) operation;
+
+    /* We will actually return a handle */
+    return sizeof(psasim_operation_t);
+}
+
+int psasim_server_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+                                                                      size_t *remaining,
+                                                                      psa_verify_hash_interruptible_operation_t *operation)
+{
+    psasim_operation_t client_operation;
+
+    if (*remaining < sizeof(client_operation)) {
+        return 0;
+    }
+
+    ssize_t slot = operation - verify_hash_interruptible_operations;
+
+    client_operation.handle = verify_hash_interruptible_operation_handles[slot];
+
+    memcpy(*pos, &client_operation, sizeof(client_operation));
+    *pos += sizeof(client_operation);
+
+    return 1;
+}
+
+int psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+                                                                        size_t *remaining,
+                                                                        psa_verify_hash_interruptible_operation_t **operation)
+{
+    psasim_operation_t client_operation;
+
+    if (*remaining < sizeof(psasim_operation_t)) {
+        return 0;
+    }
+
+    memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
+    *pos += sizeof(psasim_operation_t);
+    *remaining -= sizeof(psasim_operation_t);
+
+    ssize_t slot;
+    if (client_operation.handle == 0) {         /* We need a new handle */
+        slot = allocate_verify_hash_interruptible_operation_slot();
+    } else {
+        slot = find_verify_hash_interruptible_slot_by_handle(client_operation.handle);
+    }
+
+    if (slot < 0) {
+        return 0;
+    }
+
+    *operation = &verify_hash_interruptible_operations[slot];
+
+    return 1;
+}
+
+size_t psasim_serialise_mbedtls_svc_key_id_t_needs(
+    mbedtls_svc_key_id_t value)
 {
     return sizeof(value);
 }
@@ -716,8 +1628,32 @@
 
 void psa_sim_serialize_reset(void)
 {
-    memset(hash_operation_handles, 0, sizeof(hash_operation_handles));
-    memset(hash_operations, 0, sizeof(hash_operations));
-    memset(aead_operation_handles, 0, sizeof(aead_operation_handles));
-    memset(aead_operations, 0, sizeof(aead_operations));
+    memset(hash_operation_handles, 0,
+           sizeof(hash_operation_handles));
+    memset(hash_operations, 0,
+           sizeof(hash_operations));
+    memset(aead_operation_handles, 0,
+           sizeof(aead_operation_handles));
+    memset(aead_operations, 0,
+           sizeof(aead_operations));
+    memset(mac_operation_handles, 0,
+           sizeof(mac_operation_handles));
+    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));
+    memset(sign_hash_interruptible_operation_handles, 0,
+           sizeof(sign_hash_interruptible_operation_handles));
+    memset(sign_hash_interruptible_operations, 0,
+           sizeof(sign_hash_interruptible_operations));
+    memset(verify_hash_interruptible_operation_handles, 0,
+           sizeof(verify_hash_interruptible_operation_handles));
+    memset(verify_hash_interruptible_operations, 0,
+           sizeof(verify_hash_interruptible_operations));
 }
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.h b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
index 537730c..f85faad 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
@@ -107,7 +107,8 @@
  *                           \c psasim_serialise_unsigned_int() to serialise
  *                           the given value.
  */
-size_t psasim_serialise_unsigned_int_needs(unsigned int value);
+size_t psasim_serialise_unsigned_int_needs(
+    unsigned int value);
 
 /** Serialise an `unsigned int` into a buffer.
  *
@@ -149,7 +150,8 @@
  *                           \c psasim_serialise_int() to serialise
  *                           the given value.
  */
-size_t psasim_serialise_int_needs(int value);
+size_t psasim_serialise_int_needs(
+    int value);
 
 /** Serialise an `int` into a buffer.
  *
@@ -191,7 +193,8 @@
  *                           \c psasim_serialise_size_t() to serialise
  *                           the given value.
  */
-size_t psasim_serialise_size_t_needs(size_t value);
+size_t psasim_serialise_size_t_needs(
+    size_t value);
 
 /** Serialise a `size_t` into a buffer.
  *
@@ -222,6 +225,135 @@
                               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_uint32_t()
+ *  to serialise an `uint32_t`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_uint32_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_uint32_t_needs(
+    uint32_t value);
+
+/** Serialise an `uint32_t` into a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_uint32_t(uint8_t **pos,
+                              size_t *remaining,
+                              uint32_t value);
+
+/** Deserialise an `uint32_t` from a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to an `uint32_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_uint32_t(uint8_t **pos,
+                                size_t *remaining,
+                                uint32_t *value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_uint64_t()
+ *  to serialise an `uint64_t`.
+ *
+ * \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 +421,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`.
  *
@@ -300,7 +482,8 @@
  *                           \c psasim_serialise_psa_status_t() to serialise
  *                           the given value.
  */
-size_t psasim_serialise_psa_status_t_needs(psa_status_t value);
+size_t psasim_serialise_psa_status_t_needs(
+    psa_status_t value);
 
 /** Serialise a `psa_status_t` into a buffer.
  *
@@ -342,7 +525,8 @@
  *                           \c psasim_serialise_psa_algorithm_t() to serialise
  *                           the given value.
  */
-size_t psasim_serialise_psa_algorithm_t_needs(psa_algorithm_t value);
+size_t psasim_serialise_psa_algorithm_t_needs(
+    psa_algorithm_t value);
 
 /** Serialise a `psa_algorithm_t` into a buffer.
  *
@@ -373,6 +557,49 @@
                                        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`.
  *
@@ -384,7 +611,8 @@
  *                           \c psasim_serialise_psa_hash_operation_t() to serialise
  *                           the given value.
  */
-size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t value);
+size_t psasim_serialise_psa_hash_operation_t_needs(
+    psa_hash_operation_t value);
 
 /** Serialise a `psa_hash_operation_t` into a buffer.
  *
@@ -426,7 +654,8 @@
  *                           \c psasim_serialise_psa_hash_operation_t() to serialise
  *                           the given value.
  */
-size_t psasim_server_serialise_psa_hash_operation_t_needs(psa_hash_operation_t *value);
+size_t psasim_server_serialise_psa_hash_operation_t_needs(
+    psa_hash_operation_t *value);
 
 /** Serialise a `psa_hash_operation_t` into a buffer on the server side.
  *
@@ -468,7 +697,8 @@
  *                           \c psasim_serialise_psa_aead_operation_t() to serialise
  *                           the given value.
  */
-size_t psasim_serialise_psa_aead_operation_t_needs(psa_aead_operation_t value);
+size_t psasim_serialise_psa_aead_operation_t_needs(
+    psa_aead_operation_t value);
 
 /** Serialise a `psa_aead_operation_t` into a buffer.
  *
@@ -510,7 +740,8 @@
  *                           \c psasim_serialise_psa_aead_operation_t() to serialise
  *                           the given value.
  */
-size_t psasim_server_serialise_psa_aead_operation_t_needs(psa_aead_operation_t *value);
+size_t psasim_server_serialise_psa_aead_operation_t_needs(
+    psa_aead_operation_t *value);
 
 /** Serialise a `psa_aead_operation_t` into a buffer on the server side.
  *
@@ -552,7 +783,8 @@
  *                           \c psasim_serialise_psa_key_attributes_t() to serialise
  *                           the given value.
  */
-size_t psasim_serialise_psa_key_attributes_t_needs(psa_key_attributes_t value);
+size_t psasim_serialise_psa_key_attributes_t_needs(
+    psa_key_attributes_t value);
 
 /** Serialise a `psa_key_attributes_t` into a buffer.
  *
@@ -583,6 +815,436 @@
                                             size_t *remaining,
                                             psa_key_attributes_t *value);
 
+/** Return how much buffer space is needed by \c psasim_serialise_psa_mac_operation_t()
+ *  to serialise a `psa_mac_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_mac_operation_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_psa_mac_operation_t_needs(
+    psa_mac_operation_t value);
+
+/** Serialise a `psa_mac_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_mac_operation_t(uint8_t **pos,
+                                         size_t *remaining,
+                                         psa_mac_operation_t value);
+
+/** Deserialise a `psa_mac_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_mac_operation_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_mac_operation_t(uint8_t **pos,
+                                           size_t *remaining,
+                                           psa_mac_operation_t *value);
+
+/** Return how much buffer space is needed by \c psasim_server_serialise_psa_mac_operation_t()
+ *  to serialise a `psa_mac_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_mac_operation_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_server_serialise_psa_mac_operation_t_needs(
+    psa_mac_operation_t *value);
+
+/** Serialise a `psa_mac_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_mac_operation_t(uint8_t **pos,
+                                                size_t *remaining,
+                                                psa_mac_operation_t *value);
+
+/** Deserialise a `psa_mac_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_mac_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_mac_operation_t(uint8_t **pos,
+                                                  size_t *remaining,
+                                                  psa_mac_operation_t **value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_psa_cipher_operation_t()
+ *  to serialise a `psa_cipher_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_cipher_operation_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_psa_cipher_operation_t_needs(
+    psa_cipher_operation_t value);
+
+/** Serialise a `psa_cipher_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_cipher_operation_t(uint8_t **pos,
+                                            size_t *remaining,
+                                            psa_cipher_operation_t value);
+
+/** Deserialise a `psa_cipher_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_cipher_operation_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_cipher_operation_t(uint8_t **pos,
+                                              size_t *remaining,
+                                              psa_cipher_operation_t *value);
+
+/** Return how much buffer space is needed by \c psasim_server_serialise_psa_cipher_operation_t()
+ *  to serialise a `psa_cipher_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_cipher_operation_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_server_serialise_psa_cipher_operation_t_needs(
+    psa_cipher_operation_t *value);
+
+/** Serialise a `psa_cipher_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_cipher_operation_t(uint8_t **pos,
+                                                   size_t *remaining,
+                                                   psa_cipher_operation_t *value);
+
+/** Deserialise a `psa_cipher_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_cipher_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_cipher_operation_t(uint8_t **pos,
+                                                     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_psa_sign_hash_interruptible_operation_t()
+ *  to serialise a `psa_sign_hash_interruptible_operation_t`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_psa_sign_hash_interruptible_operation_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(
+    psa_sign_hash_interruptible_operation_t value);
+
+/** Serialise a `psa_sign_hash_interruptible_operation_t` into a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+                                                             size_t *remaining,
+                                                             psa_sign_hash_interruptible_operation_t value);
+
+/** Deserialise a `psa_sign_hash_interruptible_operation_t` from a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to a `psa_sign_hash_interruptible_operation_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+                                                               size_t *remaining,
+                                                               psa_sign_hash_interruptible_operation_t *value);
+
+/** Return how much buffer space is needed by \c psasim_server_serialise_psa_sign_hash_interruptible_operation_t()
+ *  to serialise a `psa_sign_hash_interruptible_operation_t`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_psa_sign_hash_interruptible_operation_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(
+    psa_sign_hash_interruptible_operation_t *value);
+
+/** Serialise a `psa_sign_hash_interruptible_operation_t` into a buffer on the server side.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_server_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+                                                                    size_t *remaining,
+                                                                    psa_sign_hash_interruptible_operation_t *value);
+
+/** Deserialise a `psa_sign_hash_interruptible_operation_t` from a buffer on the server side.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to a `psa_sign_hash_interruptible_operation_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos,
+                                                                      size_t *remaining,
+                                                                      psa_sign_hash_interruptible_operation_t **value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_psa_verify_hash_interruptible_operation_t()
+ *  to serialise a `psa_verify_hash_interruptible_operation_t`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_psa_verify_hash_interruptible_operation_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(
+    psa_verify_hash_interruptible_operation_t value);
+
+/** Serialise a `psa_verify_hash_interruptible_operation_t` into a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+                                                               size_t *remaining,
+                                                               psa_verify_hash_interruptible_operation_t value);
+
+/** Deserialise a `psa_verify_hash_interruptible_operation_t` from a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to a `psa_verify_hash_interruptible_operation_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+                                                                 size_t *remaining,
+                                                                 psa_verify_hash_interruptible_operation_t *value);
+
+/** Return how much buffer space is needed by \c psasim_server_serialise_psa_verify_hash_interruptible_operation_t()
+ *  to serialise a `psa_verify_hash_interruptible_operation_t`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_psa_verify_hash_interruptible_operation_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(
+    psa_verify_hash_interruptible_operation_t *value);
+
+/** Serialise a `psa_verify_hash_interruptible_operation_t` into a buffer on the server side.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_server_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+                                                                      size_t *remaining,
+                                                                      psa_verify_hash_interruptible_operation_t *value);
+
+/** Deserialise a `psa_verify_hash_interruptible_operation_t` from a buffer on the server side.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to a `psa_verify_hash_interruptible_operation_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos,
+                                                                        size_t *remaining,
+                                                                        psa_verify_hash_interruptible_operation_t **value);
+
 /** Return how much buffer space is needed by \c psasim_serialise_mbedtls_svc_key_id_t()
  *  to serialise a `mbedtls_svc_key_id_t`.
  *
@@ -594,7 +1256,8 @@
  *                           \c psasim_serialise_mbedtls_svc_key_id_t() to serialise
  *                           the given value.
  */
-size_t psasim_serialise_mbedtls_svc_key_id_t_needs(mbedtls_svc_key_id_t value);
+size_t psasim_serialise_mbedtls_svc_key_id_t_needs(
+    mbedtls_svc_key_id_t value);
 
 /** Serialise a `mbedtls_svc_key_id_t` into a buffer.
  *
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 e89fafe..81808ca 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
@@ -36,11 +36,18 @@
 # are).
 #
 my @types = qw(unsigned-int int size_t
+               uint16_t uint32_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
+               psa_sign_hash_interruptible_operation_t
+               psa_verify_hash_interruptible_operation_t
                mbedtls_svc_key_id_t);
 
 grep(s/-/ /g, @types);
@@ -49,6 +56,7 @@
 my %isa = (
     "psa_status_t" => "int",
     "psa_algorithm_t" => "unsigned int",
+    "psa_key_derivation_step_t" => "uint16_t",
 );
 
 if ($which eq "h") {
@@ -58,6 +66,8 @@
     for my $type (@types) {
         if ($type eq "buffer") {
             print declare_buffer_functions();
+        } elsif ($type eq "psa_key_production_parameters_t") {
+            print declare_psa_key_production_parameters_t_functions();
         } else {
             print declare_needs($type, "");
             print declare_serialise($type, "");
@@ -88,6 +98,8 @@
     for my $type (@types) {
         if ($type eq "buffer") {
             print define_buffer_functions();
+        } elsif ($type eq "psa_key_production_parameters_t") {
+            print define_psa_key_production_parameters_t_functions();
         } elsif (exists($isa{$type})) {
             print define_needs_isa($type, $isa{$type});
             print define_serialise_isa($type, $isa{$type});
@@ -133,7 +145,8 @@
  *                           \\c psasim_serialise_$type_d() to serialise
  *                           the given value.
  */
-size_t psasim_${server}serialise_${type_d}_needs($type ${ptr}value);
+size_t psasim_${server}serialise_${type_d}_needs(
+    $type ${ptr}value);
 EOF
 }
 
@@ -271,6 +284,62 @@
 EOF
 }
 
+sub declare_psa_key_production_parameters_t_functions
+{
+    return <<'EOF';
+
+/** 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);
+EOF
+}
+
 sub h_header
 {
     return <<'EOF';
@@ -383,7 +452,8 @@
 
     return <<EOF;
 
-size_t psasim_serialise_${type_d}_needs($type value)
+size_t psasim_serialise_${type_d}_needs(
+    $type value)
 {
     return sizeof(value);
 }
@@ -399,7 +469,8 @@
 
     return <<EOF;
 
-size_t psasim_server_serialise_${type_d}_needs($type *operation)
+size_t psasim_server_serialise_${type_d}_needs(
+    $type *operation)
 {
     (void) operation;
 
@@ -421,7 +492,8 @@
 
     return <<EOF;
 
-size_t psasim_serialise_${type_d}_needs($type value)
+size_t psasim_serialise_${type_d}_needs(
+    $type value)
 {
     return psasim_serialise_${isa_d}_needs(value);
 }
@@ -716,6 +788,106 @@
 EOF
 }
 
+sub define_psa_key_production_parameters_t_functions
+{
+    return <<'EOF';
+
+#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;
+}
+EOF
+}
+
 sub c_header
 {
     return <<'EOF';
@@ -800,8 +972,10 @@
 
     return <<EOF;
 
-static psa_${type}_operation_t ${type}_operations[MAX_LIVE_HANDLES_PER_CLASS];
-static psasim_client_handle_t ${type}_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
+static psa_${type}_operation_t ${type}_operations[
+    MAX_LIVE_HANDLES_PER_CLASS];
+static psasim_client_handle_t ${type}_operation_handles[
+    MAX_LIVE_HANDLES_PER_CLASS];
 static psasim_client_handle_t next_${type}_operation_handle = 1;
 
 /* Get a free slot */
@@ -937,8 +1111,10 @@
         my $what = $1;  # e.g. "hash_operation"
 
         $code .= <<EOF;
-    memset(${what}_handles, 0, sizeof(${what}_handles));
-    memset(${what}s, 0, sizeof(${what}s));
+    memset(${what}_handles, 0,
+           sizeof(${what}_handles));
+    memset(${what}s, 0,
+           sizeof(${what}s));
 EOF
     }
 
diff --git a/tests/psa-client-server/psasim/test/run_test.sh b/tests/psa-client-server/psasim/test/run_test.sh
index 45a317a..7c1011e 100755
--- a/tests/psa-client-server/psasim/test/run_test.sh
+++ b/tests/psa-client-server/psasim/test/run_test.sh
@@ -13,6 +13,9 @@
 
 cd "$(dirname "$0")"
 
+CLIENT_BIN=$1
+shift
+
 function clean_run() {
     rm -f psa_notify_*
     pkill psa_partition || true
@@ -30,8 +33,9 @@
 
 clean_run
 
-./psa_partition -k &
-SERV_PID=$!
+./psa_partition &
 wait_for_server_startup
-./psa_client "$@"
-wait $SERV_PID
+./$CLIENT_BIN "$@"
+
+# Kill server once client exited
+pkill psa_partition
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 93054e5..3bff3a8 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -6044,47 +6044,16 @@
     msg "build library for client"
     helper_crypto_client_build client
 
-    msg "build psasim to test psa_client"
-    rm -f tests/psa-client-server/psasim/test/psa_client        # In case left behind
-    make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" test/psa_client
+    msg "build basic psasim client"
+    make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" test/psa_client_base
+    msg "test basic psasim client"
+    tests/psa-client-server/psasim/test/run_test.sh psa_client_base
 
-    msg "test psasim"
-    tests/psa-client-server/psasim/test/run_test.sh
+    msg "build full psasim client"
+    make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" test/psa_client_full
+    msg "test full psasim client"
+    tests/psa-client-server/psasim/test/run_test.sh psa_client_full
 
-
-    msg "build psasim to test psa_hash_compute"
-    # Delete the executable to ensure we build using the right MAIN
-    rm tests/psa-client-server/psasim/test/psa_client
-    # API under test: psa_hash_compute()
-    make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="src/aut_psa_hash_compute.c" test/psa_client
-
-    msg "test psasim running psa_hash_compute"
-    tests/psa-client-server/psasim/test/run_test.sh
-
-
-    # Next APIs under test: psa_hash_*(). Use our copy of the PSA hash example.
-    msg "build psasim to test all psa_hash_* APIs"
-    # Delete the executable to ensure we build using the right MAIN
-    rm tests/psa-client-server/psasim/test/psa_client
-    make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="src/aut_psa_hash.c" test/psa_client
-
-    msg "test psasim running psa_hash sample"
-    tests/psa-client-server/psasim/test/run_test.sh
-
-
-    # Next APIs under test: psa_aead_*(). Use our copy of the PSA aead example.
-    msg "build psasim to test all psa_aead_* APIs"
-    # Delete the executable to ensure we build using the right MAIN
-    rm tests/psa-client-server/psasim/test/psa_client
-    make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="src/aut_psa_aead_demo.c" test/psa_client
-
-    msg "test psasim running psa_aead_demo sample"
-    tests/psa-client-server/psasim/test/run_test.sh aes128-gcm
-    tests/psa-client-server/psasim/test/run_test.sh aes256-gcm
-    tests/psa-client-server/psasim/test/run_test.sh aes128-gcm_8
-    tests/psa-client-server/psasim/test/run_test.sh chachapoly
-
-    msg "clean psasim"
     make -C tests/psa-client-server/psasim clean
 }