Add support for and run (a copy of) the PSA aead_demo program under PSA sim
Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
diff --git a/tests/psa-client-server/psasim/src/aut_psa_aead_demo.c b/tests/psa-client-server/psasim/src/aut_psa_aead_demo.c
new file mode 100644
index 0000000..4a46c40
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_aead_demo.c
@@ -0,0 +1,283 @@
+/**
+ * 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"
+
+#include <stdlib.h>
+#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]";
+
+/* Dummy data for encryption: IV/nonce, additional data, 2-part message */
+const unsigned char iv1[12] = { 0x00 };
+const unsigned char add_data1[] = { 0x01, 0x02 };
+const unsigned char msg1_part1[] = { 0x03, 0x04 };
+const unsigned char msg1_part2[] = { 0x05, 0x06, 0x07 };
+
+/* Dummy data (2nd message) */
+const unsigned char iv2[12] = { 0x10 };
+const unsigned char add_data2[] = { 0x11, 0x12 };
+const unsigned char msg2_part1[] = { 0x13, 0x14 };
+const unsigned char msg2_part2[] = { 0x15, 0x16, 0x17 };
+
+/* Maximum total size of the messages */
+#define MSG1_SIZE (sizeof(msg1_part1) + sizeof(msg1_part2))
+#define MSG2_SIZE (sizeof(msg2_part1) + sizeof(msg2_part2))
+#define MSG_MAX_SIZE (MSG1_SIZE > MSG2_SIZE ? MSG1_SIZE : MSG2_SIZE)
+
+/* Dummy key material - never do this in production!
+ * 32-byte is enough to all the key size supported by this program. */
+const unsigned char key_bytes[32] = { 0x2a };
+
+/* Print the contents of a buffer in hex */
+void print_buf(const char *title, uint8_t *buf, size_t len)
+{
+ printf("%s:", title);
+ for (size_t i = 0; i < len; i++) {
+ printf(" %02x", buf[i]);
+ }
+ printf("\n");
+}
+
+/* Run a PSA function and bail out if it fails.
+ * The symbolic name of the error code can be recovered using:
+ * programs/psa/psa_constant_name status <value> */
+#define PSA_CHECK(expr) \
+ do \
+ { \
+ status = (expr); \
+ if (status != PSA_SUCCESS) \
+ { \
+ printf("Error %d at line %d: %s\n", \
+ (int) status, \
+ __LINE__, \
+ #expr); \
+ goto exit; \
+ } \
+ } \
+ while (0)
+
+/*
+ * Prepare encryption material:
+ * - interpret command-line argument
+ * - set up key
+ * - outputs: key and algorithm, which together hold all the information
+ */
+static psa_status_t aead_prepare(const char *info,
+ psa_key_id_t *key,
+ psa_algorithm_t *alg)
+{
+ psa_status_t status;
+
+ /* Convert arg to alg + key_bits + key_type */
+ size_t key_bits;
+ psa_key_type_t key_type;
+ if (strcmp(info, "aes128-gcm") == 0) {
+ *alg = PSA_ALG_GCM;
+ key_bits = 128;
+ key_type = PSA_KEY_TYPE_AES;
+ } else if (strcmp(info, "aes256-gcm") == 0) {
+ *alg = PSA_ALG_GCM;
+ key_bits = 256;
+ key_type = PSA_KEY_TYPE_AES;
+ } else if (strcmp(info, "aes128-gcm_8") == 0) {
+ *alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 8);
+ key_bits = 128;
+ key_type = PSA_KEY_TYPE_AES;
+ } else if (strcmp(info, "chachapoly") == 0) {
+ *alg = PSA_ALG_CHACHA20_POLY1305;
+ key_bits = 256;
+ key_type = PSA_KEY_TYPE_CHACHA20;
+ } else {
+ puts(usage);
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
+ /* Prepare key attributes */
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
+ psa_set_key_algorithm(&attributes, *alg);
+ psa_set_key_type(&attributes, key_type);
+ psa_set_key_bits(&attributes, key_bits); // optional
+
+ /* Import key */
+ PSA_CHECK(psa_import_key(&attributes, key_bytes, key_bits / 8, key));
+
+exit:
+ return status;
+}
+
+/*
+ * Print out some information.
+ *
+ * All of this information was present in the command line argument, but his
+ * function demonstrates how each piece can be recovered from (key, alg).
+ */
+static void aead_info(psa_key_id_t key, psa_algorithm_t alg)
+{
+ psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+ (void) psa_get_key_attributes(key, &attr);
+ psa_key_type_t key_type = psa_get_key_type(&attr);
+ size_t key_bits = psa_get_key_bits(&attr);
+ psa_algorithm_t base_alg = PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg);
+ size_t tag_len = PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg);
+
+ const char *type_str = key_type == PSA_KEY_TYPE_AES ? "AES"
+ : key_type == PSA_KEY_TYPE_CHACHA20 ? "Chacha"
+ : "???";
+ const char *base_str = base_alg == PSA_ALG_GCM ? "GCM"
+ : base_alg == PSA_ALG_CHACHA20_POLY1305 ? "ChachaPoly"
+ : "???";
+
+ printf("%s, %u, %s, %u\n",
+ type_str, (unsigned) key_bits, base_str, (unsigned) tag_len);
+}
+
+/*
+ * Encrypt a 2-part message.
+ */
+static int aead_encrypt(psa_key_id_t key, psa_algorithm_t alg,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *ad, size_t ad_len,
+ const unsigned char *part1, size_t part1_len,
+ const unsigned char *part2, size_t part2_len)
+{
+ psa_status_t status;
+ size_t olen, olen_tag;
+ unsigned char out[PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(MSG_MAX_SIZE)];
+ unsigned char *p = out, *end = out + sizeof(out);
+ unsigned char tag[PSA_AEAD_TAG_MAX_SIZE];
+
+ psa_aead_operation_t op = PSA_AEAD_OPERATION_INIT;
+ PSA_CHECK(psa_aead_encrypt_setup(&op, key, alg));
+
+ PSA_CHECK(psa_aead_set_nonce(&op, iv, iv_len));
+ PSA_CHECK(psa_aead_update_ad(&op, ad, ad_len));
+ PSA_CHECK(psa_aead_update(&op, part1, part1_len, p, end - p, &olen));
+ p += olen;
+ PSA_CHECK(psa_aead_update(&op, part2, part2_len, p, end - p, &olen));
+ p += olen;
+ PSA_CHECK(psa_aead_finish(&op, p, end - p, &olen,
+ tag, sizeof(tag), &olen_tag));
+ p += olen;
+ memcpy(p, tag, olen_tag);
+ p += olen_tag;
+
+ olen = p - out;
+ print_buf("out", out, olen);
+
+exit:
+ psa_aead_abort(&op); // required on errors, harmless on success
+ return status;
+}
+
+/*
+ * AEAD demo: set up key/alg, print out info, encrypt messages.
+ */
+static psa_status_t aead_demo(const char *info)
+{
+ psa_status_t status;
+
+ psa_key_id_t key;
+ psa_algorithm_t alg;
+
+ PSA_CHECK(aead_prepare(info, &key, &alg));
+
+ aead_info(key, alg);
+
+ PSA_CHECK(aead_encrypt(key, alg,
+ iv1, sizeof(iv1), add_data1, sizeof(add_data1),
+ msg1_part1, sizeof(msg1_part1),
+ msg1_part2, sizeof(msg1_part2)));
+ PSA_CHECK(aead_encrypt(key, alg,
+ iv2, sizeof(iv2), add_data2, sizeof(add_data2),
+ msg2_part1, sizeof(msg2_part1),
+ msg2_part2, sizeof(msg2_part2)));
+
+exit:
+ psa_destroy_key(key);
+
+ return status;
+}
+
+/*
+ * Main function
+ */
+int main(int argc, char **argv)
+{
+ 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]));
+
+ /* Deinitialize the PSA crypto library. */
+ mbedtls_psa_crypto_free();
+
+exit:
+ return status == PSA_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+#endif
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 0093733..c68b416 100644
--- a/tests/psa-client-server/psasim/src/psa_functions_codes.h
+++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h
@@ -12,6 +12,20 @@
/* Start here to avoid overlap with PSA_IPC_CONNECT, PSA_IPC_DISCONNECT
* and VERSION_REQUEST */
PSA_CRYPTO_INIT = 100,
+ PSA_AEAD_ABORT,
+ PSA_AEAD_DECRYPT,
+ PSA_AEAD_DECRYPT_SETUP,
+ PSA_AEAD_ENCRYPT,
+ PSA_AEAD_ENCRYPT_SETUP,
+ PSA_AEAD_FINISH,
+ PSA_AEAD_GENERATE_NONCE,
+ PSA_AEAD_SET_LENGTHS,
+ PSA_AEAD_SET_NONCE,
+ PSA_AEAD_UPDATE,
+ PSA_AEAD_UPDATE_AD,
+ PSA_AEAD_VERIFY,
+ PSA_DESTROY_KEY,
+ PSA_GET_KEY_ATTRIBUTES,
PSA_HASH_ABORT,
PSA_HASH_CLONE,
PSA_HASH_COMPARE,
@@ -20,6 +34,7 @@
PSA_HASH_SETUP,
PSA_HASH_UPDATE,
PSA_HASH_VERIFY,
+ PSA_IMPORT_KEY,
};
#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 505a976..2ffb615 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
@@ -125,6 +125,1141 @@
}
+psa_status_t psa_aead_abort(
+ psa_aead_operation_t *operation
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psa_crypto_call(PSA_AEAD_ABORT,
+ params, (size_t) (pos - params), &result, &result_length);
+ if (!ok) {
+ printf("PSA_AEAD_ABORT server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_decrypt(
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce, size_t nonce_length,
+ const uint8_t *additional_data, size_t additional_data_length,
+ const uint8_t *ciphertext, size_t ciphertext_length,
+ uint8_t *plaintext, size_t plaintext_size,
+ size_t *plaintext_length
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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, nonce, nonce_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, additional_data, additional_data_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, ciphertext, ciphertext_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, plaintext, plaintext_size);
+ if (!ok) {
+ goto fail;
+ }
+ 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);
+ if (!ok) {
+ printf("PSA_AEAD_DECRYPT server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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, plaintext, plaintext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&rpos, &rremain, plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_decrypt_setup(
+ psa_aead_operation_t *operation,
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ 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_AEAD_DECRYPT_SETUP,
+ params, (size_t) (pos - params), &result, &result_length);
+ if (!ok) {
+ printf("PSA_AEAD_DECRYPT_SETUP server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_encrypt(
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce, size_t nonce_length,
+ const uint8_t *additional_data, size_t additional_data_length,
+ const uint8_t *plaintext, size_t plaintext_length,
+ uint8_t *ciphertext, size_t ciphertext_size,
+ size_t *ciphertext_length
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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, nonce, nonce_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, additional_data, additional_data_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, plaintext, plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, ciphertext, ciphertext_size);
+ if (!ok) {
+ goto fail;
+ }
+ 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);
+ if (!ok) {
+ printf("PSA_AEAD_ENCRYPT server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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, ciphertext, ciphertext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&rpos, &rremain, ciphertext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_encrypt_setup(
+ psa_aead_operation_t *operation,
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ 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_AEAD_ENCRYPT_SETUP,
+ params, (size_t) (pos - params), &result, &result_length);
+ if (!ok) {
+ printf("PSA_AEAD_ENCRYPT_SETUP server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_finish(
+ psa_aead_operation_t *operation,
+ uint8_t *ciphertext, size_t ciphertext_size,
+ size_t *ciphertext_length,
+ uint8_t *tag, size_t tag_size,
+ size_t *tag_length
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, ciphertext, ciphertext_size);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_size_t(&pos, &remaining, *ciphertext_length);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, tag, tag_size);
+ if (!ok) {
+ goto fail;
+ }
+ 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);
+ if (!ok) {
+ printf("PSA_AEAD_FINISH server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_return_buffer(&rpos, &rremain, ciphertext, ciphertext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&rpos, &rremain, ciphertext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_return_buffer(&rpos, &rremain, tag, tag_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&rpos, &rremain, tag_length);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_generate_nonce(
+ psa_aead_operation_t *operation,
+ uint8_t *nonce, size_t nonce_size,
+ size_t *nonce_length
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, nonce, nonce_size);
+ if (!ok) {
+ goto fail;
+ }
+ 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);
+ if (!ok) {
+ printf("PSA_AEAD_GENERATE_NONCE server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_return_buffer(&rpos, &rremain, nonce, nonce_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&rpos, &rremain, nonce_length);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_set_lengths(
+ psa_aead_operation_t *operation,
+ size_t ad_length,
+ size_t plaintext_length
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_size_t(&pos, &remaining, ad_length);
+ if (!ok) {
+ goto fail;
+ }
+ 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);
+ if (!ok) {
+ printf("PSA_AEAD_SET_LENGTHS server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_set_nonce(
+ psa_aead_operation_t *operation,
+ const uint8_t *nonce, size_t nonce_length
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ if (!ok) {
+ goto fail;
+ }
+ 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);
+ if (!ok) {
+ printf("PSA_AEAD_SET_NONCE server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_update(
+ psa_aead_operation_t *operation,
+ const uint8_t *input, size_t input_length,
+ uint8_t *output, size_t output_size,
+ size_t *output_length
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ 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_AEAD_UPDATE,
+ params, (size_t) (pos - params), &result, &result_length);
+ if (!ok) {
+ printf("PSA_AEAD_UPDATE server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_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(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_update_ad(
+ psa_aead_operation_t *operation,
+ const uint8_t *input, size_t input_length
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ if (!ok) {
+ goto fail;
+ }
+ 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);
+ if (!ok) {
+ printf("PSA_AEAD_UPDATE_AD server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_aead_verify(
+ psa_aead_operation_t *operation,
+ uint8_t *plaintext, size_t plaintext_size,
+ size_t *plaintext_length,
+ const uint8_t *tag, size_t tag_length
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_buffer(&pos, &remaining, plaintext, plaintext_size);
+ if (!ok) {
+ goto fail;
+ }
+ ok = psasim_serialise_size_t(&pos, &remaining, *plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+ 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);
+ if (!ok) {
+ printf("PSA_AEAD_VERIFY server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_return_buffer(&rpos, &rremain, plaintext, plaintext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&rpos, &rremain, plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_destroy_key(
+ mbedtls_svc_key_id_t key
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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_DESTROY_KEY,
+ params, (size_t) (pos - params), &result, &result_length);
+ if (!ok) {
+ printf("PSA_DESTROY_KEY server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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(params);
+ free(result);
+
+ return status;
+}
+
+
+psa_status_t psa_get_key_attributes(
+ mbedtls_svc_key_id_t key,
+ psa_key_attributes_t *attributes
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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_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);
+ if (!ok) {
+ printf("PSA_GET_KEY_ATTRIBUTES server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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_attributes_t(&rpos, &rremain, attributes);
+ if (!ok) {
+ goto fail;
+ }
+
+fail:
+ free(params);
+ free(result);
+
+ return status;
+}
+
+
psa_status_t psa_hash_abort(
psa_hash_operation_t *operation
)
@@ -703,3 +1838,78 @@
return status;
}
+
+
+psa_status_t psa_import_key(
+ const psa_key_attributes_t *attributes,
+ const uint8_t *data, size_t data_length,
+ mbedtls_svc_key_id_t *key
+ )
+{
+ uint8_t *params = NULL;
+ uint8_t *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);
+
+ params = malloc(needed);
+ if (params == NULL) {
+ status = PSA_ERROR_INSUFFICIENT_MEMORY;
+ goto fail;
+ }
+
+ uint8_t *pos = 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_buffer(&pos, &remaining, data, 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_IMPORT_KEY,
+ params, (size_t) (pos - params), &result, &result_length);
+ if (!ok) {
+ printf("PSA_IMPORT_KEY server call failed\n");
+ goto fail;
+ }
+
+ uint8_t *rpos = 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(params);
+ free(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 5812542..da3adb0 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
@@ -71,6 +71,1336 @@
}
// Returns 1 for success, 0 for failure
+int psa_aead_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_aead_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_aead_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_aead_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_aead_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_aead_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_aead_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 *nonce = NULL;
+ size_t nonce_length;
+ uint8_t *additional_data = NULL;
+ size_t additional_data_length;
+ uint8_t *ciphertext = NULL;
+ size_t ciphertext_length;
+ uint8_t *plaintext = NULL;
+ size_t plaintext_size;
+ size_t plaintext_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, &nonce, &nonce_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &additional_data, &additional_data_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &ciphertext, &ciphertext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &plaintext, &plaintext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_aead_decrypt(
+ key,
+ alg,
+ nonce, nonce_length,
+ additional_data, additional_data_length,
+ ciphertext, ciphertext_length,
+ plaintext, plaintext_size,
+ &plaintext_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(plaintext, plaintext_size) +
+ psasim_serialise_size_t_needs(plaintext_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, plaintext, plaintext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_size_t(&rpos, &rremain, plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(nonce);
+ free(additional_data);
+ free(ciphertext);
+ free(plaintext);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(nonce);
+ free(additional_data);
+ free(ciphertext);
+ free(plaintext);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_aead_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_aead_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_aead_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_aead_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_aead_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_aead_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_aead_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 *nonce = NULL;
+ size_t nonce_length;
+ uint8_t *additional_data = NULL;
+ size_t additional_data_length;
+ uint8_t *plaintext = NULL;
+ size_t plaintext_length;
+ uint8_t *ciphertext = NULL;
+ size_t ciphertext_size;
+ size_t ciphertext_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, &nonce, &nonce_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &additional_data, &additional_data_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &plaintext, &plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &ciphertext, &ciphertext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &ciphertext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_aead_encrypt(
+ key,
+ alg,
+ nonce, nonce_length,
+ additional_data, additional_data_length,
+ plaintext, plaintext_length,
+ ciphertext, ciphertext_size,
+ &ciphertext_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(ciphertext, ciphertext_size) +
+ psasim_serialise_size_t_needs(ciphertext_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, ciphertext, ciphertext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_size_t(&rpos, &rremain, ciphertext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(nonce);
+ free(additional_data);
+ free(plaintext);
+ free(ciphertext);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(nonce);
+ free(additional_data);
+ free(plaintext);
+ free(ciphertext);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_aead_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_aead_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_aead_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_aead_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_aead_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_aead_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_aead_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_aead_operation_t *operation;
+ uint8_t *ciphertext = NULL;
+ size_t ciphertext_size;
+ size_t ciphertext_length;
+ uint8_t *tag = NULL;
+ size_t tag_size;
+ size_t tag_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_aead_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &ciphertext, &ciphertext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &ciphertext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &tag, &tag_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &tag_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_aead_finish(
+ operation,
+ ciphertext, ciphertext_size,
+ &ciphertext_length,
+ tag, tag_size,
+ &tag_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_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);
+
+ 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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_buffer(&rpos, &rremain, ciphertext, ciphertext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_size_t(&rpos, &rremain, ciphertext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_buffer(&rpos, &rremain, tag, tag_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_size_t(&rpos, &rremain, tag_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(ciphertext);
+ free(tag);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(ciphertext);
+ free(tag);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_aead_generate_nonce_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_aead_operation_t *operation;
+ uint8_t *nonce = NULL;
+ size_t nonce_size;
+ size_t nonce_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_aead_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &nonce_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_aead_generate_nonce(
+ operation,
+ nonce, nonce_size,
+ &nonce_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_aead_operation_t_needs(operation) +
+ psasim_serialise_buffer_needs(nonce, nonce_size) +
+ psasim_serialise_size_t_needs(nonce_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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_buffer(&rpos, &rremain, nonce, nonce_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_size_t(&rpos, &rremain, nonce_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(nonce);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(nonce);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_aead_set_lengths_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_aead_operation_t *operation;
+ size_t ad_length;
+ size_t plaintext_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_aead_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &ad_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_aead_set_lengths(
+ operation,
+ ad_length,
+ plaintext_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_aead_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_aead_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_aead_set_nonce_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_aead_operation_t *operation;
+ uint8_t *nonce = NULL;
+ size_t nonce_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_aead_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_aead_set_nonce(
+ operation,
+ nonce, nonce_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_aead_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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(nonce);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(nonce);
+
+ return 0; // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_aead_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_aead_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_aead_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_aead_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_aead_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_aead_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_aead_update_ad_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_aead_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_aead_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_aead_update_ad(
+ 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_aead_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_aead_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_aead_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;
+ psa_aead_operation_t *operation;
+ uint8_t *plaintext = NULL;
+ size_t plaintext_size;
+ size_t plaintext_length;
+ uint8_t *tag = NULL;
+ size_t tag_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_aead_operation_t(&pos, &remaining, &operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &plaintext, &plaintext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_size_t(&pos, &remaining, &plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_deserialise_buffer(&pos, &remaining, &tag, &tag_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ // Now we call the actual target function
+
+ status = psa_aead_verify(
+ operation,
+ plaintext, plaintext_size,
+ &plaintext_length,
+ tag, tag_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_aead_operation_t_needs(operation) +
+ psasim_serialise_buffer_needs(plaintext, plaintext_size) +
+ psasim_serialise_size_t_needs(plaintext_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_aead_operation_t(&rpos, &rremain, operation);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_buffer(&rpos, &rremain, plaintext, plaintext_size);
+ if (!ok) {
+ goto fail;
+ }
+
+ ok = psasim_serialise_size_t(&rpos, &rremain, plaintext_length);
+ if (!ok) {
+ goto fail;
+ }
+
+ *out_params = result;
+ *out_params_len = result_size;
+
+ free(plaintext);
+ free(tag);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(plaintext);
+ free(tag);
+
+ 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)
+{
+ 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_destroy_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_get_key_attributes_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_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_mbedtls_svc_key_id_t(&pos, &remaining, &key);
+ 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
+
+ status = psa_get_key_attributes(
+ key,
+ &attributes
+ );
+
+ // NOTE: Should really check there is no overflow as we go along.
+ size_t result_size =
+ psasim_serialise_begin_needs() +
+ psasim_serialise_psa_status_t_needs(status) +
+ psasim_serialise_psa_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_status_t(&rpos, &rremain, status);
+ 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_hash_abort_wrapper(
uint8_t *in_params, size_t in_params_len,
uint8_t **out_params, size_t *out_params_len)
@@ -742,6 +2072,94 @@
return 0; // This shouldn't happen!
}
+// Returns 1 for success, 0 for failure
+int psa_import_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;
+ uint8_t *data = NULL;
+ size_t 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_buffer(&pos, &remaining, &data, &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_import_key(
+ &attributes,
+ data, 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(data);
+
+ return 1; // success
+
+fail:
+ free(result);
+
+ free(data);
+
+ return 0; // This shouldn't happen!
+}
+
psa_status_t psa_crypto_call(psa_msg_t msg)
{
int ok = 0;
@@ -782,6 +2200,62 @@
ok = psa_crypto_init_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
+ case PSA_AEAD_ABORT:
+ ok = psa_aead_abort_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_DECRYPT:
+ ok = psa_aead_decrypt_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_DECRYPT_SETUP:
+ ok = psa_aead_decrypt_setup_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_ENCRYPT:
+ ok = psa_aead_encrypt_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_ENCRYPT_SETUP:
+ ok = psa_aead_encrypt_setup_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_FINISH:
+ ok = psa_aead_finish_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_GENERATE_NONCE:
+ ok = psa_aead_generate_nonce_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_SET_LENGTHS:
+ ok = psa_aead_set_lengths_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_SET_NONCE:
+ ok = psa_aead_set_nonce_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_UPDATE:
+ ok = psa_aead_update_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_UPDATE_AD:
+ ok = psa_aead_update_ad_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
+ case PSA_AEAD_VERIFY:
+ ok = psa_aead_verify_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_GET_KEY_ATTRIBUTES:
+ ok = psa_get_key_attributes_wrapper(in_params, in_params_len,
+ &out_params, &out_params_len);
+ break;
case PSA_HASH_ABORT:
ok = psa_hash_abort_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
@@ -814,6 +2288,10 @@
ok = psa_hash_verify_wrapper(in_params, in_params_len,
&out_params, &out_params_len);
break;
+ case PSA_IMPORT_KEY:
+ ok = psa_import_key_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 9765de7..ee3894f 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl
@@ -1425,3 +1425,939 @@
size_t input_length,
const uint8_t *hash,
size_t hash_length);
+
+/** Process an authenticated encryption operation.
+ *
+ * \param key Identifier of the key to use for the
+ * operation. It must allow the usage
+ * #PSA_KEY_USAGE_ENCRYPT.
+ * \param alg The AEAD algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param[in] nonce Nonce or IV to use.
+ * \param nonce_length Size of the \p nonce buffer in bytes.
+ * \param[in] additional_data Additional data that will be authenticated
+ * but not encrypted.
+ * \param additional_data_length Size of \p additional_data in bytes.
+ * \param[in] plaintext Data that will be authenticated and
+ * encrypted.
+ * \param plaintext_length Size of \p plaintext in bytes.
+ * \param[out] ciphertext Output buffer for the authenticated and
+ * encrypted data. The additional data is not
+ * part of this output. For algorithms where the
+ * encrypted data and the authentication tag
+ * are defined as separate outputs, the
+ * authentication tag is appended to the
+ * encrypted data.
+ * \param ciphertext_size Size of the \p ciphertext buffer in bytes.
+ * This must be appropriate for the selected
+ * algorithm and key:
+ * - A sufficient output size is
+ * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type,
+ * \p alg, \p plaintext_length) where
+ * \c key_type is the type of \p key.
+ * - #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p
+ * plaintext_length) evaluates to the maximum
+ * ciphertext size of any supported AEAD
+ * encryption.
+ * \param[out] ciphertext_length On success, the size of the output
+ * in the \p ciphertext buffer.
+ *
+ * \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 an AEAD algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * \p ciphertext_size is too small.
+ * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, \p alg,
+ * \p plaintext_length) or
+ * #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length) can be used to
+ * determine the required buffer size.
+ * \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_aead_encrypt(mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *plaintext,
+ size_t plaintext_length,
+ uint8_t *ciphertext,
+ size_t ciphertext_size,
+ size_t *ciphertext_length);
+
+/** Process an authenticated decryption operation.
+ *
+ * \param key Identifier of the key to use for the
+ * operation. It must allow the usage
+ * #PSA_KEY_USAGE_DECRYPT.
+ * \param alg The AEAD algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param[in] nonce Nonce or IV to use.
+ * \param nonce_length Size of the \p nonce buffer in bytes.
+ * \param[in] additional_data Additional data that has been authenticated
+ * but not encrypted.
+ * \param additional_data_length Size of \p additional_data in bytes.
+ * \param[in] ciphertext Data that has been authenticated and
+ * encrypted. For algorithms where the
+ * encrypted data and the authentication tag
+ * are defined as separate inputs, the buffer
+ * must contain the encrypted data followed
+ * by the authentication tag.
+ * \param ciphertext_length Size of \p ciphertext in bytes.
+ * \param[out] plaintext Output buffer for the decrypted data.
+ * \param plaintext_size Size of the \p plaintext buffer in bytes.
+ * This must be appropriate for the selected
+ * algorithm and key:
+ * - A sufficient output size is
+ * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type,
+ * \p alg, \p ciphertext_length) where
+ * \c key_type is the type of \p key.
+ * - #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p
+ * ciphertext_length) evaluates to the maximum
+ * plaintext size of any supported AEAD
+ * decryption.
+ * \param[out] plaintext_length On success, the size of the output
+ * in the \p plaintext buffer.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ * The ciphertext is not authentic.
+ * \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 an AEAD algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * \p plaintext_size is too small.
+ * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, \p alg,
+ * \p ciphertext_length) or
+ * #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length) can be used
+ * to determine the required buffer size.
+ * \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_aead_decrypt(mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *ciphertext,
+ size_t ciphertext_length,
+ uint8_t *plaintext,
+ size_t plaintext_size,
+ size_t *plaintext_length);
+
+/** The type of the state data structure for multipart AEAD operations.
+ *
+ * Before calling any function on an AEAD operation object, the application
+ * must initialize it by any of the following means:
+ * - Set the structure to all-bits-zero, for example:
+ * \code
+ * psa_aead_operation_t operation;
+ * memset(&operation, 0, sizeof(operation));
+ * \endcode
+ * - Initialize the structure to logical zero values, for example:
+ * \code
+ * psa_aead_operation_t operation = {0};
+ * \endcode
+ * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT,
+ * for example:
+ * \code
+ * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
+ * \endcode
+ * - Assign the result of the function psa_aead_operation_init()
+ * to the structure, for example:
+ * \code
+ * psa_aead_operation_t operation;
+ * operation = psa_aead_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_aead_operation_s psa_aead_operation_t;
+
+/** \def PSA_AEAD_OPERATION_INIT
+ *
+ * This macro returns a suitable initializer for an AEAD operation object of
+ * type #psa_aead_operation_t.
+ */
+
+/** Return an initial value for an AEAD operation object.
+ */
+static psa_aead_operation_t psa_aead_operation_init(void);
+
+/** Set the key for a multipart authenticated encryption operation.
+ *
+ * The sequence of operations to encrypt a message with authentication
+ * 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_aead_operation_t, e.g.
+ * #PSA_AEAD_OPERATION_INIT.
+ * -# Call psa_aead_encrypt_setup() to specify the algorithm and key.
+ * -# If needed, call psa_aead_set_lengths() to specify the length of the
+ * inputs to the subsequent calls to psa_aead_update_ad() and
+ * psa_aead_update(). See the documentation of psa_aead_set_lengths()
+ * for details.
+ * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to
+ * generate or set the nonce. You should use
+ * psa_aead_generate_nonce() unless the protocol you are implementing
+ * requires a specific nonce value.
+ * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment
+ * of the non-encrypted additional authenticated data each time.
+ * -# Call psa_aead_update() zero, one or more times, passing a fragment
+ * of the message to encrypt each time.
+ * -# Call psa_aead_finish().
+ *
+ * If an error occurs at any step after a call to psa_aead_encrypt_setup(),
+ * the operation will need to be reset by a call to psa_aead_abort(). The
+ * application may call psa_aead_abort() at any time after the operation
+ * has been initialized.
+ *
+ * After a successful call to psa_aead_encrypt_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A successful call to psa_aead_finish().
+ * - A call to psa_aead_abort().
+ *
+ * \param[in,out] operation The operation object to set up. It must have
+ * been initialized as per the documentation for
+ * #psa_aead_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 AEAD algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \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().
+ * \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 an AEAD 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 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_aead_encrypt_setup(psa_aead_operation_t *operation,
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg);
+
+/** Set the key for a multipart authenticated decryption operation.
+ *
+ * The sequence of operations to decrypt a message with authentication
+ * 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_aead_operation_t, e.g.
+ * #PSA_AEAD_OPERATION_INIT.
+ * -# Call psa_aead_decrypt_setup() to specify the algorithm and key.
+ * -# If needed, call psa_aead_set_lengths() to specify the length of the
+ * inputs to the subsequent calls to psa_aead_update_ad() and
+ * psa_aead_update(). See the documentation of psa_aead_set_lengths()
+ * for details.
+ * -# Call psa_aead_set_nonce() with the nonce for the decryption.
+ * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment
+ * of the non-encrypted additional authenticated data each time.
+ * -# Call psa_aead_update() zero, one or more times, passing a fragment
+ * of the ciphertext to decrypt each time.
+ * -# Call psa_aead_verify().
+ *
+ * If an error occurs at any step after a call to psa_aead_decrypt_setup(),
+ * the operation will need to be reset by a call to psa_aead_abort(). The
+ * application may call psa_aead_abort() at any time after the operation
+ * has been initialized.
+ *
+ * After a successful call to psa_aead_decrypt_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A successful call to psa_aead_verify().
+ * - A call to psa_aead_abort().
+ *
+ * \param[in,out] operation The operation object to set up. It must have
+ * been initialized as per the documentation for
+ * #psa_aead_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 AEAD algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_AEAD(\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 an AEAD 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_aead_decrypt_setup(psa_aead_operation_t *operation,
+ mbedtls_svc_key_id_t key,
+ psa_algorithm_t alg);
+
+/** Generate a random nonce for an authenticated encryption operation.
+ *
+ * This function generates a random nonce for the authenticated encryption
+ * operation with an appropriate size for the chosen algorithm, key type
+ * and key size.
+ *
+ * The application must call psa_aead_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_aead_abort().
+ *
+ * \param[in,out] operation Active AEAD operation.
+ * \param[out] nonce Buffer where the generated nonce is to be
+ * written.
+ * \param nonce_size Size of the \p nonce buffer in bytes.
+ * \param[out] nonce_length On success, the number of bytes of the
+ * generated nonce.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p nonce 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 an active aead encrypt
+ * operation, with no nonce 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_aead_generate_nonce(psa_aead_operation_t *operation,
+ uint8_t *nonce,
+ size_t nonce_size,
+ size_t *nonce_length);
+
+/** Set the nonce for an authenticated encryption or decryption operation.
+ *
+ * This function sets the nonce for the authenticated
+ * encryption or decryption operation.
+ *
+ * The application must call psa_aead_encrypt_setup() or
+ * psa_aead_decrypt_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_aead_abort().
+ *
+ * \note When encrypting, applications should use psa_aead_generate_nonce()
+ * instead of this function, unless implementing a protocol that requires
+ * a non-random IV.
+ *
+ * \param[in,out] operation Active AEAD operation.
+ * \param[in] nonce Buffer containing the nonce to use.
+ * \param nonce_length Size of the nonce in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The size of \p nonce is not acceptable for the chosen 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 active, with no nonce
+ * 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_aead_set_nonce(psa_aead_operation_t *operation,
+ const uint8_t *nonce,
+ size_t nonce_length);
+
+/** Declare the lengths of the message and additional data for AEAD.
+ *
+ * The application must call this function before calling
+ * psa_aead_update_ad() or psa_aead_update() if the algorithm for
+ * the operation requires it. If the algorithm does not require it,
+ * calling this function is optional, but if this function is called
+ * then the implementation must enforce the lengths.
+ *
+ * You may call this function before or after setting the nonce with
+ * psa_aead_set_nonce() or psa_aead_generate_nonce().
+ *
+ * - For #PSA_ALG_CCM, calling this function is required.
+ * - For the other AEAD algorithms defined in this specification, calling
+ * this function is not required.
+ * - For vendor-defined algorithm, refer to the vendor documentation.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_aead_abort().
+ *
+ * \param[in,out] operation Active AEAD operation.
+ * \param ad_length Size of the non-encrypted additional
+ * authenticated data in bytes.
+ * \param plaintext_length Size of the plaintext to encrypt in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * At least one of the lengths is not acceptable for the chosen
+ * 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_BAD_STATE
+ * The operation state is not valid (it must be active, and
+ * psa_aead_update_ad() and psa_aead_update() must not have been
+ * called yet), 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_aead_set_lengths(psa_aead_operation_t *operation,
+ size_t ad_length,
+ size_t plaintext_length);
+
+/** Pass additional data to an active AEAD operation.
+ *
+ * Additional data is authenticated, but not encrypted.
+ *
+ * You may call this function multiple times to pass successive fragments
+ * of the additional data. You may not call this function after passing
+ * data to encrypt or decrypt with psa_aead_update().
+ *
+ * Before calling this function, you must:
+ * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup().
+ * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce().
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_aead_abort().
+ *
+ * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS,
+ * there is no guarantee that the input is valid. Therefore, until
+ * you have called psa_aead_verify() and it has returned #PSA_SUCCESS,
+ * treat the input as untrusted and prepare to undo any action that
+ * depends on the input if psa_aead_verify() returns an error status.
+ *
+ * \param[in,out] operation Active AEAD operation.
+ * \param[in] input Buffer containing the fragment of
+ * additional data.
+ * \param input_length Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The total input length overflows the additional data length that
+ * was previously specified with psa_aead_set_lengths().
+ * \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, have a nonce
+ * set, have lengths set if required by the algorithm, and
+ * psa_aead_update() must not have been called yet), 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_aead_update_ad(psa_aead_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length);
+
+/** Encrypt or decrypt a message fragment in an active AEAD operation.
+ *
+ * Before calling this function, you must:
+ * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup().
+ * The choice of setup function determines whether this function
+ * encrypts or decrypts its input.
+ * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce().
+ * 3. Call psa_aead_update_ad() to pass all the additional data.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_aead_abort().
+ *
+ * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS,
+ * there is no guarantee that the input is valid. Therefore, until
+ * you have called psa_aead_verify() and it has returned #PSA_SUCCESS:
+ * - Do not use the output in any way other than storing it in a
+ * confidential location. If you take any action that depends
+ * on the tentative decrypted data, this action will need to be
+ * undone if the input turns out not to be valid. Furthermore,
+ * if an adversary can observe that this action took place
+ * (for example through timing), they may be able to use this
+ * fact as an oracle to decrypt any message encrypted with the
+ * same key.
+ * - In particular, do not copy the output anywhere but to a
+ * memory or storage space that you have exclusive access to.
+ *
+ * This function does not require the input to be aligned to any
+ * particular block boundary. If the implementation can only process
+ * a whole block at a time, it must consume all the input provided, but
+ * it may delay the end of the corresponding output until a subsequent
+ * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify()
+ * provides sufficient input. The amount of data that can be delayed
+ * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE.
+ *
+ * \param[in,out] operation Active AEAD 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.
+ * This must be appropriate for the selected
+ * algorithm and key:
+ * - A sufficient output size is
+ * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type,
+ * \c alg, \p input_length) where
+ * \c key_type is the type of key and \c alg is
+ * the algorithm that were used to set up the
+ * operation.
+ * - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p
+ * input_length) evaluates to the maximum
+ * output size of any supported AEAD
+ * algorithm.
+ * \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.
+ * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or
+ * #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to
+ * determine the required buffer size.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The total length of input to psa_aead_update_ad() so far is
+ * less than the additional data length that was previously
+ * specified with psa_aead_set_lengths(), or
+ * the total input length overflows the plaintext length that
+ * was previously specified with psa_aead_set_lengths().
+ * \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, have a nonce
+ * set, and have lengths set if required by 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_aead_update(psa_aead_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length);
+
+/** Finish encrypting a message in an AEAD operation.
+ *
+ * The operation must have been set up with psa_aead_encrypt_setup().
+ *
+ * This function finishes the authentication of the additional data
+ * formed by concatenating the inputs passed to preceding calls to
+ * psa_aead_update_ad() with the plaintext formed by concatenating the
+ * inputs passed to preceding calls to psa_aead_update().
+ *
+ * This function has two output buffers:
+ * - \p ciphertext contains trailing ciphertext that was buffered from
+ * preceding calls to psa_aead_update().
+ * - \p tag contains the authentication tag.
+ *
+ * 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_aead_abort().
+ *
+ * \param[in,out] operation Active AEAD operation.
+ * \param[out] ciphertext Buffer where the last part of the ciphertext
+ * is to be written.
+ * \param ciphertext_size Size of the \p ciphertext buffer in bytes.
+ * This must be appropriate for the selected
+ * algorithm and key:
+ * - A sufficient output size is
+ * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type,
+ * \c alg) where \c key_type is the type of key
+ * and \c alg is the algorithm that were used to
+ * set up the operation.
+ * - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to
+ * the maximum output size of any supported AEAD
+ * algorithm.
+ * \param[out] ciphertext_length On success, the number of bytes of
+ * returned ciphertext.
+ * \param[out] tag Buffer where the authentication tag is
+ * to be written.
+ * \param tag_size Size of the \p tag buffer in bytes.
+ * This must be appropriate for the selected
+ * algorithm and key:
+ * - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c
+ * key_type, \c key_bits, \c alg) where
+ * \c key_type and \c key_bits are the type and
+ * bit-size of the key, and \c alg is the
+ * algorithm that were used in the call to
+ * psa_aead_encrypt_setup().
+ * - #PSA_AEAD_TAG_MAX_SIZE evaluates to the
+ * maximum tag size of any supported AEAD
+ * algorithm.
+ * \param[out] tag_length On success, the number of bytes
+ * that make up the returned tag.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p ciphertext or \p tag buffer is too small.
+ * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, \c alg) or
+ * #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE can be used to determine the
+ * required \p ciphertext buffer size. #PSA_AEAD_TAG_LENGTH(\c key_type,
+ * \c key_bits, \c alg) or #PSA_AEAD_TAG_MAX_SIZE can be used to
+ * determine the required \p tag buffer size.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The total length of input to psa_aead_update_ad() so far is
+ * less than the additional data length that was previously
+ * specified with psa_aead_set_lengths(), or
+ * the total length of input to psa_aead_update() so far is
+ * less than the plaintext length that was previously
+ * specified with psa_aead_set_lengths().
+ * \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 encryption
+ * operation with a nonce 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_aead_finish(psa_aead_operation_t *operation,
+ uint8_t *ciphertext,
+ size_t ciphertext_size,
+ size_t *ciphertext_length,
+ uint8_t *tag,
+ size_t tag_size,
+ size_t *tag_length);
+
+/** Finish authenticating and decrypting a message in an AEAD operation.
+ *
+ * The operation must have been set up with psa_aead_decrypt_setup().
+ *
+ * This function finishes the authenticated decryption of the message
+ * components:
+ *
+ * - The additional data consisting of the concatenation of the inputs
+ * passed to preceding calls to psa_aead_update_ad().
+ * - The ciphertext consisting of the concatenation of the inputs passed to
+ * preceding calls to psa_aead_update().
+ * - The tag passed to this function call.
+ *
+ * If the authentication tag is correct, this function outputs any remaining
+ * plaintext and reports success. If the authentication tag is not correct,
+ * this function returns #PSA_ERROR_INVALID_SIGNATURE.
+ *
+ * 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_aead_abort().
+ *
+ * \note Implementations shall make the best effort to ensure that the
+ * comparison between the actual tag and the expected tag is performed
+ * in constant time.
+ *
+ * \param[in,out] operation Active AEAD operation.
+ * \param[out] plaintext Buffer where the last part of the plaintext
+ * is to be written. This is the remaining data
+ * from previous calls to psa_aead_update()
+ * that could not be processed until the end
+ * of the input.
+ * \param plaintext_size Size of the \p plaintext buffer in bytes.
+ * This must be appropriate for the selected algorithm and key:
+ * - A sufficient output size is
+ * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type,
+ * \c alg) where \c key_type is the type of key
+ * and \c alg is the algorithm that were used to
+ * set up the operation.
+ * - #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE evaluates to
+ * the maximum output size of any supported AEAD
+ * algorithm.
+ * \param[out] plaintext_length On success, the number of bytes of
+ * returned plaintext.
+ * \param[in] tag Buffer containing the authentication tag.
+ * \param tag_length Size of the \p tag buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ * The calculations were successful, but the authentication tag is
+ * not correct.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p plaintext buffer is too small.
+ * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, \c alg) or
+ * #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE can be used to determine the
+ * required buffer size.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The total length of input to psa_aead_update_ad() so far is
+ * less than the additional data length that was previously
+ * specified with psa_aead_set_lengths(), or
+ * the total length of input to psa_aead_update() so far is
+ * less than the plaintext length that was previously
+ * specified with psa_aead_set_lengths().
+ * \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 decryption
+ * operation with a nonce 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_aead_verify(psa_aead_operation_t *operation,
+ uint8_t *plaintext,
+ size_t plaintext_size,
+ size_t *plaintext_length,
+ const uint8_t *tag,
+ size_t tag_length);
+
+/** Abort an AEAD 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_aead_encrypt_setup() or psa_aead_decrypt_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized as described in #psa_aead_operation_t.
+ *
+ * In particular, calling psa_aead_abort() after the operation has been
+ * terminated by a call to psa_aead_abort(), psa_aead_finish() or
+ * psa_aead_verify() is safe and has no effect.
+ *
+ * \param[in,out] operation Initialized AEAD 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_aead_abort(psa_aead_operation_t *operation);
+
+/**
+ * \brief Import a key in binary format.
+ *
+ * This function supports any output from psa_export_key(). Refer to the
+ * documentation of psa_export_public_key() for the format of public keys
+ * and to the documentation of psa_export_key() for the format for
+ * other key types.
+ *
+ * The key data determines the key size. The attributes may optionally
+ * specify a key size; in this case it must match the size determined
+ * from the key data. A key size of 0 in \p attributes indicates that
+ * the key size is solely determined by the key data.
+ *
+ * Implementations must reject an attempt to import a key of size 0.
+ *
+ * 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.
+ *
+ * \param[in] attributes The attributes for the new key.
+ * The key size is always determined from the
+ * \p data buffer.
+ * If the key size in \p attributes is nonzero,
+ * it must be equal to the size from \p data.
+ * \param[out] key On success, an identifier to the newly created key.
+ * For persistent keys, this is the key identifier
+ * defined in \p attributes.
+ * \c 0 on failure.
+ * \param[in] data Buffer containing the key data. The content of this
+ * buffer is interpreted according to the type declared
+ * in \p attributes.
+ * All implementations must support at least the format
+ * described in the documentation
+ * of psa_export_key() or psa_export_public_key() for
+ * the chosen type. Implementations may allow other
+ * formats, but should be conservative: implementations
+ * should err on the side of rejecting content if it
+ * may be erroneous (e.g. wrong type or truncated data).
+ * \param data_length Size of the \p data buffer in bytes.
+ *
+ * \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
+ * The key type or key size is not supported, either by the
+ * implementation in general or in this particular persistent location.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The key attributes, as a whole, are invalid, or
+ * the key data is not correctly formatted, or
+ * the size in \p attributes is nonzero and does not match the size
+ * of the key data.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_STORAGE_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_import_key(const psa_key_attributes_t *attributes,
+ const uint8_t *data,
+ size_t data_length,
+ mbedtls_svc_key_id_t *key);
+
+/** Retrieve the attributes of a key.
+ *
+ * This function first resets the attribute structure as with
+ * psa_reset_key_attributes(). It then copies the attributes of
+ * the given key into the given attribute structure.
+ *
+ * \note This function may allocate memory or other resources.
+ * Once you have called this function on an attribute structure,
+ * you must call psa_reset_key_attributes() to free these resources.
+ *
+ * \param[in] key Identifier of the key to query.
+ * \param[in,out] attributes On success, the attributes of the key.
+ * On failure, equivalent to a
+ * freshly-initialized structure.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_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_get_key_attributes(mbedtls_svc_key_id_t key,
+ psa_key_attributes_t *attributes);
+
+/**
+ * \brief Destroy a key.
+ *
+ * This function destroys a key from both volatile
+ * memory and, if applicable, non-volatile storage. Implementations shall
+ * make a best effort to ensure that the key material cannot be recovered.
+ *
+ * This function also erases any metadata such as policies and frees
+ * resources associated with the key.
+ *
+ * If a key is currently in use in a multipart operation, then destroying the
+ * key will cause the multipart operation to fail.
+ *
+ * \warning We can only guarantee that the the key material will
+ * eventually be wiped from memory. With threading enabled
+ * and during concurrent execution, copies of the key material may
+ * still exist until all threads have finished using the key.
+ *
+ * \param key Identifier of the key to erase. If this is \c 0, do nothing and
+ * return #PSA_SUCCESS.
+ *
+ * \retval #PSA_SUCCESS
+ * \p key was a valid identifier and the key material that it
+ * referred to has been erased. Alternatively, \p key is \c 0.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The key cannot be erased because it is
+ * read-only, either due to a policy or due to physical restrictions.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \p key is not a valid identifier nor \c 0.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * There was a failure in communication with the cryptoprocessor.
+ * The key material may still be present in the cryptoprocessor.
+ * \retval #PSA_ERROR_DATA_INVALID
+ * This error is typically a result of either storage corruption on a
+ * cleartext storage backend, or an attempt to read data that was
+ * written by an incompatible version of the library.
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * The storage is corrupted. Implementations shall make a best effort
+ * to erase key material even in this stage, however applications
+ * should be aware that it may be impossible to guarantee that the
+ * key material is not recoverable in such cases.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * An unexpected condition which is not a storage corruption or
+ * a communication failure occurred. The cryptoprocessor may have
+ * been compromised.
+ * \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_destroy_key(mbedtls_svc_key_id_t key);
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 348e42c..9e8c38b 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
@@ -97,6 +97,41 @@
return -1; /* all in use */
}
+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 */
+static ssize_t allocate_aead_operation_slot(void)
+{
+ psasim_client_handle_t handle = next_aead_operation_handle++;
+ if (next_aead_operation_handle == 0) { /* wrapped around */
+ fprintf(stderr, "MAX HASH HANDLES REACHED\n");
+ exit(1);
+ }
+
+ for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+ if (aead_operation_handles[i] == 0) {
+ aead_operation_handles[i] = handle;
+ return i;
+ }
+ }
+
+ return -1; /* all in use */
+}
+
+/* Find the slot given the handle */
+static ssize_t find_aead_slot_by_handle(psasim_client_handle_t handle)
+{
+ for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
+ if (aead_operation_handles[i] == handle) {
+ return i;
+ }
+ }
+
+ return -1; /* all in use */
+}
+
size_t psasim_serialise_begin_needs(void)
{
/* The serialisation buffer will
@@ -508,3 +543,166 @@
return 1;
}
+
+size_t psasim_serialise_psa_aead_operation_t_needs(psa_aead_operation_t value)
+{
+ return sizeof(value);
+}
+
+int psasim_serialise_psa_aead_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_aead_operation_t value)
+{
+ if (*remaining < sizeof(value)) {
+ return 0;
+ }
+
+ memcpy(*pos, &value, sizeof(value));
+ *pos += sizeof(value);
+
+ return 1;
+}
+
+int psasim_deserialise_psa_aead_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_aead_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_aead_operation_t_needs(psa_aead_operation_t *operation)
+{
+ (void) operation;
+
+ /* We will actually return a handle */
+ return sizeof(psasim_operation_t);
+}
+
+int psasim_server_serialise_psa_aead_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_aead_operation_t *operation)
+{
+ psasim_operation_t client_operation;
+
+ if (*remaining < sizeof(client_operation)) {
+ return 0;
+ }
+
+ ssize_t slot = operation - aead_operations;
+
+ client_operation.handle = aead_operation_handles[slot];
+
+ memcpy(*pos, &client_operation, sizeof(client_operation));
+ *pos += sizeof(client_operation);
+
+ return 1;
+}
+
+int psasim_server_deserialise_psa_aead_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_aead_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_aead_operation_slot();
+ } else {
+ slot = find_aead_slot_by_handle(client_operation.handle);
+ }
+
+ if (slot < 0) {
+ return 0;
+ }
+
+ *operation = &aead_operations[slot];
+
+ return 1;
+}
+
+size_t psasim_serialise_psa_key_attributes_t_needs(psa_key_attributes_t value)
+{
+ return sizeof(value);
+}
+
+int psasim_serialise_psa_key_attributes_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_attributes_t value)
+{
+ if (*remaining < sizeof(value)) {
+ return 0;
+ }
+
+ memcpy(*pos, &value, sizeof(value));
+ *pos += sizeof(value);
+
+ return 1;
+}
+
+int psasim_deserialise_psa_key_attributes_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_attributes_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_mbedtls_svc_key_id_t_needs(mbedtls_svc_key_id_t value)
+{
+ return sizeof(value);
+}
+
+int psasim_serialise_mbedtls_svc_key_id_t(uint8_t **pos,
+ size_t *remaining,
+ mbedtls_svc_key_id_t value)
+{
+ if (*remaining < sizeof(value)) {
+ return 0;
+ }
+
+ memcpy(*pos, &value, sizeof(value));
+ *pos += sizeof(value);
+
+ return 1;
+}
+
+int psasim_deserialise_mbedtls_svc_key_id_t(uint8_t **pos,
+ size_t *remaining,
+ mbedtls_svc_key_id_t *value)
+{
+ if (*remaining < sizeof(*value)) {
+ return 0;
+ }
+
+ memcpy(value, *pos, sizeof(*value));
+
+ *pos += sizeof(*value);
+ *remaining -= sizeof(*value);
+
+ return 1;
+}
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 4ec7ec0..9c69e65 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
@@ -450,3 +450,171 @@
int psasim_server_deserialise_psa_hash_operation_t(uint8_t **pos,
size_t *remaining,
psa_hash_operation_t **value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_psa_aead_operation_t()
+ * to serialise a `psa_aead_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_aead_operation_t() to serialise
+ * the given value.
+ */
+size_t psasim_serialise_psa_aead_operation_t_needs(psa_aead_operation_t value);
+
+/** Serialise a `psa_aead_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_aead_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_aead_operation_t value);
+
+/** Deserialise a `psa_aead_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_aead_operation_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_aead_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_aead_operation_t *value);
+
+/** Return how much buffer space is needed by \c psasim_server_serialise_psa_aead_operation_t()
+ * to serialise a `psa_aead_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_aead_operation_t() to serialise
+ * the given 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.
+ *
+ * \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_aead_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_aead_operation_t *value);
+
+/** Deserialise a `psa_aead_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_aead_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_aead_operation_t(uint8_t **pos,
+ size_t *remaining,
+ psa_aead_operation_t **value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_psa_key_attributes_t()
+ * to serialise a `psa_key_attributes_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_attributes_t() to serialise
+ * the given value.
+ */
+size_t psasim_serialise_psa_key_attributes_t_needs(psa_key_attributes_t value);
+
+/** Serialise a `psa_key_attributes_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_attributes_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_attributes_t value);
+
+/** Deserialise a `psa_key_attributes_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_attributes_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_key_attributes_t(uint8_t **pos,
+ size_t *remaining,
+ psa_key_attributes_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`.
+ *
+ * \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_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);
+
+/** Serialise a `mbedtls_svc_key_id_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_mbedtls_svc_key_id_t(uint8_t **pos,
+ size_t *remaining,
+ mbedtls_svc_key_id_t value);
+
+/** Deserialise a `mbedtls_svc_key_id_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 `mbedtls_svc_key_id_t` to receive the value
+ * deserialised from the buffer.
+ *
+ * \return \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_mbedtls_svc_key_id_t(uint8_t **pos,
+ size_t *remaining,
+ mbedtls_svc_key_id_t *value);
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
index eb2893e..e09bb81 100755
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
@@ -38,7 +38,11 @@
my @types = qw(unsigned-int int size_t
buffer
psa_status_t psa_algorithm_t
- psa_hash_operation_t);
+ psa_hash_operation_t
+ psa_aead_operation_t
+ psa_key_attributes_t
+ mbedtls_svc_key_id_t);
+
grep(s/-/ /g, @types);
# IS-A: Some data types are typedef'd; we serialise them as the other type
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 88d051b..3bde666 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -964,10 +964,14 @@
scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
scripts/config.py unset MBEDTLS_ECP_RESTARTABLE
+ scripts/config.py unset MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
else
scripts/config.py crypto_full
scripts/config.py unset MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
- scripts/config.py set MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
+ # We need to match the client with MBEDTLS_PSA_CRYPTO_SE_C
+ scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
+ # Also ensure MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER not set (to match client)
+ scripts/config.py unset MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
fi
make -C tests/psa-client-server/psasim/ CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" $TARGET_LIB "$@"
@@ -6223,6 +6227,7 @@
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 "test psasim"
@@ -6249,6 +6254,18 @@
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
}