diff options
author | Tom Cosgrove <tom.cosgrove@arm.com> | 2024-06-13 10:13:40 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-13 10:13:40 +0000 |
commit | 7c52100fbd882437b5fb46e639c5db57bcc56b15 (patch) | |
tree | b6a2b881424be682acf7fca09d684abcba4fa21a | |
parent | f41272099bedef5522eaf54b7689048633d612f6 (diff) | |
parent | 0fe5b8d4a3d51d988a9942f2dd0810d8f2ad89cf (diff) | |
download | mbedtls-7c52100fbd882437b5fb46e639c5db57bcc56b15.zip mbedtls-7c52100fbd882437b5fb46e639c5db57bcc56b15.tar.gz mbedtls-7c52100fbd882437b5fb46e639c5db57bcc56b15.tar.bz2 |
Merge pull request #9238 from tom-cosgrove-arm/psasim_update_for_operation_types
Update PSA simulator C code to do operations by handles
-rw-r--r-- | tests/psa-client-server/psasim/Makefile | 7 | ||||
-rw-r--r-- | tests/psa-client-server/psasim/src/aut_psa_aead_demo.c | 283 | ||||
-rw-r--r-- | tests/psa-client-server/psasim/src/aut_psa_hash.c | 160 | ||||
-rw-r--r-- | tests/psa-client-server/psasim/src/aut_psa_hash_compute.c | 5 | ||||
-rw-r--r-- | tests/psa-client-server/psasim/src/psa_functions_codes.h | 15 | ||||
-rw-r--r-- | tests/psa-client-server/psasim/src/psa_sim_crypto_client.c | 1230 | ||||
-rw-r--r-- | tests/psa-client-server/psasim/src/psa_sim_crypto_server.c | 1548 | ||||
-rwxr-xr-x | tests/psa-client-server/psasim/src/psa_sim_generate.pl | 966 | ||||
-rw-r--r-- | tests/psa-client-server/psasim/src/psa_sim_serialise.c | 302 | ||||
-rw-r--r-- | tests/psa-client-server/psasim/src/psa_sim_serialise.h | 210 | ||||
-rwxr-xr-x | tests/psa-client-server/psasim/src/psa_sim_serialise.pl | 237 | ||||
-rwxr-xr-x | tests/psa-client-server/psasim/test/run_test.sh | 2 | ||||
-rwxr-xr-x | tests/scripts/all.sh | 68 |
13 files changed, 4935 insertions, 98 deletions
diff --git a/tests/psa-client-server/psasim/Makefile b/tests/psa-client-server/psasim/Makefile index 06d3059..38dbef6 100644 --- a/tests/psa-client-server/psasim/Makefile +++ b/tests/psa-client-server/psasim/Makefile @@ -12,9 +12,6 @@ LIBPSASERVER := -Llibpsaserver/ -lmbedcrypto MBEDTLS_ROOT_PATH = ../../.. COMMON_INCLUDE := -I./include -I$(MBEDTLS_ROOT_PATH)/include -TEST_BIN = test/psa_client \ - test/psa_partition - GENERATED_H_FILES = include/psa_manifest/manifest.h \ include/psa_manifest/pid.h \ include/psa_manifest/sid.h @@ -33,7 +30,7 @@ PSA_SERVER_SRC = $(PARTITION_SERVER_BOOTSTRAP) \ .PHONY: all clean libpsaclient libpsaserver -all: $(TEST_BIN) +all: test/seedfile: dd if=/dev/urandom of=./test/seedfile bs=64 count=1 @@ -59,7 +56,7 @@ libpsaclient libpsaserver: $(MAKE) -C $(MBEDTLS_ROOT_PATH) clean clean: - rm -f $(TEST_BIN) + rm -f test/psa_client test/psa_partition rm -f $(PARTITION_SERVER_BOOTSTRAP) rm -rf libpsaclient libpsaserver rm -rf include/psa_manifest diff --git a/tests/psa-client-server/psasim/src/aut_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/aut_psa_hash.c b/tests/psa-client-server/psasim/src/aut_psa_hash.c new file mode 100644 index 0000000..6c2c07e --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_psa_hash.c @@ -0,0 +1,160 @@ +/* + * Example computing a SHA-256 hash using the PSA Crypto API + * + * The example computes the SHA-256 hash of a test string using the + * one-shot API call psa_hash_compute() and the using multi-part + * operation, which requires psa_hash_setup(), psa_hash_update() and + * psa_hash_finish(). The multi-part operation is popular on embedded + * devices where a rolling hash needs to be computed. + * + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mbedtls/build_info.h" +#include "mbedtls/platform.h" + +/* Information about hashing with the PSA API can be + * found here: + * https://arm-software.github.io/psa-api/crypto/1.1/api/ops/hashes.html + * + * The algorithm used by this demo is SHA 256. + * Please see include/psa/crypto_values.h to see the other + * algorithms that are supported by Mbed TLS. + * If you switch to a different algorithm you will need to update + * the hash data in the EXAMPLE_HASH_VALUE macro below. */ + +#if !defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \ + (!defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256)) +int main(void) +{ + mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256" + "not defined, and not MBEDTLS_PSA_CRYPTO_CLIENT.\r\n"); + return EXIT_SUCCESS; +} +#else + +#define HASH_ALG PSA_ALG_SHA_256 + +const uint8_t sample_message[] = "Hello World!"; +/* sample_message is terminated with a null byte which is not part of + * the message itself so we make sure to subtract it in order to get + * the message length. */ +const size_t sample_message_length = sizeof(sample_message) - 1; + +#define EXPECTED_HASH_VALUE { \ + 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \ + 0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, \ + 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \ +} + +const uint8_t expected_hash[] = EXPECTED_HASH_VALUE; +const size_t expected_hash_len = sizeof(expected_hash); + +int main(void) +{ + psa_status_t status; + uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)]; + size_t hash_length; + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + psa_hash_operation_t cloned_hash_operation = PSA_HASH_OPERATION_INIT; + + mbedtls_printf("PSA Crypto API: SHA-256 example\n\n"); + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + /* Compute hash using multi-part operation */ + status = psa_hash_setup(&hash_operation, HASH_ALG); + if (status == PSA_ERROR_NOT_SUPPORTED) { + mbedtls_printf("unknown hash algorithm supplied\n"); + return EXIT_FAILURE; + } else if (status != PSA_SUCCESS) { + mbedtls_printf("psa_hash_setup failed\n"); + return EXIT_FAILURE; + } + + status = psa_hash_update(&hash_operation, sample_message, sample_message_length); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_hash_update failed\n"); + goto cleanup; + } + + status = psa_hash_clone(&hash_operation, &cloned_hash_operation); + if (status != PSA_SUCCESS) { + mbedtls_printf("PSA hash clone failed\n"); + goto cleanup; + } + + status = psa_hash_finish(&hash_operation, hash, sizeof(hash), &hash_length); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_hash_finish failed\n"); + goto cleanup; + } + + /* Check the result of the operation against the sample */ + if (hash_length != expected_hash_len || + (memcmp(hash, expected_hash, expected_hash_len) != 0)) { + mbedtls_printf("Multi-part hash operation gave the wrong result!\n\n"); + goto cleanup; + } + + status = + psa_hash_verify(&cloned_hash_operation, expected_hash, + expected_hash_len); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_hash_verify failed\n"); + goto cleanup; + } else { + mbedtls_printf("Multi-part hash operation successful!\n"); + } + + /* Clear local variables prior to one-shot hash demo */ + memset(hash, 0, sizeof(hash)); + hash_length = 0; + + /* Compute hash using one-shot function call */ + status = psa_hash_compute(HASH_ALG, + sample_message, sample_message_length, + hash, sizeof(hash), + &hash_length); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_hash_compute failed\n"); + goto cleanup; + } + + if (hash_length != expected_hash_len || + (memcmp(hash, expected_hash, expected_hash_len) != 0)) { + mbedtls_printf("One-shot hash operation gave the wrong result!\n\n"); + goto cleanup; + } + + mbedtls_printf("One-shot hash operation successful!\n\n"); + + /* Print out result */ + mbedtls_printf("The SHA-256( '%s' ) is: ", sample_message); + + for (size_t j = 0; j < expected_hash_len; j++) { + mbedtls_printf("%02x", hash[j]); + } + + mbedtls_printf("\n"); + + mbedtls_psa_crypto_free(); + return EXIT_SUCCESS; + +cleanup: + psa_hash_abort(&hash_operation); + psa_hash_abort(&cloned_hash_operation); + return EXIT_FAILURE; +} +#endif /* !MBEDTLS_PSA_CRYPTO_C || !PSA_WANT_ALG_SHA_256 */ diff --git a/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c b/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c index 519c072..70c3e5b 100644 --- a/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c +++ b/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c @@ -32,11 +32,12 @@ * If you switch to a different algorithm you will need to update * the hash data in the EXAMPLE_HASH_VALUE macro below. */ -#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256) +#if !defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \ + (!defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256)) int main(void) { mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256" - "not defined.\r\n"); + "not defined, and not MBEDTLS_PSA_CRYPTO_CLIENT.\r\n"); return EXIT_SUCCESS; } #else 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 @@ enum { /* 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 @@ enum { 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 4ac6c4a..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 @@ -26,6 +26,10 @@ static psa_handle_t handle = -1; +#if defined(MBEDTLS_PSA_CRYPTO_C) +#error "Error: MBEDTLS_PSA_CRYPTO_C must be disabled on client build" +#endif + int psa_crypto_call(int function, uint8_t *in_params, size_t in_params_len, uint8_t **out_params, size_t *out_params_len) @@ -121,6 +125,1141 @@ void mbedtls_psa_crypto_free(void) } +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 ) @@ -154,7 +1293,7 @@ psa_status_t psa_hash_abort( ok = psa_crypto_call(PSA_HASH_ABORT, params, (size_t) (pos - params), &result, &result_length); if (!ok) { - printf("XXX server call failed\n"); + printf("PSA_HASH_ABORT server call failed\n"); goto fail; } @@ -223,7 +1362,7 @@ psa_status_t psa_hash_clone( ok = psa_crypto_call(PSA_HASH_CLONE, params, (size_t) (pos - params), &result, &result_length); if (!ok) { - printf("XXX server call failed\n"); + printf("PSA_HASH_CLONE server call failed\n"); goto fail; } @@ -298,7 +1437,7 @@ psa_status_t psa_hash_compare( ok = psa_crypto_call(PSA_HASH_COMPARE, params, (size_t) (pos - params), &result, &result_length); if (!ok) { - printf("XXX server call failed\n"); + printf("PSA_HASH_COMPARE server call failed\n"); goto fail; } @@ -374,7 +1513,7 @@ psa_status_t psa_hash_compute( ok = psa_crypto_call(PSA_HASH_COMPUTE, params, (size_t) (pos - params), &result, &result_length); if (!ok) { - printf("XXX server call failed\n"); + printf("PSA_HASH_COMPUTE server call failed\n"); goto fail; } @@ -454,7 +1593,7 @@ psa_status_t psa_hash_finish( ok = psa_crypto_call(PSA_HASH_FINISH, params, (size_t) (pos - params), &result, &result_length); if (!ok) { - printf("XXX server call failed\n"); + printf("PSA_HASH_FINISH server call failed\n"); goto fail; } @@ -533,7 +1672,7 @@ psa_status_t psa_hash_setup( ok = psa_crypto_call(PSA_HASH_SETUP, params, (size_t) (pos - params), &result, &result_length); if (!ok) { - printf("XXX server call failed\n"); + printf("PSA_HASH_SETUP server call failed\n"); goto fail; } @@ -602,7 +1741,7 @@ psa_status_t psa_hash_update( ok = psa_crypto_call(PSA_HASH_UPDATE, params, (size_t) (pos - params), &result, &result_length); if (!ok) { - printf("XXX server call failed\n"); + printf("PSA_HASH_UPDATE server call failed\n"); goto fail; } @@ -671,7 +1810,7 @@ psa_status_t psa_hash_verify( ok = psa_crypto_call(PSA_HASH_VERIFY, params, (size_t) (pos - params), &result, &result_length); if (!ok) { - printf("XXX server call failed\n"); + printf("PSA_HASH_VERIFY server call failed\n"); goto fail; } @@ -699,3 +1838,78 @@ fail: 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 919eb84..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 @@ -17,6 +17,10 @@ #include "service.h" +#if !defined(MBEDTLS_PSA_CRYPTO_C) +#error "Error: MBEDTLS_PSA_CRYPTO_C must be enabled on server build" +#endif + // Returns 1 for success, 0 for failure int psa_crypto_init_wrapper( uint8_t *in_params, size_t in_params_len, @@ -67,12 +71,1342 @@ fail: } // 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) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_hash_operation_t operation; + psa_hash_operation_t *operation; uint8_t *pos = in_params; size_t remaining = in_params_len; @@ -84,7 +1418,7 @@ int psa_hash_abort_wrapper( goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); if (!ok) { goto fail; } @@ -92,14 +1426,14 @@ int psa_hash_abort_wrapper( // Now we call the actual target function status = psa_hash_abort( - &operation + operation ); // NOTE: Should really check there is no overflow as we go along. size_t result_size = psasim_serialise_begin_needs() + psasim_serialise_psa_status_t_needs(status) + - psasim_serialise_psa_hash_operation_t_needs(operation); + psasim_server_serialise_psa_hash_operation_t_needs(operation); result = malloc(result_size); if (result == NULL) { @@ -119,7 +1453,7 @@ int psa_hash_abort_wrapper( goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); if (!ok) { goto fail; } @@ -141,8 +1475,8 @@ int psa_hash_clone_wrapper( uint8_t **out_params, size_t *out_params_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_hash_operation_t source_operation; - psa_hash_operation_t target_operation; + psa_hash_operation_t *source_operation; + psa_hash_operation_t *target_operation; uint8_t *pos = in_params; size_t remaining = in_params_len; @@ -154,12 +1488,12 @@ int psa_hash_clone_wrapper( goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &source_operation); + ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &source_operation); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &target_operation); + ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &target_operation); if (!ok) { goto fail; } @@ -167,15 +1501,15 @@ int psa_hash_clone_wrapper( // Now we call the actual target function status = psa_hash_clone( - &source_operation, - &target_operation + source_operation, + target_operation ); // NOTE: Should really check there is no overflow as we go along. size_t result_size = psasim_serialise_begin_needs() + psasim_serialise_psa_status_t_needs(status) + - psasim_serialise_psa_hash_operation_t_needs(target_operation); + psasim_server_serialise_psa_hash_operation_t_needs(target_operation); result = malloc(result_size); if (result == NULL) { @@ -195,7 +1529,7 @@ int psa_hash_clone_wrapper( goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, target_operation); + ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, target_operation); if (!ok) { goto fail; } @@ -406,7 +1740,7 @@ int psa_hash_finish_wrapper( uint8_t **out_params, size_t *out_params_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_hash_operation_t operation; + psa_hash_operation_t *operation; uint8_t *hash = NULL; size_t hash_size; size_t hash_length; @@ -421,7 +1755,7 @@ int psa_hash_finish_wrapper( goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); if (!ok) { goto fail; } @@ -439,7 +1773,7 @@ int psa_hash_finish_wrapper( // Now we call the actual target function status = psa_hash_finish( - &operation, + operation, hash, hash_size, &hash_length ); @@ -448,7 +1782,7 @@ int psa_hash_finish_wrapper( size_t result_size = psasim_serialise_begin_needs() + psasim_serialise_psa_status_t_needs(status) + - psasim_serialise_psa_hash_operation_t_needs(operation) + + psasim_server_serialise_psa_hash_operation_t_needs(operation) + psasim_serialise_buffer_needs(hash, hash_size) + psasim_serialise_size_t_needs(hash_length); @@ -470,7 +1804,7 @@ int psa_hash_finish_wrapper( goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); if (!ok) { goto fail; } @@ -506,7 +1840,7 @@ int psa_hash_setup_wrapper( uint8_t **out_params, size_t *out_params_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_hash_operation_t operation; + psa_hash_operation_t *operation; psa_algorithm_t alg; uint8_t *pos = in_params; @@ -519,7 +1853,7 @@ int psa_hash_setup_wrapper( goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); if (!ok) { goto fail; } @@ -532,7 +1866,7 @@ int psa_hash_setup_wrapper( // Now we call the actual target function status = psa_hash_setup( - &operation, + operation, alg ); @@ -540,7 +1874,7 @@ int psa_hash_setup_wrapper( size_t result_size = psasim_serialise_begin_needs() + psasim_serialise_psa_status_t_needs(status) + - psasim_serialise_psa_hash_operation_t_needs(operation); + psasim_server_serialise_psa_hash_operation_t_needs(operation); result = malloc(result_size); if (result == NULL) { @@ -560,7 +1894,7 @@ int psa_hash_setup_wrapper( goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); if (!ok) { goto fail; } @@ -582,7 +1916,7 @@ int psa_hash_update_wrapper( uint8_t **out_params, size_t *out_params_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_hash_operation_t operation; + psa_hash_operation_t *operation; uint8_t *input = NULL; size_t input_length; @@ -596,7 +1930,7 @@ int psa_hash_update_wrapper( goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); if (!ok) { goto fail; } @@ -609,7 +1943,7 @@ int psa_hash_update_wrapper( // Now we call the actual target function status = psa_hash_update( - &operation, + operation, input, input_length ); @@ -617,7 +1951,7 @@ int psa_hash_update_wrapper( size_t result_size = psasim_serialise_begin_needs() + psasim_serialise_psa_status_t_needs(status) + - psasim_serialise_psa_hash_operation_t_needs(operation); + psasim_server_serialise_psa_hash_operation_t_needs(operation); result = malloc(result_size); if (result == NULL) { @@ -637,7 +1971,7 @@ int psa_hash_update_wrapper( goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); if (!ok) { goto fail; } @@ -663,7 +1997,7 @@ int psa_hash_verify_wrapper( uint8_t **out_params, size_t *out_params_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_hash_operation_t operation; + psa_hash_operation_t *operation; uint8_t *hash = NULL; size_t hash_length; @@ -677,7 +2011,7 @@ int psa_hash_verify_wrapper( goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); if (!ok) { goto fail; } @@ -690,7 +2024,7 @@ int psa_hash_verify_wrapper( // Now we call the actual target function status = psa_hash_verify( - &operation, + operation, hash, hash_length ); @@ -698,7 +2032,7 @@ int psa_hash_verify_wrapper( size_t result_size = psasim_serialise_begin_needs() + psasim_serialise_psa_status_t_needs(status) + - psasim_serialise_psa_hash_operation_t_needs(operation); + psasim_server_serialise_psa_hash_operation_t_needs(operation); result = malloc(result_size); if (result == NULL) { @@ -718,7 +2052,7 @@ int psa_hash_verify_wrapper( goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); if (!ok) { goto fail; } @@ -738,6 +2072,94 @@ fail: 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; @@ -778,6 +2200,62 @@ psa_status_t psa_crypto_call(psa_msg_t msg) 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); @@ -810,6 +2288,10 @@ psa_status_t psa_crypto_call(psa_msg_t msg) 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 19c6a0b..ee3894f 100755 --- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl +++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl @@ -268,6 +268,10 @@ sub server_implementations_header #include "psa_sim_serialise.h" #include "service.h" + +#if !defined(MBEDTLS_PSA_CRYPTO_C) +#error "Error: MBEDTLS_PSA_CRYPTO_C must be enabled on server build" +#endif EOF } @@ -301,6 +305,10 @@ sub client_calls_header PRINT("Client: " fmt, ##__VA_ARGS__) static psa_handle_t handle = -1; + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#error "Error: MBEDTLS_PSA_CRYPTO_C must be disabled on client build" +#endif EOF $code .= debug_functions() if $debug; @@ -522,8 +530,9 @@ EOF push(@buffers, $n1); # Add to the list to be free()d at end } else { $argname =~ s/^\*//; # Remove any leading * + my $pointer = ($argtype =~ /^psa_\w+_operation_t/) ? "*" : ""; print $fh <<EOF; - $argtype $argname; + $argtype $pointer$argname; EOF } } @@ -574,9 +583,10 @@ EOF EOF } else { $argname =~ s/^\*//; # Remove any leading * + my $server_specific = ($argtype =~ /^psa_\w+_operation_t/) ? "server_" : ""; print $fh <<EOF; - ok = psasim_deserialise_${argtype}(&pos, &remaining, &$argname); + ok = psasim_${server_specific}deserialise_${argtype}(&pos, &remaining, &$argname); if (!ok) { goto fail; } @@ -588,7 +598,7 @@ EOF // Now we call the actual target function EOF - output_call($fh, $f, $name); + output_call($fh, $f, $name, 1); my @outputs = grep($_->{is_output}, @$args); @@ -616,9 +626,10 @@ EOF my $sep = ($i == $#outputs) ? ";" : " +"; $argtype =~ s/^const //; $argname =~ s/^\*//; # Remove any leading * + my $server_specific = ($argtype =~ /^psa_\w+_operation_t/) ? "server_" : ""; print $fh <<EOF; - psasim_serialise_${argtype}_needs($argname)$sep + psasim_${server_specific}serialise_${argtype}_needs($argname)$sep EOF } @@ -673,9 +684,11 @@ EOF die("$0: $argname: HOW TO OUTPUT?\n"); } + my $server_specific = ($argtype =~ /^psa_\w+_operation_t/) ? "server_" : ""; + print $fh <<EOF; - ok = psasim_serialise_${argtype}(&rpos, &rremain, $argname); + ok = psasim_${server_specific}serialise_${argtype}(&rpos, &rremain, $argname); if (!ok) { goto fail; } @@ -790,7 +803,7 @@ EOF ok = psa_crypto_call($enum, params, (size_t) (pos - params), &result, &result_length); if (!ok) { - printf("XXX server call failed\\n"); + printf("$enum server call failed\\n"); goto fail; } EOF @@ -881,7 +894,7 @@ sub output_definition_begin sub output_call { - my ($fh, $f, $name) = @_; + my ($fh, $f, $name, $is_server) = @_; my $ret_name = $f->{return}->{name}; my $args = $f->{args}; @@ -900,6 +913,9 @@ sub output_call print $fh " $n1, $n2"; } else { $argname =~ s/^\*/\&/; # Replace leading * with & + if ($is_server && $argtype =~ /^psa_\w+_operation_t/) { + $argname =~ s/^\&//; # Actually, for psa_XXX_operation_t, don't do this on the server side + } print $fh " $argname"; } my $sep = ($i == $#$args) ? "\n );" : ","; @@ -1409,3 +1425,939 @@ psa_status_t psa_hash_compare(psa_algorithm_t alg, 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 78ae9d6..9e8c38b 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c @@ -51,6 +51,87 @@ * don't contain pointers. */ +/* include/psa/crypto_platform.h:typedef uint32_t mbedtls_psa_client_handle_t; + * but we don't get it on server builds, so redefine it here with a unique type name + */ +typedef uint32_t psasim_client_handle_t; + +typedef struct psasim_operation_s { + psasim_client_handle_t handle; +} psasim_operation_t; + +#define MAX_LIVE_HANDLES_PER_CLASS 100 /* this many slots */ + +static psa_hash_operation_t hash_operations[MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t hash_operation_handles[MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t next_hash_operation_handle = 1; + +/* Get a free slot */ +static ssize_t allocate_hash_operation_slot(void) +{ + psasim_client_handle_t handle = next_hash_operation_handle++; + if (next_hash_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 (hash_operation_handles[i] == 0) { + hash_operation_handles[i] = handle; + return i; + } + } + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_hash_slot_by_handle(psasim_client_handle_t handle) +{ + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (hash_operation_handles[i] == handle) { + return i; + } + } + + 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 @@ -404,3 +485,224 @@ int psasim_deserialise_psa_hash_operation_t(uint8_t **pos, return 1; } + +size_t psasim_server_serialise_psa_hash_operation_t_needs(psa_hash_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_hash_operation_t(uint8_t **pos, + size_t *remaining, + psa_hash_operation_t *operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - hash_operations; + + client_operation.handle = hash_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_hash_operation_t(uint8_t **pos, + size_t *remaining, + psa_hash_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_hash_operation_slot(); + } else { + slot = find_hash_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &hash_operations[slot]; + + 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 d5eaccf..9c69e65 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h @@ -408,3 +408,213 @@ int psasim_serialise_psa_hash_operation_t(uint8_t **pos, int psasim_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_server_serialise_psa_hash_operation_t() + * to serialise a `psa_hash_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_hash_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_hash_operation_t_needs(psa_hash_operation_t *value); + +/** Serialise a `psa_hash_operation_t` into a buffer on the server side. + * + * \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_hash_operation_t(uint8_t **pos, + size_t *remaining, + psa_hash_operation_t *value); + +/** Deserialise a `psa_hash_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_hash_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_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 5161db1..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 @@ die($usage) unless $which eq "c" || $which eq "h"; 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 @@ -55,15 +59,31 @@ if ($which eq "h") { if ($type eq "buffer") { print declare_buffer_functions(); } else { - print declare_needs($type); - print declare_serialise($type); - print declare_deserialise($type); + print declare_needs($type, ""); + print declare_serialise($type, ""); + print declare_deserialise($type, ""); + + if ($type =~ /^psa_\w+_operation_t$/) { + print declare_needs($type, "server_"); + print declare_serialise($type, "server_"); + print declare_deserialise($type, "server_"); + } } } } elsif ($which eq "c") { + my $have_operation_types = (grep(/psa_\w+_operation_t/, @types)) ? 1 : 0; + print c_header(); + print c_define_types_for_operation_types() if $have_operation_types; + + for my $type (@types) { + next unless $type =~ /^psa_(\w+)_operation_t$/; + print define_operation_type_data_and_functions($1); + } + + print c_define_begins(); for my $type (@types) { if ($type eq "buffer") { @@ -76,6 +96,12 @@ if ($which eq "h") { print define_needs($type); print define_serialise($type); print define_deserialise($type); + + if ($type =~ /^psa_\w+_operation_t$/) { + print define_server_needs($type); + print define_server_serialise($type); + print define_server_deserialise($type); + } } } @@ -85,15 +111,17 @@ if ($which eq "h") { sub declare_needs { - my ($type) = @_; + my ($type, $server) = @_; my $an = ($type =~ /^[ui]/) ? "an" : "a"; my $type_d = $type; $type_d =~ s/ /_/g; + my $ptr = (length($server)) ? "*" : ""; + return <<EOF; -/** Return how much buffer space is needed by \\c psasim_serialise_$type_d() +/** Return how much buffer space is needed by \\c psasim_${server}serialise_$type_d() * to serialise $an `$type`. * * \\param value The value that will be serialised into the buffer @@ -104,21 +132,25 @@ sub declare_needs * \\c psasim_serialise_$type_d() to serialise * the given value. */ -size_t psasim_serialise_${type_d}_needs($type value); +size_t psasim_${server}serialise_${type_d}_needs($type ${ptr}value); EOF } sub declare_serialise { - my ($type) = @_; + my ($type, $server) = @_; my $an = ($type =~ /^[ui]/) ? "an" : "a"; my $type_d = $type; $type_d =~ s/ /_/g; + my $server_side = (length($server)) ? " on the server side" : ""; + + my $ptr = (length($server)) ? "*" : ""; + return align_declaration(<<EOF); -/** Serialise $an `$type` into a buffer. +/** Serialise $an `$type` into a buffer${server_side}. * * \\param pos[in,out] Pointer to a `uint8_t *` holding current position * in the buffer. @@ -128,23 +160,27 @@ sub declare_serialise * * \\return \\c 1 on success ("okay"), \\c 0 on error. */ -int psasim_serialise_$type_d(uint8_t **pos, +int psasim_${server}serialise_$type_d(uint8_t **pos, size_t *remaining, - $type value); + $type ${ptr}value); EOF } sub declare_deserialise { - my ($type) = @_; + my ($type, $server) = @_; my $an = ($type =~ /^[ui]/) ? "an" : "a"; my $type_d = $type; $type_d =~ s/ /_/g; + my $server_side = (length($server)) ? " on the server side" : ""; + + my $ptr = (length($server)) ? "*" : ""; + return align_declaration(<<EOF); -/** Deserialise $an `$type` from a buffer. +/** Deserialise $an `$type` from a buffer${server_side}. * * \\param pos[in,out] Pointer to a `uint8_t *` holding current position * in the buffer. @@ -155,9 +191,9 @@ sub declare_deserialise * * \\return \\c 1 on success ("okay"), \\c 0 on error. */ -int psasim_deserialise_$type_d(uint8_t **pos, +int psasim_${server}deserialise_$type_d(uint8_t **pos, size_t *remaining, - $type *value); + $type ${ptr}*value); EOF } @@ -347,6 +383,25 @@ size_t psasim_serialise_${type_d}_needs($type value) EOF } +sub define_server_needs +{ + my ($type) = @_; + + my $type_d = $type; + $type_d =~ s/ /_/g; + + return <<EOF; + +size_t psasim_server_serialise_${type_d}_needs($type *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} +EOF +} + sub define_needs_isa { my ($type, $isa) = @_; @@ -391,6 +446,44 @@ int psasim_serialise_$type_d(uint8_t **pos, EOF } +sub define_server_serialise +{ + my ($type) = @_; + + my $t; + if ($type =~ /^psa_(\w+)_operation_t$/) { + $t = $1; + } else { + die("$0: define_server_serialise: $type: not supported\n"); + } + + my $type_d = $type; + $type_d =~ s/ /_/g; + + return align_signature(<<EOF); + +int psasim_server_serialise_$type_d(uint8_t **pos, + size_t *remaining, + $type *operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - ${t}_operations; + + client_operation.handle = ${t}_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} +EOF +} + sub define_serialise_isa { my ($type, $isa) = @_; @@ -439,6 +532,54 @@ int psasim_deserialise_$type_d(uint8_t **pos, EOF } +sub define_server_deserialise +{ + my ($type) = @_; + + my $t; + if ($type =~ /^psa_(\w+)_operation_t$/) { + $t = $1; + } else { + die("$0: define_server_serialise: $type: not supported\n"); + } + + my $type_d = $type; + $type_d =~ s/ /_/g; + + return align_signature(<<EOF); + +int psasim_server_deserialise_$type_d(uint8_t **pos, + size_t *remaining, + $type **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_${t}_operation_slot(); + } else { + slot = find_${t}_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &${t}_operations[slot]; + + return 1; +} +EOF +} + sub define_deserialise_isa { my ($type, $isa) = @_; @@ -623,6 +764,72 @@ sub c_header * data types (e.g. int), types typedef'd to those, and even structures that * don't contain pointers. */ +EOF +} + +sub c_define_types_for_operation_types +{ + return <<'EOF'; + +/* include/psa/crypto_platform.h:typedef uint32_t mbedtls_psa_client_handle_t; + * but we don't get it on server builds, so redefine it here with a unique type name + */ +typedef uint32_t psasim_client_handle_t; + +typedef struct psasim_operation_s { + psasim_client_handle_t handle; +} psasim_operation_t; + +#define MAX_LIVE_HANDLES_PER_CLASS 100 /* this many slots */ +EOF +} + +sub define_operation_type_data_and_functions +{ + my ($type) = @_; # e.g. 'hash' rather than 'psa_hash_operation_t' + + return <<EOF; + +static psa_${type}_operation_t ${type}_operations[MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t ${type}_operation_handles[MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t next_${type}_operation_handle = 1; + +/* Get a free slot */ +static ssize_t allocate_${type}_operation_slot(void) +{ + psasim_client_handle_t handle = next_${type}_operation_handle++; + if (next_${type}_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 (${type}_operation_handles[i] == 0) { + ${type}_operation_handles[i] = handle; + return i; + } + } + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_${type}_slot_by_handle(psasim_client_handle_t handle) +{ + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (${type}_operation_handles[i] == handle) { + return i; + } + } + + return -1; /* all in use */ +} +EOF +} + +sub c_define_begins +{ + return <<'EOF'; size_t psasim_serialise_begin_needs(void) { diff --git a/tests/psa-client-server/psasim/test/run_test.sh b/tests/psa-client-server/psasim/test/run_test.sh index 31429c8..45a317a 100755 --- a/tests/psa-client-server/psasim/test/run_test.sh +++ b/tests/psa-client-server/psasim/test/run_test.sh @@ -33,5 +33,5 @@ clean_run ./psa_partition -k & SERV_PID=$! wait_for_server_startup -./psa_client +./psa_client "$@" wait $SERV_PID diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 35b3ff9..44ac90e 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -964,18 +964,17 @@ helper_crypto_client_build() { 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 "$@" - - # cleanup() will restore some backed-up files which include $CONFIG_H and - # $CRYPTO_CONFIG_H. Built libraries were already copied to psasim at this - # point. - cleanup } ################################################################ @@ -6158,45 +6157,60 @@ component_check_test_helpers () { } component_test_psasim() { - msg "build library for client" - - helper_crypto_client_build client - msg "build library for server" - scripts/config.py crypto - helper_crypto_client_build server - msg "build psasim" - make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" + msg "build server" + make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" test/psa_partition + + # cleanup() will restore some backed-up files which include $CONFIG_H and + # $CRYPTO_CONFIG_H. Built libraries were already copied to psasim at this + # point. + cleanup + + msg "build library for client" + helper_crypto_client_build client + + msg "build psasim to test psa_client" + rm -f tests/psa-client-server/psasim/test/psa_client # In case left behind + make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" test/psa_client msg "test psasim" tests/psa-client-server/psasim/test/run_test.sh + msg "build psasim to test psa_hash_compute" # Delete the executable to ensure we build using the right MAIN rm tests/psa-client-server/psasim/test/psa_client # API under test: psa_hash_compute() - make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="src/aut_psa_hash_compute.c" + make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="src/aut_psa_hash_compute.c" test/psa_client msg "test psasim running psa_hash_compute" tests/psa-client-server/psasim/test/run_test.sh - # Next APIs under test: psa_hash_*(). Just use the PSA hash example. - aut_psa_hash="../../../programs/psa/psa_hash.c" - if [ -f "tests/psa-client-server/psasim/$aut_psa_hash" ]; then - msg "build psasim to test all psa_hash_* APIs" - # Delete the executable to ensure we build using the right MAIN - rm tests/psa-client-server/psasim/test/psa_client - make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="$aut_psa_hash" + # Next APIs under test: psa_hash_*(). Use our copy of the PSA hash example. + msg "build psasim to test all psa_hash_* APIs" + # Delete the executable to ensure we build using the right MAIN + rm tests/psa-client-server/psasim/test/psa_client + make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="src/aut_psa_hash.c" test/psa_client + + msg "test psasim running psa_hash sample" + tests/psa-client-server/psasim/test/run_test.sh + + + # Next APIs under test: psa_aead_*(). Use our copy of the PSA aead example. + msg "build psasim to test all psa_aead_* APIs" + # Delete the executable to ensure we build using the right MAIN + rm tests/psa-client-server/psasim/test/psa_client + make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="src/aut_psa_aead_demo.c" test/psa_client - msg "test psasim running psa_hash sample" - tests/psa-client-server/psasim/test/run_test.sh - else - echo $aut_psa_hash NOT FOUND, so not running that test - fi + 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 |