diff --git a/psasim/Makefile b/psasim/Makefile index 88ea7091c4..a141807b39 100644 --- a/psasim/Makefile +++ b/psasim/Makefile @@ -1,64 +1,81 @@ -CFLAGS ?= -Wall -std=c99 -INCLUDE := -I./include/ -DESTDIR ?= /usr/local -PREFIX := libpsaff -BUILDDIR ?= bin +CFLAGS += -Wall -Werror -std=c99 -D_XOPEN_SOURCE=1 -D_POSIX_C_SOURCE=200809L -.PHONY: all install test uninstall run docker ci +ifeq ($(DEBUG),1) +override CFLAGS += -DDEBUG -O0 -g +endif -all: libpsaff.so +CLIENT_LIBS := -Lclient_libs -lpsaclient -lmbedtls -lmbedx509 -lmbedcrypto +SERVER_LIBS := -Lserver_libs -lmbedcrypto -libpsaff.so: - $(CC) $(INCLUDE) $(CFLAGS) -c -fpic src/common.c -o common.o - $(CC) $(INCLUDE) $(CFLAGS) -c -fpic src/client.c -o client.o - $(CC) $(INCLUDE) $(CFLAGS) -c -fpic src/service.c -o server.o - $(CC) -shared -o libpsaff.so common.o client.o server.o +MBEDTLS_ROOT_PATH = ../.. +COMMON_INCLUDE := -I./include -I$(MBEDTLS_ROOT_PATH)/include \ + -I$(MBEDTLS_ROOT_PATH)/tf-psa-crypto/include \ + -I$(MBEDTLS_ROOT_PATH)/tf-psa-crypto/drivers/builtin/include -ifeq ($(DEBUG),1) - CFLAGS += -DDEBUG -g -endif +GENERATED_H_FILES = include/psa_manifest/manifest.h \ + include/psa_manifest/pid.h \ + include/psa_manifest/sid.h + +LIBPSACLIENT_SRC = src/psa_ff_client.c \ + src/psa_sim_crypto_client.c \ + src/psa_sim_serialise.c +LIBPSACLIENT_OBJS=$(LIBPSACLIENT_SRC:.c=.o) + +PSA_CLIENT_BASE_SRC = $(LIBPSACLIENT_SRC) src/client.c + +PSA_CLIENT_FULL_SRC = $(LIBPSACLIENT_SRC) \ + $(wildcard src/aut_*.c) + +PARTITION_SERVER_BOOTSTRAP = src/psa_ff_bootstrap_TEST_PARTITION.c + +PSA_SERVER_SRC = $(PARTITION_SERVER_BOOTSTRAP) \ + src/psa_ff_server.c \ + src/psa_sim_crypto_server.c \ + src/psa_sim_serialise.c + +.PHONY: all clean client_libs server_libs + +all: + +test/seedfile: + dd if=/dev/urandom of=./test/seedfile bs=64 count=1 + +src/%.o: src/%.c $(GENERATED_H_FILES) + $(CC) $(COMMON_INCLUDE) $(CFLAGS) -c $< $(LDFLAGS) -o $@ + +client_libs/libpsaclient: $(LIBPSACLIENT_OBJS) + mkdir -p client_libs + $(AR) -src client_libs/libpsaclient.a $(LIBPSACLIENT_OBJS) + +test/psa_client_base: $(PSA_CLIENT_BASE_SRC) $(GENERATED_H_FILES) test/seedfile + $(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_BASE_SRC) $(CLIENT_LIBS) $(LDFLAGS) -o $@ + +test/psa_client_full: $(PSA_CLIENT_FULL_SRC) $(GENERATED_H_FILES) test/seedfile + $(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_FULL_SRC) $(CLIENT_LIBS) $(LDFLAGS) -o $@ + +test/psa_server: $(PSA_SERVER_SRC) $(GENERATED_H_FILES) + $(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_SERVER_SRC) $(SERVER_LIBS) $(LDFLAGS) -o $@ + +$(PARTITION_SERVER_BOOTSTRAP) $(GENERATED_H_FILES): src/manifest.json src/server.c + tools/psa_autogen.py src/manifest.json + +# Build MbedTLS libraries (crypto, x509 and tls) and copy them locally to +# build client/server applications. +# +# Note: these rules assume that mbedtls_config.h is already configured by all.sh. +# If not using all.sh then the user must do it manually. +client_libs: client_libs/libpsaclient +client_libs server_libs: + $(MAKE) -C $(MBEDTLS_ROOT_PATH)/library CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" libmbedcrypto.a libmbedx509.a libmbedtls.a + mkdir -p $@ + cp $(MBEDTLS_ROOT_PATH)/library/libmbed*.a $@/ -clean: - rm -rf $(BUILDDIR) - rm -f *.so *.o - rm -rf test/*dSYM - cd test && make clean - -test: - cd test && make - -test/partition: - cd test && make - -run: test/partition - pkill partition || true - pkill client || true - ipcs | grep q | awk '{ printf " -q " $$2 }' | xargs ipcrm > /dev/null 2>&1 || true - (sleep 3 && ./test/client)& - ./test/partition - -ci: - pkill client || true - ipcs | grep q | awk '{ printf " -q " $$2 }' | xargs ipcrm > /dev/null 2>&1 || true - ./test/partition 2>&1 & - sleep 3 && ./test/client - pkill partition || true - -docker: - @docker run --rm -ti -v $$PWD:/opt --entrypoint /bin/bash ubuntu \ - -c "cd /opt && ls && apt-get update -qq && apt install \ - -y gcc make gdb python -qq && make clean && make install && make test && ldconfig && make run" - -install: libpsaff.so - mkdir -p $(DESTDIR)/lib - mkdir -p $(DESTDIR)/include - cp libpsaff.so $(DESTDIR)/lib/ - cp -r include/* $(DESTDIR)/include/ - cp tools/psa_autogen /usr/local/bin/ - -uninstall: - rm $(DESTDIR)/lib/libpsaff.so - rm -rf $(DESTDIR)/include/psa - rm -rf $(DESTDIR)/include/psasim - rm -f /usr/local/bin/psa_autogen +clean_server_intermediate_files: + rm -f $(PARTITION_SERVER_BOOTSTRAP) + rm -rf include/psa_manifest +clean: clean_server_intermediate_files + rm -f test/psa_client_base test/psa_client_full test/psa_server + rm -rf client_libs server_libs + rm -f test/psa_service_* test/psa_notify_* test/*.log + rm -f test/seedfile diff --git a/psasim/README.md b/psasim/README.md index e8f2863180..db49ae9473 100644 --- a/psasim/README.md +++ b/psasim/README.md @@ -1,60 +1,42 @@ # psasim -This tool simulates a PSA Firmware Framework implementation. -It allows you to develop secure partitions and their clients on a desktop computer. -It should be able to run on all systems that support POSIX and System V IPC: -e.g. macOS, Linux, FreeBSD, and perhaps Windows 10 WSL2. +PSASIM holds necessary C source and header files which allows to test Mbed TLS in a "pure crypto client" scenario, i.e `MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C`. +In practical terms it means that this allow to build PSASIM with Mbed TLS sources and get 2 Linux applications, a client and a server, which are connected through Linux's shared memeory, and in which the client relies on the server to perform all PSA Crypto operations. -Please note that the code in this directory is maintained by the Mbed TLS / PSA Crypto project solely for the purpose of testing the use of Mbed TLS with client/service separation. We do not recommend using this code for any other purpose. In particular: +The goal of PSASIM is _not_ to provide a ready-to-use solution for anyone looking to implement the pure crypto client structure (see [Limitations](#limitations) for details), but to provide an example of TF-PSA-Crypto RPC (Remote Procedure Call) implementation using Mbed TLS. +## Limitations -* This simulator is not intended to pass or demonstrate compliance. -* This code is only intended for simulation and does not have any security goals. It does not isolate services from clients. +In the current implementation: -## Building +- Only Linux PC is supported. +- There can be only 1 client connected to 1 server. +- Shared memory is the only communication medium allowed. Others can be implemented (ex: net sockets), but in terms of simulation speed shared memory proved to be the fastest. +- Server is not secure at all: keys and operation structs are stored on the RAM, so they can easily be dumped. -To build and run the test program make sure you have `make`, `python` and a -C compiler installed and then enter the following commands: +## Testing -```sh -make install -make run -``` +Please refer to `tests/scripts/components-psasim.sh` for guidance on how to build & test PSASIM: -On Linux you may need to run `ldconfig` to ensure the library is properly installed. +- `component_test_psasim()`: builds the server and a couple of test clients which are used to evaluate some basic PSA Crypto API commands. +- `component_test_suite_with_psasim()`: builds the server and _all_ the usual test suites (those found under the `/tests/suites/*` folder) which are used by the CI and runs them. A small subset of test suites (`test_suite_constant_time_hmac`,`test_suite_lmots`,`test_suite_lms`) are being skipped, for CI turnover time optimization. They can be run locally if required. -An example pair of programs is included in the `test` directory. +## How to update automatically generated files -## Features +A significant portion of the intermediate code of PSASIM is auto-generated using Perl. In particular: -The implemented API is intended to be compliant with PSA-FF 1.0.0 with the exception of a couple of things that are a work in progress: +- `psa_sim_serialise.[c|h]`: + - Generated by `psa_sim_serialise.pl`. + - These files provide the serialisation/deserialisation support that is required to pass functions' parameters between client and server. +- `psa_sim_crypto_[client|server].c` and `psa_functions_codes.h`: + - Generated by `psa_sim_generate.pl`. + - `psa_sim_crypto_[client|server].c` provide interfaces for PSA Crypto APIs on client and server sides, while `psa_functions_codes.h` simply enumerates all PSA Crypto APIs. -* `psa_notify` support -* "strict" policy in manifest +These files need to be regenerated whenever some PSA Crypto API is added/deleted/modified. The procedure is as follows: -The only supported "interrupts" are POSIX signals, which act -as a "virtual interrupt". - -The standard PSA RoT APIs are not included (e.g. cryptography, attestation, lifecycle etc). - -## Design - -The code is designed to be readable rather than fast or secure. -In this implementation only one message is delivered to a -RoT service at a time. -The code is not thread-safe. - -To debug the simulator enable the debug flag: - -```sh -make DEBUG=1 install -``` - -## Unsupported features - -Because this is a simulator there are a few things that -can't be reasonably emulated: - -* Manifest MMIO regions are unsupported -* Manifest priority field is ignored -* Partition IDs are in fact POSIX `pid_t`, which are only assigned at runtime, - making it infeasible to populate pid.h with correct values. +- `psa_sim_serialise.[c|h]`: + - go to `/tests/psa-client-server/psasim/src/` + - run `./psa_sim_serialise.pl h > psa_sim_serialise.h` + - run `./psa_sim_serialise.pl c > psa_sim_serialise.c` +- `psa_sim_crypto_[client|server].c` and `psa_functions_codes.h`: + - go to Mbed TLS' root folder + - run `./tests/psa-client-server/psasim/src/psa_sim_generate.pl` diff --git a/psasim/include/psa/client.h b/psasim/include/client.h similarity index 94% rename from psasim/include/psa/client.h rename to psasim/include/client.h index 55d536917e..d48498e682 100644 --- a/psasim/include/psa/client.h +++ b/psasim/include/client.h @@ -14,7 +14,10 @@ extern "C" { #include #include -#include + +#include "psa/crypto.h" + +#include "error_ext.h" /*********************** PSA Client Macros and Types *************************/ #define PSA_FRAMEWORK_VERSION (0x0100) @@ -32,12 +35,6 @@ extern "C" { #define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t) (handle) > 0) #define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t) (handle)) -#define PSA_MAX_IOVEC (4u) - -#define PSA_IPC_CALL (0) - -typedef int32_t psa_handle_t; - /** * A read-only input memory region provided to an RoT Service. */ diff --git a/psasim/include/common.h b/psasim/include/common.h new file mode 100644 index 0000000000..ee5b5a3789 --- /dev/null +++ b/psasim/include/common.h @@ -0,0 +1,52 @@ +/* Common definitions used for clients and services */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include +#include + +/* Increasing this might break on some platforms */ +#define MAX_FRAGMENT_SIZE 200 + +#define CONNECT_REQUEST 1 +#define CALL_REQUEST 2 +#define CLOSE_REQUEST 3 +#define VERSION_REQUEST 4 +#define READ_REQUEST 5 +#define READ_RESPONSE 6 +#define WRITE_REQUEST 7 +#define WRITE_RESPONSE 8 +#define SKIP_REQUEST 9 +#define PSA_REPLY 10 + +#define NON_SECURE (1 << 30) + +typedef int32_t psa_handle_t; + +#define PSA_MAX_IOVEC (4u) + +#define PSA_IPC_CALL (0) + +struct message_text { + int qid; + int32_t psa_type; + char buf[MAX_FRAGMENT_SIZE]; +}; + +struct message { + long message_type; + struct message_text message_text; +}; + +typedef struct vector_sizes { + size_t invec_sizes[PSA_MAX_IOVEC]; + size_t outvec_sizes[PSA_MAX_IOVEC]; +} vector_sizes_t; + +#endif /* _COMMON_H_ */ diff --git a/psasim/include/error_ext.h b/psasim/include/error_ext.h new file mode 100644 index 0000000000..6c82b8a72f --- /dev/null +++ b/psasim/include/error_ext.h @@ -0,0 +1,19 @@ +/* PSA status codes used by psasim. */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_ERROR_H +#define PSA_ERROR_H + +#include + +#include "common.h" + +#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t) -129) +#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t) -130) +#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t) -131) + +#endif diff --git a/psasim/include/psasim/init.h b/psasim/include/init.h similarity index 94% rename from psasim/include/psasim/init.h rename to psasim/include/init.h index 9496fc2a1c..de95d905c7 100644 --- a/psasim/include/psasim/init.h +++ b/psasim/include/init.h @@ -6,7 +6,7 @@ */ #include -#include +#include void raise_signal(psa_signal_t signal); void __init_psasim(const char **array, int size, diff --git a/psasim/include/psa/lifecycle.h b/psasim/include/lifecycle.h similarity index 100% rename from psasim/include/psa/lifecycle.h rename to psasim/include/lifecycle.h diff --git a/psasim/include/psa/error.h b/psasim/include/psa/error.h deleted file mode 100644 index 2a7558a5d0..0000000000 --- a/psasim/include/psa/error.h +++ /dev/null @@ -1,36 +0,0 @@ -/* PSA status codes used by psasim. */ - -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -#ifndef PSA_ERROR_H -#define PSA_ERROR_H -#include -typedef int32_t psa_status_t; - -#define PSA_SUCCESS ((psa_status_t) 0) - -#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t) -129) -#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t) -130) -#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t) -131) -#define PSA_ERROR_GENERIC_ERROR ((psa_status_t) -132) -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t) -133) -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t) -134) -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t) -135) -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t) -136) -#define PSA_ERROR_BAD_STATE ((psa_status_t) -137) -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t) -138) -#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t) -139) -#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t) -140) -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t) -141) -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t) -142) -#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t) -143) -#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t) -144) -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t) -145) -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t) -146) -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t) -147) -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t) -149) - -#endif diff --git a/psasim/include/psa/service.h b/psasim/include/service.h similarity index 99% rename from psasim/include/psa/service.h rename to psasim/include/service.h index 9ae801d8fd..cbcb918cb2 100644 --- a/psasim/include/psa/service.h +++ b/psasim/include/service.h @@ -14,7 +14,11 @@ extern "C" { #include #include #include -#include + +#include "common.h" + +#include "psa/crypto.h" + /********************** PSA Secure Partition Macros and Types ****************/ /* PSA wait timeouts */ diff --git a/psasim/include/util.h b/psasim/include/util.h new file mode 100644 index 0000000000..dfc9a32379 --- /dev/null +++ b/psasim/include/util.h @@ -0,0 +1,33 @@ +/* Common definitions used for clients and services */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "service.h" + +#include + +#define PRINT(fmt, ...) \ + fprintf(stdout, fmt "\n", ##__VA_ARGS__) + +#if defined(DEBUG) +#define INFO(fmt, ...) \ + fprintf(stdout, "Info (%s - %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#else /* !DEBUG */ +#define INFO(...) +#endif /* DEBUG*/ + +#define ERROR(fmt, ...) \ + fprintf(stderr, "Error (%s - %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) + +#define FATAL(fmt, ...) \ + { \ + fprintf(stderr, "Fatal (%s - %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ + abort(); \ + } + +#define PROJECT_ID 'M' +#define PATHNAMESIZE 256 +#define TMP_FILE_BASE_PATH "./" diff --git a/psasim/src/aut_main.c b/psasim/src/aut_main.c new file mode 100644 index 0000000000..ed198790c6 --- /dev/null +++ b/psasim/src/aut_main.c @@ -0,0 +1,71 @@ +/** + * This is the base AUT that exectues all other AUTs meant to test PSA APIs + * through PSASIM. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +/* First include Mbed TLS headers to get the Mbed TLS configuration and + * platform definitions that we'll use in this program. Also include + * standard C headers for functions we'll use here. */ +#include "mbedtls/build_info.h" + +#include "psa/crypto.h" + +#include +#include +#include + +int psa_hash_compute_main(void); +int psa_hash_main(void); +int psa_aead_encrypt_main(char *cipher_name); +int psa_aead_encrypt_decrypt_main(void); +int psa_cipher_encrypt_decrypt_main(void); +int psa_asymmetric_encrypt_decrypt_main(void); +int psa_random_main(void); +int psa_mac_main(void); +int psa_key_agreement_main(void); +int psa_sign_verify_main(void); +int psa_hkdf_main(void); + +#define TEST_MODULE(main_func) \ + do { \ + char title[128] = { 0 }; \ + char separator[128] = { 0 }; \ + int title_len = snprintf(title, sizeof(title), "=== Test: %s ===", #main_func); \ + memset(separator, '=', title_len); \ + printf("%s\n%s\n%s\n", separator, title, separator); \ + ret = main_func; \ + if (ret != 0) { \ + goto exit; \ + } \ + } while (0) + +int main() +{ + int ret; + + TEST_MODULE(psa_hash_compute_main()); + TEST_MODULE(psa_hash_main()); + + TEST_MODULE(psa_aead_encrypt_main("aes128-gcm")); + TEST_MODULE(psa_aead_encrypt_main("aes256-gcm")); + TEST_MODULE(psa_aead_encrypt_main("aes128-gcm_8")); + TEST_MODULE(psa_aead_encrypt_main("chachapoly")); + TEST_MODULE(psa_aead_encrypt_decrypt_main()); + TEST_MODULE(psa_cipher_encrypt_decrypt_main()); + TEST_MODULE(psa_asymmetric_encrypt_decrypt_main()); + + TEST_MODULE(psa_random_main()); + + TEST_MODULE(psa_mac_main()); + TEST_MODULE(psa_key_agreement_main()); + TEST_MODULE(psa_sign_verify_main()); + TEST_MODULE(psa_hkdf_main()); + +exit: + return (ret != 0) ? 1 : 0; +} diff --git a/psasim/src/aut_psa_aead_encrypt.c b/psasim/src/aut_psa_aead_encrypt.c new file mode 100644 index 0000000000..64463f57fc --- /dev/null +++ b/psasim/src/aut_psa_aead_encrypt.c @@ -0,0 +1,227 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "mbedtls/build_info.h" + +#include "psa/crypto.h" + +#include +#include +#include + +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 */ +#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 psa_aead_encrypt_main(char *cipher_name) +{ + psa_status_t status = PSA_SUCCESS; + + /* Initialize the PSA crypto library. */ + PSA_CHECK(psa_crypto_init()); + + /* Run the demo */ + PSA_CHECK(aead_demo(cipher_name)); + + /* Deinitialize the PSA crypto library. */ + mbedtls_psa_crypto_free(); + +exit: + return status == PSA_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/psasim/src/aut_psa_aead_encrypt_decrypt.c b/psasim/src/aut_psa_aead_encrypt_decrypt.c new file mode 100644 index 0000000000..87ef39a9ed --- /dev/null +++ b/psasim/src/aut_psa_aead_encrypt_decrypt.c @@ -0,0 +1,126 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +/* + * Temporary hack: psasim’s Makefile only does: + * -Itests/psa-client-server/psasim/include + * -I$(MBEDTLS_ROOT_PATH)/include + * -I$(MBEDTLS_ROOT_PATH)/tf-psa-crypto/include + * -I$(MBEDTLS_ROOT_PATH)/tf-psa-crypto/drivers/builtin/include + * None of those cover tf-psa-crypto/core, so we rely on the + * “-I$(MBEDTLS_ROOT_PATH)/include” entry plus a parent-relative + * include "../tf-psa-crypto/core/tf_psa_crypto_common.h" in order to pull in tf_psa_crypto_common.h here, + * which in turn gets MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING (to silence the + * new GCC-15 unterminated-string-initialization warning). + * See GitHub issue #10223 for the proper long-term fix. + * https://github.com/Mbed-TLS/mbedtls/issues/10223 + */ +#include "../tf-psa-crypto/core/tf_psa_crypto_common.h" +#include +#include +#include + +#define BUFFER_SIZE 500 + +static void print_bytestr(const uint8_t *bytes, size_t len) +{ + for (unsigned int idx = 0; idx < len; idx++) { + printf("%02X", bytes[idx]); + } +} + +int psa_aead_encrypt_decrypt_main(void) +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + uint8_t encrypt[BUFFER_SIZE] = { 0 }; + uint8_t decrypt[BUFFER_SIZE] = { 0 }; + const uint8_t plaintext[] = "Hello World!"; + /* We need to tell the compiler that we meant to leave out the null character. */ + const uint8_t key_bytes[32] MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + uint8_t nonce[PSA_AEAD_NONCE_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CCM)]; + size_t nonce_length = sizeof(nonce); + size_t ciphertext_length; + size_t plaintext_length; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_CCM); + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, 256); + + status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id); + if (status != PSA_SUCCESS) { + printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + status = psa_generate_random(nonce, nonce_length); + if (status != PSA_SUCCESS) { + printf("psa_generate_random failed\n"); + return EXIT_FAILURE; + } + + status = psa_aead_encrypt(key_id, // key + PSA_ALG_CCM, // algorithm + nonce, nonce_length, // nonce + NULL, 0, // additional data + plaintext, sizeof(plaintext), // plaintext + encrypt, sizeof(encrypt), // ciphertext + &ciphertext_length); // length of output + if (status != PSA_SUCCESS) { + printf("psa_aead_encrypt failed\n"); + return EXIT_FAILURE; + } + + printf("AES-CCM encryption:\n"); + printf("- Plaintext: '%s':\n", plaintext); + printf("- Key: "); + print_bytestr(key_bytes, sizeof(key_bytes)); + printf("\n- Nonce: "); + print_bytestr(nonce, nonce_length); + printf("\n- No additional data\n"); + printf("- Ciphertext:\n"); + + for (size_t j = 0; j < ciphertext_length; j++) { + if (j % 8 == 0) { + printf("\n "); + } + printf("%02x ", encrypt[j]); + } + + printf("\n"); + + status = psa_aead_decrypt(key_id, // key + PSA_ALG_CCM, // algorithm + nonce, nonce_length, // nonce + NULL, 0, // additional data + encrypt, ciphertext_length, // ciphertext + decrypt, sizeof(decrypt), // plaintext + &plaintext_length); // length of output + if (status != PSA_SUCCESS) { + printf("psa_aead_decrypt failed\n"); + return EXIT_FAILURE; + } + + if (memcmp(plaintext, decrypt, sizeof(plaintext)) != 0) { + printf("\nEncryption/Decryption failed!\n"); + } else { + printf("\nEncryption/Decryption successful!\n"); + } + + psa_destroy_key(key_id); + mbedtls_psa_crypto_free(); + return 0; +} diff --git a/psasim/src/aut_psa_asymmetric_encrypt_decrypt.c b/psasim/src/aut_psa_asymmetric_encrypt_decrypt.c new file mode 100644 index 0000000000..02d8cf486d --- /dev/null +++ b/psasim/src/aut_psa_asymmetric_encrypt_decrypt.c @@ -0,0 +1,81 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#include +#include + +#define KEY_BITS 4096 +#define BUFFER_SIZE PSA_BITS_TO_BYTES(KEY_BITS) + +static void print_bytestr(const uint8_t *bytes, size_t len) +{ + for (unsigned int idx = 0; idx < len; idx++) { + printf("%02X", bytes[idx]); + } +} + +int psa_asymmetric_encrypt_decrypt_main(void) +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + uint8_t original[BUFFER_SIZE/2] = { 0 }; + uint8_t encrypt[BUFFER_SIZE] = { 0 }; + uint8_t decrypt[BUFFER_SIZE] = { 0 }; + size_t encrypted_length; + size_t decrypted_length; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + status = psa_generate_random(original, sizeof(original)); + if (status != PSA_SUCCESS) { + printf("psa_generate_random() failed\n"); + return EXIT_FAILURE; + } + + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + psa_set_key_bits(&attributes, KEY_BITS); + + status = psa_generate_key(&attributes, &key_id); + if (status != PSA_SUCCESS) { + printf("psa_generate_key failed (%d)\n", status); + return EXIT_FAILURE; + } + + status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT, + original, sizeof(original), NULL, 0, + encrypt, sizeof(encrypt), &encrypted_length); + if (status != PSA_SUCCESS) { + printf("psa_asymmetric_encrypt failed (%d)\n", status); + return EXIT_FAILURE; + } + + status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT, + encrypt, encrypted_length, NULL, 0, + decrypt, sizeof(decrypt), &decrypted_length); + if (status != PSA_SUCCESS) { + printf("psa_cipher_decrypt failed (%d)\n", status); + return EXIT_FAILURE; + } + + if (memcmp(original, decrypt, sizeof(original)) != 0) { + printf("\nEncryption/Decryption failed!\n"); + } else { + printf("\nEncryption/Decryption successful!\n"); + } + + psa_destroy_key(key_id); + mbedtls_psa_crypto_free(); + return 0; +} diff --git a/psasim/src/aut_psa_cipher_encrypt_decrypt.c b/psasim/src/aut_psa_cipher_encrypt_decrypt.c new file mode 100644 index 0000000000..82bdca54dc --- /dev/null +++ b/psasim/src/aut_psa_cipher_encrypt_decrypt.c @@ -0,0 +1,84 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include "../tf-psa-crypto/core/tf_psa_crypto_common.h" +#include +#include +#include + +#define BUFFER_SIZE 4096 + +static void print_bytestr(const uint8_t *bytes, size_t len) +{ + for (unsigned int idx = 0; idx < len; idx++) { + printf("%02X", bytes[idx]); + } +} + +int psa_cipher_encrypt_decrypt_main(void) +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + uint8_t original[BUFFER_SIZE] = { 0 }; + uint8_t encrypt[BUFFER_SIZE] = { 0 }; + uint8_t decrypt[BUFFER_SIZE] = { 0 }; + /* We need to tell the compiler that we meant to leave out the null character. */ + const uint8_t key_bytes[32] MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + size_t encrypted_length; + size_t decrypted_length; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + status = psa_generate_random(original, sizeof(original)); + if (status != PSA_SUCCESS) { + printf("psa_generate_random() failed\n"); + return EXIT_FAILURE; + } + + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING); + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, 256); + + status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id); + if (status != PSA_SUCCESS) { + printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, + original, sizeof(original), + encrypt, sizeof(encrypt), &encrypted_length); + if (status != PSA_SUCCESS) { + printf("psa_cipher_encrypt failed\n"); + return EXIT_FAILURE; + } + + status = psa_cipher_decrypt(key_id, PSA_ALG_ECB_NO_PADDING, + encrypt, encrypted_length, + decrypt, sizeof(decrypt), &decrypted_length); + if (status != PSA_SUCCESS) { + printf("psa_cipher_decrypt failed\n"); + return EXIT_FAILURE; + } + + if (memcmp(original, decrypt, sizeof(original)) != 0) { + printf("\nEncryption/Decryption failed!\n"); + } else { + printf("\nEncryption/Decryption successful!\n"); + } + + psa_destroy_key(key_id); + mbedtls_psa_crypto_free(); + return 0; +} diff --git a/psasim/src/aut_psa_hash.c b/psasim/src/aut_psa_hash.c new file mode 100644 index 0000000000..b429c0bc58 --- /dev/null +++ b/psasim/src/aut_psa_hash.c @@ -0,0 +1,167 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#include +#include + +#include "mbedtls/build_info.h" +#include "mbedtls/platform.h" + +#define HASH_ALG PSA_ALG_SHA_256 + +static const uint8_t sample_message[] = "Hello World!"; +/* sample_message is terminated with a null byte which is not part of + * the message itself so we make sure to subtract it in order to get + * the message length. */ +static const size_t sample_message_length = sizeof(sample_message) - 1; + +#define EXPECTED_HASH_VALUE { \ + 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \ + 0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, \ + 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \ +} + +static const uint8_t expected_hash[] = EXPECTED_HASH_VALUE; +static const size_t expected_hash_len = sizeof(expected_hash); + +int psa_hash_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"); + } + + /* A bit of white-box testing: ensure that we can abort an operation more + * times than there are operation slots on the simulator server. + */ + for (int i = 0; i < 200; i++) { + /* This should be a no-op */ + status = psa_hash_abort(&hash_operation); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_hash_abort failed\n"); + goto cleanup; + } + } + + /* Compute hash using multi-part operation using the same operation struct */ + status = psa_hash_setup(&hash_operation, HASH_ALG); + if (status == PSA_ERROR_NOT_SUPPORTED) { + mbedtls_printf("unknown hash algorithm supplied\n"); + goto cleanup; + } else if (status != PSA_SUCCESS) { + mbedtls_printf("psa_hash_setup failed: %d\n", status); + goto cleanup; + } + + status = psa_hash_update(&hash_operation, sample_message, sample_message_length); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_hash_update failed\n"); + goto cleanup; + } + + /* Don't use psa_hash_finish() when going to check against an expected result */ + status = psa_hash_verify(&hash_operation, expected_hash, expected_hash_len); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_hash_verify failed: %d\n", status); + goto cleanup; + } else { + mbedtls_printf("Second 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; +} diff --git a/psasim/src/aut_psa_hash_compute.c b/psasim/src/aut_psa_hash_compute.c new file mode 100644 index 0000000000..959e0c38ab --- /dev/null +++ b/psasim/src/aut_psa_hash_compute.c @@ -0,0 +1,81 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#include +#include + +#include "mbedtls/build_info.h" +#include "mbedtls/platform.h" + +#define HASH_ALG PSA_ALG_SHA_256 + +static const uint8_t sample_message[] = "Hello World!"; +/* sample_message is terminated with a null byte which is not part of + * the message itself so we make sure to subtract it in order to get + * the message length. */ +static const size_t sample_message_length = sizeof(sample_message) - 1; + +#define EXPECTED_HASH_VALUE { \ + 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \ + 0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, \ + 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \ +} + +static const uint8_t expected_hash[] = EXPECTED_HASH_VALUE; +static const size_t expected_hash_len = sizeof(expected_hash); + +int psa_hash_compute_main(void) +{ + psa_status_t status; + uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)]; + size_t hash_length; + + 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; + } + + /* 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: + return EXIT_FAILURE; +} diff --git a/psasim/src/aut_psa_hkdf.c b/psasim/src/aut_psa_hkdf.c new file mode 100644 index 0000000000..891fdb3f92 --- /dev/null +++ b/psasim/src/aut_psa_hkdf.c @@ -0,0 +1,121 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#include +#include +#include "mbedtls/build_info.h" + +int psa_hkdf_main(void) +{ + psa_status_t status; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + + /* Example test vector from RFC 5869 */ + + /* Input keying material (IKM) */ + unsigned char ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; + + unsigned char salt[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c }; + + /* Context and application specific information, which can be of zero length */ + unsigned char info[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 }; + + /* Expected OKM based on the RFC 5869-provided test vector */ + unsigned char expected_okm[] = { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, + 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, + 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, + 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, + 0x58, 0x65 }; + + /* The output size of the HKDF function depends on the hash function used. + * In our case we use SHA-256, which produces a 32 byte fingerprint. + * Therefore, we allocate a buffer of 32 bytes to hold the output keying + * material (OKM). + */ + unsigned char output[32]; + + psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256); + + printf("PSA Crypto API: HKDF SHA-256 example\n\n"); + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&attributes, PSA_ALG_HKDF(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE); + + status = psa_import_key(&attributes, ikm, sizeof(ikm), &key_id); + if (status != PSA_SUCCESS) { + printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + status = psa_key_derivation_setup(&operation, alg); + if (status != PSA_SUCCESS) { + printf("psa_key_derivation_setup failed"); + return EXIT_FAILURE; + } + + status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, + salt, sizeof(salt)); + if (status != PSA_SUCCESS) { + printf("psa_key_derivation_input_bytes (salt) failed"); + return EXIT_FAILURE; + } + + status = psa_key_derivation_input_key(&operation, PSA_KEY_DERIVATION_INPUT_SECRET, + key_id); + if (status != PSA_SUCCESS) { + printf("psa_key_derivation_input_key failed"); + return EXIT_FAILURE; + } + + status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_INFO, + info, sizeof(info)); + if (status != PSA_SUCCESS) { + printf("psa_key_derivation_input_bytes (info) failed"); + return EXIT_FAILURE; + } + + status = psa_key_derivation_output_bytes(&operation, output, sizeof(output)); + if (status != PSA_SUCCESS) { + printf("psa_key_derivation_output_bytes failed"); + return EXIT_FAILURE; + } + + status = psa_key_derivation_abort(&operation); + if (status != PSA_SUCCESS) { + printf("psa_key_derivation_abort failed"); + return EXIT_FAILURE; + } + + printf("OKM: \n"); + + for (size_t j = 0; j < sizeof(output); j++) { + if (output[j] != expected_okm[j]) { + printf("\n --- Unexpected outcome!\n"); + return EXIT_FAILURE; + } + + if (j % 8 == 0) { + printf("\n "); + } + printf("%02x ", output[j]); + } + + printf("\n"); + mbedtls_psa_crypto_free(); + return EXIT_SUCCESS; +} diff --git a/psasim/src/aut_psa_key_agreement.c b/psasim/src/aut_psa_key_agreement.c new file mode 100644 index 0000000000..4a0aab1477 --- /dev/null +++ b/psasim/src/aut_psa_key_agreement.c @@ -0,0 +1,146 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + + +#include "psa/crypto.h" +#include +#include +#include +#include "mbedtls/build_info.h" +#include "mbedtls/debug.h" +#include "mbedtls/platform.h" + +#define BUFFER_SIZE 500 + +#define SERVER_PK_VALUE { \ + 0x04, 0xde, 0xa5, 0xe4, 0x5d, 0x0e, 0xa3, 0x7f, 0xc5, \ + 0x66, 0x23, 0x2a, 0x50, 0x8f, 0x4a, 0xd2, 0x0e, 0xa1, \ + 0x3d, 0x47, 0xe4, 0xbf, 0x5f, 0xa4, 0xd5, 0x4a, 0x57, \ + 0xa0, 0xba, 0x01, 0x20, 0x42, 0x08, 0x70, 0x97, 0x49, \ + 0x6e, 0xfc, 0x58, 0x3f, 0xed, 0x8b, 0x24, 0xa5, 0xb9, \ + 0xbe, 0x9a, 0x51, 0xde, 0x06, 0x3f, 0x5a, 0x00, 0xa8, \ + 0xb6, 0x98, 0xa1, 0x6f, 0xd7, 0xf2, 0x9b, 0x54, 0x85, \ + 0xf3, 0x20 \ +} + +#define KEY_BITS 256 + +int psa_key_agreement_main(void) +{ + psa_status_t status; + psa_key_attributes_t client_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_attributes_t server_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t client_key_id = 0; + psa_key_id_t server_key_id = 0; + uint8_t client_pk[BUFFER_SIZE] = { 0 }; + size_t client_pk_len; + size_t key_bits; + psa_key_type_t key_type; + + const uint8_t server_pk[] = SERVER_PK_VALUE; + uint8_t derived_key[BUFFER_SIZE] = { 0 }; + size_t derived_key_len; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + psa_set_key_usage_flags(&client_attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&client_attributes, PSA_ALG_ECDH); + psa_set_key_type(&client_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&client_attributes, KEY_BITS); + + /* Generate ephemeral key pair */ + status = psa_generate_key(&client_attributes, &client_key_id); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_generate_key failed\n"); + return EXIT_FAILURE; + } + status = psa_export_public_key(client_key_id, + client_pk, sizeof(client_pk), + &client_pk_len); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_export_public_key failed\n"); + return EXIT_FAILURE; + } + + mbedtls_printf("Client Public Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", client_pk_len); + + for (size_t j = 0; j < client_pk_len; j++) { + if (j % 8 == 0) { + mbedtls_printf("\n "); + } + mbedtls_printf("%02x ", client_pk[j]); + } + mbedtls_printf("\n\n"); + + psa_set_key_usage_flags(&server_attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT); + psa_set_key_algorithm(&server_attributes, PSA_ALG_ECDSA_ANY); + psa_set_key_type(&server_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + + /* Import server public key */ + status = psa_import_key(&server_attributes, server_pk, sizeof(server_pk), &server_key_id); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + status = psa_get_key_attributes(server_key_id, &check_attributes); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_get_key_attributes failed\n"); + return EXIT_FAILURE; + } + + key_bits = psa_get_key_bits(&check_attributes); + if (key_bits != 256) { + mbedtls_printf("Incompatible key size!\n"); + return EXIT_FAILURE; + } + + key_type = psa_get_key_type(&check_attributes); + if (key_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) { + mbedtls_printf("Unsupported key type!\n"); + return EXIT_FAILURE; + } + + mbedtls_printf("Server Public Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", sizeof(server_pk)); + + for (size_t j = 0; j < sizeof(server_pk); j++) { + if (j % 8 == 0) { + mbedtls_printf("\n "); + } + mbedtls_printf("%02x ", server_pk[j]); + } + mbedtls_printf("\n\n"); + + /* Generate ECDHE derived key */ + status = psa_raw_key_agreement(PSA_ALG_ECDH, // algorithm + client_key_id, // client secret key + server_pk, sizeof(server_pk), // server public key + derived_key, sizeof(derived_key), // buffer to store derived key + &derived_key_len); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_raw_key_agreement failed\n"); + return EXIT_FAILURE; + } + + mbedtls_printf("Derived Key (%" MBEDTLS_PRINTF_SIZET " bytes):\n", derived_key_len); + + for (size_t j = 0; j < derived_key_len; j++) { + if (j % 8 == 0) { + mbedtls_printf("\n "); + } + mbedtls_printf("%02x ", derived_key[j]); + } + mbedtls_printf("\n"); + + psa_destroy_key(server_key_id); + psa_destroy_key(client_key_id); + mbedtls_psa_crypto_free(); + return EXIT_SUCCESS; +} diff --git a/psasim/src/aut_psa_mac.c b/psasim/src/aut_psa_mac.c new file mode 100644 index 0000000000..18b4b571a3 --- /dev/null +++ b/psasim/src/aut_psa_mac.c @@ -0,0 +1,162 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#include +#include + +#include "mbedtls/build_info.h" + +/* constant-time buffer comparison */ +static inline int safer_memcmp(const void *a, const void *b, size_t n) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for (i = 0; i < n; i++) { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return diff; +} + + +int psa_mac_main(void) +{ + uint8_t input[] = "Hello World!"; + psa_status_t status; + size_t mac_size_real = 0; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + uint8_t mac[PSA_MAC_MAX_SIZE]; + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + const uint8_t key_bytes[16] = "kkkkkkkkkkkkkkkk"; + const uint8_t mbedtls_test_hmac_sha256[] = { + 0xae, 0x72, 0x34, 0x5a, 0x10, 0x36, 0xfb, 0x71, + 0x35, 0x3c, 0x7d, 0x6c, 0x81, 0x98, 0x52, 0x86, + 0x00, 0x4a, 0x43, 0x7c, 0x2d, 0xb3, 0x1a, 0xd8, + 0x67, 0xb1, 0xad, 0x11, 0x4d, 0x18, 0x49, 0x8b + }; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE | + PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + + status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id); + if (status != PSA_SUCCESS) { + printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + /* Single-part MAC operation with psa_mac_compute() */ + status = psa_mac_compute(key_id, + PSA_ALG_HMAC(PSA_ALG_SHA_256), + input, + sizeof(input), + mac, + sizeof(mac), + &mac_size_real); + if (status != PSA_SUCCESS) { + printf("psa_mac_compute failed\n"); + return EXIT_FAILURE; + } + + printf("HMAC-SHA-256(%s) with psa_mac_compute():\n", input); + + for (size_t j = 0; j < mac_size_real; j++) { + if (j % 8 == 0) { + printf("\n "); + } + printf("%02x ", mac[j]); + } + + printf("\n"); + + if (safer_memcmp(mac, + mbedtls_test_hmac_sha256, + mac_size_real + ) != 0) { + printf("\nMAC verified incorrectly!\n"); + } else { + printf("\nMAC verified correctly!\n"); + } + + psa_destroy_key(key_id); + + status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id); + if (status != PSA_SUCCESS) { + printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + /* Single-part MAC operation with psa_mac_verify() */ + status = psa_mac_verify(key_id, + PSA_ALG_HMAC(PSA_ALG_SHA_256), + input, + sizeof(input), + mbedtls_test_hmac_sha256, + sizeof(mbedtls_test_hmac_sha256)); + if (status != PSA_SUCCESS) { + printf("psa_mac_verify failed\n"); + return EXIT_FAILURE; + } else { + printf("psa_mac_verify passed successfully\n"); + } + + psa_destroy_key(key_id); + + status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id); + if (status != PSA_SUCCESS) { + printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + /* Multi-part MAC operation */ + status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256)); + if (status != PSA_SUCCESS) { + printf("psa_mac_sign_setup failed\n"); + return EXIT_FAILURE; + } + + status = psa_mac_update(&operation, input, sizeof(input)); + if (status != PSA_SUCCESS) { + printf("psa_mac_update failed\n"); + return EXIT_FAILURE; + } + + status = psa_mac_sign_finish(&operation, mac, sizeof(mac), &mac_size_real); + if (status != PSA_SUCCESS) { + printf("psa_mac_sign_finish failed\n"); + return EXIT_FAILURE; + } + + if (safer_memcmp(mac, + mbedtls_test_hmac_sha256, + mac_size_real + ) != 0) { + printf("MAC, calculated with multi-part MAC operation, verified incorrectly!\n"); + } else { + printf("MAC, calculated with multi-part MAC operation, verified correctly!\n"); + } + + psa_destroy_key(key_id); + mbedtls_psa_crypto_free(); + return EXIT_SUCCESS; +} diff --git a/psasim/src/aut_psa_random.c b/psasim/src/aut_psa_random.c new file mode 100644 index 0000000000..203f4d44ba --- /dev/null +++ b/psasim/src/aut_psa_random.c @@ -0,0 +1,47 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "mbedtls/build_info.h" + +#include +#include +#include +#include + +#include "mbedtls/private/entropy.h" + +#define BUFFER_SIZE 100 + +int psa_random_main(void) +{ + psa_status_t status; + uint8_t output[BUFFER_SIZE] = { 0 }; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + status = psa_generate_random(output, BUFFER_SIZE); + if (status != PSA_SUCCESS) { + printf("psa_generate_random failed\n"); + return EXIT_FAILURE; + } + + printf("Random bytes generated:\n"); + + for (size_t j = 0; j < BUFFER_SIZE; j++) { + if (j % 8 == 0) { + printf("\n "); + } + printf("%02x ", output[j]); + } + + printf("\n"); + + mbedtls_psa_crypto_free(); + return 0; +} diff --git a/psasim/src/aut_psa_sign_verify.c b/psasim/src/aut_psa_sign_verify.c new file mode 100644 index 0000000000..98df9e5162 --- /dev/null +++ b/psasim/src/aut_psa_sign_verify.c @@ -0,0 +1,93 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + + +#include "psa/crypto.h" +#include +#include +#include + +#include "mbedtls/build_info.h" +#include "mbedtls/platform.h" + +#define KEY_BYTES_VALUE { \ + 0x49, 0xc9, 0xa8, 0xc1, 0x8c, 0x4b, 0x88, 0x56, 0x38, 0xc4, 0x31, 0xcf, \ + 0x1d, 0xf1, 0xc9, 0x94, 0x13, 0x16, 0x09, 0xb5, 0x80, 0xd4, 0xfd, 0x43, \ + 0xa0, 0xca, 0xb1, 0x7d, 0xb2, 0xf1, 0x3e, 0xee \ +} + +#define PLAINTEXT_VALUE "Hello World!" + +/* SHA-256(plaintext) */ +#define HASH_VALUE { \ + 0x5a, 0x09, 0xe8, 0xfa, 0x9c, 0x77, 0x80, 0x7b, 0x24, 0xe9, 0x9c, 0x9c, \ + 0xf9, 0x99, 0xde, 0xbf, 0xad, 0x84, 0x41, 0xe2, 0x69, 0xeb, 0x96, 0x0e, \ + 0x20, 0x1f, 0x61, 0xfc, 0x3d, 0xe2, 0x0d, 0x5a \ +} + +int psa_sign_verify_main(void) +{ + psa_status_t status; + psa_key_id_t key_id = 0; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + uint8_t signature[PSA_SIGNATURE_MAX_SIZE] = { 0 }; + size_t signature_length; + const uint8_t key_bytes[] = KEY_BYTES_VALUE; + const uint8_t plaintext[] = PLAINTEXT_VALUE; + const uint8_t hash[] = HASH_VALUE; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + + status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id); + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + status = psa_sign_hash(key_id, // key handle + PSA_ALG_ECDSA(PSA_ALG_SHA_256), // signature algorithm + hash, sizeof(hash), // hash of the message + signature, sizeof(signature), // signature (as output) + &signature_length); // length of signature output + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_sign_hash failed\n"); + return EXIT_FAILURE; + } + + mbedtls_printf("ECDSA-SHA256 signature of SHA-256('%s'):\n", plaintext); + + for (size_t j = 0; j < signature_length; j++) { + if (j % 8 == 0) { + mbedtls_printf("\n "); + } + mbedtls_printf("%02x ", signature[j]); + } + + mbedtls_printf("\n"); + + status = psa_verify_hash(key_id, // key handle + PSA_ALG_ECDSA(PSA_ALG_SHA_256), // signature algorithm + hash, sizeof(hash), // hash of message + signature, signature_length); // signature + if (status != PSA_SUCCESS) { + mbedtls_printf("psa_verify_hash failed\n"); + return EXIT_FAILURE; + } else { + mbedtls_printf("\nSignature verification successful!\n"); + } + + psa_destroy_key(key_id); + mbedtls_psa_crypto_free(); + return EXIT_SUCCESS; +} diff --git a/psasim/src/client.c b/psasim/src/client.c index fa989002e8..4c63abf5a3 100644 --- a/psasim/src/client.c +++ b/psasim/src/client.c @@ -1,380 +1,23 @@ -/* PSA firmware framework client API */ +/* psasim test client */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +/* Includes from mbedtls */ +#include "psa/crypto.h" +#include "util.h" -#include "common.h" - -typedef struct internal_handle { - int server_qid; - int client_qid; - int internal_server_qid; - int valid; -} internal_handle_t; - -/* Access to this global is not thread safe */ -#define MAX_HANDLES 32 -static internal_handle_t handles[MAX_HANDLES] = { { 0 } }; - -static int get_next_free_handle() -{ - /* Never return handle 0 as it's a special null handle */ - for (int i = 1; i < MAX_HANDLES; i++) { - if (handles[i].valid == 0) { - return i; - } - } - return -1; -} - -static int handle_is_valid(psa_handle_t handle) -{ - if (handle > 0 && handle < MAX_HANDLES) { - if (handles[handle].valid == 1) { - return 1; - } - } - PROGRAMMER_ERROR("ERROR: Invalid handle"); - return 0; -} - -static int get_queue_info(char *path, int *cqid, int *sqid) +int main() { - - key_t server_queue_key; - int rx_qid, server_qid; - - INFO("Attempting to contact a RoT service queue"); - - if ((rx_qid = msgget(IPC_PRIVATE, 0660)) == -1) { - INFO("msgget: rx_qid"); - return -1; - } - - if ((server_queue_key = ftok(path, PROJECT_ID)) == -1) { - INFO("ftok"); - return -2; - } - - if ((server_qid = msgget(server_queue_key, 0)) == -1) { - INFO("msgget: server_qid"); - return -3; + /* psa_crypto_init() connects to the server */ + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + ERROR("psa_crypto_init returned %d", status); + return 1; } - *cqid = rx_qid; - *sqid = server_qid; - + mbedtls_psa_crypto_free(); return 0; } - -static psa_status_t process_response(int rx_qid, vectors_t *vecs, int type, - int *internal_server_qid) -{ - - struct message response, request; - psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED; - size_t invec_seek[4] = { 0 }; - size_t data_size; - psa_status_t invec, outvec; /* TODO: Should these be size_t ? */ - - assert(internal_server_qid > 0); - - while (1) { - data_size = 0; - invec = 0; - outvec = 0; - - // read response from server - if (msgrcv(rx_qid, &response, sizeof(struct message_text), 0, 0) == -1) { - puts(" msgrcv failed"); - return ret; - } - - // process return message from server - switch (response.message_type) { - case PSA_REPLY: - memcpy(&ret, response.message_text.buf, sizeof(psa_status_t)); - printf(" Message received from server: %d\n", ret); - if (type == PSA_IPC_CONNECT && ret > 0) { - *internal_server_qid = ret; - INFO(" ASSSIGNED q ID %d", *internal_server_qid); - ret = PSA_SUCCESS; - } - return ret; - break; - case READ_REQUEST: - /* read data request */ - request.message_type = READ_RESPONSE; - - assert(vecs != 0); - - memcpy(&invec, response.message_text.buf, sizeof(psa_status_t)); - memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t)); - INFO(" Partition asked for %lu bytes from invec %d", data_size, invec); - - /* need to add more checks here */ - assert(invec >= 0 && invec < PSA_MAX_IOVEC); - - if (data_size > MAX_FRAGMENT_SIZE) { - data_size = MAX_FRAGMENT_SIZE; - } - - /* send response */ - INFO(" invec_seek[invec] is %lu", invec_seek[invec]); - INFO(" Reading from offset %p", vecs->in_vec[invec].base + invec_seek[invec]); - memcpy(request.message_text.buf, - (vecs->in_vec[invec].base + invec_seek[invec]), - data_size); - - /* update invec base TODO: check me */ - invec_seek[invec] = invec_seek[invec] + data_size; - - INFO(" Sending message of type %li", request.message_type); - INFO(" with content %s\n", request.message_text.buf); - - if (msgsnd(*internal_server_qid, &request, - sizeof(int) + sizeof(uint32_t) + data_size, 0) == -1) { - INFO("Internal error: failed to respond to read request"); - } - break; - case WRITE_REQUEST: - assert(vecs != 0); - - request.message_type = WRITE_RESPONSE; - - memcpy(&outvec, response.message_text.buf, sizeof(psa_status_t)); - memcpy(&data_size, response.message_text.buf + sizeof(size_t), sizeof(size_t)); - INFO(" Partition wants to write %lu bytes to outvec %d", data_size, outvec); - - assert(outvec >= 0 && outvec < PSA_MAX_IOVEC); - - /* copy memory into message and send back amount written */ - size_t sofar = vecs->out_vec[outvec].len; - memcpy(vecs->out_vec[outvec].base + sofar, - response.message_text.buf+(sizeof(size_t)*2), data_size); - INFO(" Data size is %lu\n", data_size); - vecs->out_vec[outvec].len += data_size; - - INFO(" Sending message of type %li\n", request.message_type); - - /* send response */ - if (msgsnd(*internal_server_qid, &request, sizeof(int) + data_size, 0) == -1) { - INFO("Internal error: failed to respond to write request"); - } - break; - case SKIP_REQUEST: - memcpy(&invec, response.message_text.buf, sizeof(psa_status_t)); - memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t)); - INFO(" Partition asked to skip %lu bytes in invec %d", data_size, invec); - assert(invec >= 0 && invec < PSA_MAX_IOVEC); - /* update invec base TODO: check me */ - invec_seek[invec] = invec_seek[invec] + data_size; - break; - - default: - FATAL(" ERROR: unknown internal message type: %ld\n", - response.message_type); - return ret; - } - } -} - -static psa_status_t send(int rx_qid, int server_qid, int *internal_server_qid, - int32_t type, uint32_t minor_version, vectors_t *vecs) -{ - { - psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED; - size_t request_msg_size = (sizeof(int) + sizeof(long)); /* msg type plus queue id */ - struct message request; - request.message_type = 1; /* TODO: change this */ - request.message_text.psa_type = type; - vector_sizes_t vec_sizes; - - /* If the client is non-secure then set the NS bit */ - if (__psa_ff_client_security_state != 0) { - request.message_type |= NON_SECURE; - } - - assert(request.message_type >= 0); - - INFO("SEND: Sending message of type %ld with psa_type %d", request.message_type, type); - INFO(" internal_server_qid = %i", *internal_server_qid); - - request.message_text.qid = rx_qid; - - if (type == PSA_IPC_CONNECT) { - memcpy(request.message_text.buf, &minor_version, sizeof(minor_version)); - request_msg_size = request_msg_size + sizeof(minor_version); - INFO(" Request msg size is %lu", request_msg_size); - } else { - assert(internal_server_qid > 0); - } - - if (vecs != NULL && type >= PSA_IPC_CALL) { - - bzero(&vec_sizes, sizeof(vec_sizes)); - - /* Copy invec sizes */ - for (size_t i = 0; i < (vecs->in_len); i++) { - vec_sizes.invec_sizes[i] = vecs->in_vec[i].len; - INFO(" Client sending vector %lu: %lu", i, vec_sizes.invec_sizes[i]); - } - - /* Copy outvec sizes */ - for (size_t i = 0; i < (vecs->out_len); i++) { - vec_sizes.outvec_sizes[i] = vecs->out_vec[i].len; - - /* Reset to 0 since we need to eventually fill in with bytes written */ - vecs->out_vec[i].len = 0; - } - - memcpy(request.message_text.buf, &vec_sizes, sizeof(vec_sizes)); - request_msg_size = request_msg_size + sizeof(vec_sizes); - } - - INFO(" Sending and then waiting"); - - // send message to server - if (msgsnd(server_qid, &request, request_msg_size, 0) == -1) { - puts(" msgsnd failed"); - return ret; - } - - return process_response(rx_qid, vecs, type, internal_server_qid); - } -} - - -uint32_t psa_framework_version(void) -{ - return PSA_FRAMEWORK_VERSION; -} - -psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version) -{ - - int idx; - psa_status_t ret; - char pathname[PATHNAMESIZE] = { 0 }; - - idx = get_next_free_handle(); - - /* if there's a free handle available */ - if (idx >= 0) { - snprintf(pathname, PATHNAMESIZE - 1, "/tmp/psa_service_%u", sid); - INFO("Attempting to contact RoT service at %s", pathname); - - /* if communication is possible */ - if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) { - - ret = send(handles[idx].client_qid, - handles[idx].server_qid, - &handles[idx].internal_server_qid, - PSA_IPC_CONNECT, - minor_version, - NULL); - - /* if connection accepted by RoT service */ - if (ret >= 0) { - handles[idx].valid = 1; - return idx; - } else { - INFO("Server didn't like you"); - } - } else { - INFO("Couldn't contact RoT service. Does it exist?"); - - if (__psa_ff_client_security_state == 0) { - PROGRAMMER_ERROR("Invalid SID"); - } - } - } - - INFO("Couldn't obtain a free handle"); - return PSA_ERROR_CONNECTION_REFUSED; -} - -uint32_t psa_version(uint32_t sid) -{ - int idx; - psa_status_t ret; - char pathname[PATHNAMESIZE] = { 0 }; - - idx = get_next_free_handle(); - - if (idx >= 0) { - snprintf(pathname, PATHNAMESIZE, "/tmp/psa_service_%u", sid); - if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) { - ret = send(handles[idx].client_qid, - handles[idx].server_qid, - &handles[idx].internal_server_qid, - VERSION_REQUEST, - 0, - NULL); - INFO("psa_version: Recieved from server %d\n", ret); - if (ret > 0) { - return ret; - } - } - } - INFO("psa_version failed: does the service exist?"); - return PSA_VERSION_NONE; -} - -psa_status_t psa_call(psa_handle_t handle, - int32_t type, - const psa_invec *in_vec, - size_t in_len, - psa_outvec *out_vec, - size_t out_len) -{ - - handle_is_valid(handle); - - if ((in_len + out_len) > PSA_MAX_IOVEC) { - PROGRAMMER_ERROR("Too many iovecs: %lu + %lu", in_len, out_len); - } - - vectors_t vecs = { 0 }; - vecs.in_vec = in_vec; - vecs.in_len = in_len; - vecs.out_vec = out_vec; - vecs.out_len = out_len; - - return send(handles[handle].client_qid, - handles[handle].server_qid, - &handles[handle].internal_server_qid, - type, - 0, - &vecs); -} - -void psa_close(psa_handle_t handle) -{ - handle_is_valid(handle); - if (send(handles[handle].client_qid, handles[handle].server_qid, - &handles[handle].internal_server_qid, PSA_IPC_DISCONNECT, 0, NULL)) { - puts("ERROR: Couldn't send disconnect msg"); - } else { - if (msgctl(handles[handle].client_qid, IPC_RMID, NULL) != 0) { - puts("ERROR: Failed to delete msg queue"); - } - } - INFO("Closing handle %u", handle); - handles[handle].valid = 0; -} diff --git a/psasim/src/common.c b/psasim/src/common.c deleted file mode 100644 index 26f3719089..0000000000 --- a/psasim/src/common.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Common code between clients and services */ - -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -#include "common.h" -int __psa_ff_client_security_state = NON_SECURE; - -#if 0 -static void _printbits(uint32_t num) -{ - for (int i = 0; i < 32; i++) { - if ((num >> (31-i) & 0x1)) { - INFO("1"); - } else { - INFO("0"); - } - } - INFO("\n"); -} -#endif diff --git a/psasim/src/common.h b/psasim/src/common.h deleted file mode 100644 index 96760d909f..0000000000 --- a/psasim/src/common.h +++ /dev/null @@ -1,85 +0,0 @@ -/* Common definitions used for clients and services */ - -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -#include - -#ifdef DEBUG -#define DEBUG_TEST 1 -#else -#define DEBUG_TEST 0 -#endif - -#define PRINT(...) \ - do { if (DEBUG_TEST) fprintf(stderr, __VA_ARGS__); } while (0) -#define INFO(...) \ - do { if (DEBUG_TEST) { PRINT("%s", __FILE__); PRINT(" INFO: " __VA_ARGS__); printf("\n"); \ - } } while (0) - -#define PROGRAMMER_ERROR(...) \ - do { if (DEBUG_TEST) { PRINT("%s:%d:%s(): PROGRAMMER ERROR", __FILE__, __LINE__, __func__); \ - PRINT(__VA_ARGS__); } abort(); } while (0) - -#define FATAL(...) \ - do { if (DEBUG_TEST) { PRINT("%s:%d:%s(): INTERNAL ERROR", __FILE__, __LINE__, __func__); PRINT( \ - __VA_ARGS__); } abort(); } while (0) - - -#define PROJECT_ID 'M' -#define PATHNAMESIZE 64 - -/* Increasing this might break on some platforms */ -#define MAX_FRAGMENT_SIZE 200 - -#define CONNECT_REQUEST 1 -#define CALL_REQUEST 2 -#define CLOSE_REQUEST 3 -#define VERSION_REQUEST 4 -#define READ_REQUEST 5 -#define READ_RESPONSE 6 -#define WRITE_REQUEST 7 -#define WRITE_RESPONSE 8 -#define SKIP_REQUEST 9 -#define PSA_REPLY 10 - -#define NON_SECURE (1 << 30) - -/* Note that this implementation is functional and not secure */ -extern int __psa_ff_client_security_state; - -struct message_text { - int qid; - int32_t psa_type; - char buf[MAX_FRAGMENT_SIZE]; -}; - - -struct message { - long message_type; - struct message_text message_text; -}; - -struct request_msg_internal { - psa_invec invec; - size_t skip_num; -}; - -struct skip_request_msg { - long message_type; - struct request_msg_internal message_text; -}; - -typedef struct vectors { - const psa_invec *in_vec; - size_t in_len; - psa_outvec *out_vec; - size_t out_len; -} vectors_t; - -typedef struct vector_sizes { - size_t invec_sizes[PSA_MAX_IOVEC]; - size_t outvec_sizes[PSA_MAX_IOVEC]; -} vector_sizes_t; diff --git a/psasim/test/manifest.json b/psasim/src/manifest.json similarity index 83% rename from psasim/test/manifest.json rename to psasim/src/manifest.json index 0ab83ef907..e67b636c17 100644 --- a/psasim/test/manifest.json +++ b/psasim/src/manifest.json @@ -3,14 +3,14 @@ "name":"TEST_PARTITION", "type":"PSA-ROT", "priority":"LOW", - "entry_point":"psa_sha256_main", + "entry_point":"psa_server_main", "stack_size":"0x400", "heap_size":"0x100", "services":[ { - "name":"PSA_SID_SHA256", + "name":"PSA_SID_CRYPTO", "sid":"0x0000F000", - "signal":"PSA_SHA256", + "signal":"PSA_CRYPTO", "non_secure_clients": "true", "minor_version":1, "minor_policy":"STRICT" diff --git a/psasim/src/psa_ff_client.c b/psasim/src/psa_ff_client.c new file mode 100644 index 0000000000..0d6bbf3c92 --- /dev/null +++ b/psasim/src/psa_ff_client.c @@ -0,0 +1,385 @@ +/* PSA firmware framework client API */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "client.h" +#include "common.h" +#include "error_ext.h" +#include "util.h" + +typedef struct internal_handle { + int server_qid; + int client_qid; + int internal_server_qid; + int valid; +} internal_handle_t; + +typedef struct vectors { + const psa_invec *in_vec; + size_t in_len; + psa_outvec *out_vec; + size_t out_len; +} vectors_t; + +/* Note that this implementation is functional and not secure */ +int __psa_ff_client_security_state = NON_SECURE; + +/* Access to this global is not thread safe */ +#define MAX_HANDLES 32 +static internal_handle_t handles[MAX_HANDLES] = { { 0 } }; + +static int get_next_free_handle() +{ + /* Never return handle 0 as it's a special null handle */ + for (int i = 1; i < MAX_HANDLES; i++) { + if (handles[i].valid == 0) { + return i; + } + } + return -1; +} + +static int handle_is_valid(psa_handle_t handle) +{ + if (handle > 0 && handle < MAX_HANDLES) { + if (handles[handle].valid == 1) { + return 1; + } + } + ERROR("ERROR: Invalid handle"); + return 0; +} + +static int get_queue_info(char *path, int *cqid, int *sqid) +{ + key_t server_queue_key; + int rx_qid, server_qid; + + INFO("Attempting to contact a RoT service queue"); + + if ((rx_qid = msgget(IPC_PRIVATE, 0660)) == -1) { + ERROR("msgget: rx_qid"); + return -1; + } + + if ((server_queue_key = ftok(path, PROJECT_ID)) == -1) { + ERROR("ftok"); + return -2; + } + + if ((server_qid = msgget(server_queue_key, 0)) == -1) { + ERROR("msgget: server_qid"); + return -3; + } + + *cqid = rx_qid; + *sqid = server_qid; + + return 0; +} + +static psa_status_t process_response(int rx_qid, vectors_t *vecs, int type, + int *internal_server_qid) +{ + struct message response, request; + psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED; + size_t invec_seek[4] = { 0 }; + size_t data_size; + psa_status_t invec, outvec; /* TODO: Should these be size_t ? */ + + assert(internal_server_qid > 0); + + while (1) { + data_size = 0; + invec = 0; + outvec = 0; + + /* read response from server */ + if (msgrcv(rx_qid, &response, sizeof(struct message_text), 0, 0) == -1) { + ERROR(" msgrcv failed"); + return ret; + } + + /* process return message from server */ + switch (response.message_type) { + case PSA_REPLY: + memcpy(&ret, response.message_text.buf, sizeof(psa_status_t)); + INFO(" Message received from server: %d", ret); + if (type == PSA_IPC_CONNECT && ret > 0) { + *internal_server_qid = ret; + INFO(" ASSSIGNED q ID %d", *internal_server_qid); + ret = PSA_SUCCESS; + } + return ret; + break; + case READ_REQUEST: + /* read data request */ + request.message_type = READ_RESPONSE; + + assert(vecs != 0); + + memcpy(&invec, response.message_text.buf, sizeof(psa_status_t)); + memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t)); + INFO(" Partition asked for %lu bytes from invec %d", data_size, invec); + + /* need to add more checks here */ + assert(invec >= 0 && invec < PSA_MAX_IOVEC); + + if (data_size > MAX_FRAGMENT_SIZE) { + data_size = MAX_FRAGMENT_SIZE; + } + + /* send response */ + INFO(" invec_seek[invec] is %lu", invec_seek[invec]); + INFO(" Reading from offset %p", vecs->in_vec[invec].base + invec_seek[invec]); + memcpy(request.message_text.buf, + (vecs->in_vec[invec].base + invec_seek[invec]), + data_size); + + /* update invec base TODO: check me */ + invec_seek[invec] = invec_seek[invec] + data_size; + + INFO(" Sending message of type %li", request.message_type); + INFO(" with content %s", request.message_text.buf); + + if (msgsnd(*internal_server_qid, &request, + sizeof(int) + sizeof(uint32_t) + data_size, 0) == -1) { + ERROR("Internal error: failed to respond to read request"); + } + break; + case WRITE_REQUEST: + assert(vecs != 0); + + request.message_type = WRITE_RESPONSE; + + memcpy(&outvec, response.message_text.buf, sizeof(psa_status_t)); + memcpy(&data_size, response.message_text.buf + sizeof(size_t), sizeof(size_t)); + INFO(" Partition wants to write %lu bytes to outvec %d", data_size, outvec); + + assert(outvec >= 0 && outvec < PSA_MAX_IOVEC); + + /* copy memory into message and send back amount written */ + size_t sofar = vecs->out_vec[outvec].len; + memcpy(vecs->out_vec[outvec].base + sofar, + response.message_text.buf+(sizeof(size_t)*2), data_size); + INFO(" Data size is %lu", data_size); + vecs->out_vec[outvec].len += data_size; + + INFO(" Sending message of type %li", request.message_type); + + /* send response */ + if (msgsnd(*internal_server_qid, &request, sizeof(int) + data_size, 0) == -1) { + ERROR("Internal error: failed to respond to write request"); + } + break; + case SKIP_REQUEST: + memcpy(&invec, response.message_text.buf, sizeof(psa_status_t)); + memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t)); + INFO(" Partition asked to skip %lu bytes in invec %d", data_size, invec); + assert(invec >= 0 && invec < PSA_MAX_IOVEC); + /* update invec base TODO: check me */ + invec_seek[invec] = invec_seek[invec] + data_size; + break; + + default: + FATAL(" ERROR: unknown internal message type: %ld", + response.message_type); + } + } +} + +static psa_status_t send(int rx_qid, int server_qid, int *internal_server_qid, + int32_t type, uint32_t minor_version, vectors_t *vecs) +{ + psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED; + size_t request_msg_size = (sizeof(int) + sizeof(long)); /* msg type plus queue id */ + struct message request; + request.message_type = 1; /* TODO: change this */ + request.message_text.psa_type = type; + vector_sizes_t vec_sizes; + + /* If the client is non-secure then set the NS bit */ + if (__psa_ff_client_security_state != 0) { + request.message_type |= NON_SECURE; + } + + assert(request.message_type >= 0); + + INFO("SEND: Sending message of type %ld with psa_type %d", request.message_type, type); + INFO(" internal_server_qid = %i", *internal_server_qid); + + request.message_text.qid = rx_qid; + + if (type == PSA_IPC_CONNECT) { + memcpy(request.message_text.buf, &minor_version, sizeof(minor_version)); + request_msg_size = request_msg_size + sizeof(minor_version); + INFO(" Request msg size is %lu", request_msg_size); + } else { + assert(internal_server_qid > 0); + } + + if (vecs != NULL && type >= PSA_IPC_CALL) { + + memset(&vec_sizes, 0, sizeof(vec_sizes)); + + /* Copy invec sizes */ + for (size_t i = 0; i < (vecs->in_len); i++) { + vec_sizes.invec_sizes[i] = vecs->in_vec[i].len; + INFO(" Client sending vector %lu: %lu", i, vec_sizes.invec_sizes[i]); + } + + /* Copy outvec sizes */ + for (size_t i = 0; i < (vecs->out_len); i++) { + vec_sizes.outvec_sizes[i] = vecs->out_vec[i].len; + + /* Reset to 0 since we need to eventually fill in with bytes written */ + vecs->out_vec[i].len = 0; + } + + memcpy(request.message_text.buf, &vec_sizes, sizeof(vec_sizes)); + request_msg_size = request_msg_size + sizeof(vec_sizes); + } + + INFO(" Sending and then waiting"); + + /* send message to server */ + if (msgsnd(server_qid, &request, request_msg_size, 0) == -1) { + ERROR(" msgsnd failed"); + return ret; + } + + return process_response(rx_qid, vecs, type, internal_server_qid); +} + + +uint32_t psa_framework_version(void) +{ + return PSA_FRAMEWORK_VERSION; +} + +psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version) +{ + int idx; + psa_status_t ret; + char pathname[PATHNAMESIZE] = { 0 }; + + idx = get_next_free_handle(); + + /* if there's a free handle available */ + if (idx >= 0) { + snprintf(pathname, PATHNAMESIZE - 1, TMP_FILE_BASE_PATH "psa_service_%u", sid); + INFO("Attempting to contact RoT service at %s", pathname); + + /* if communication is possible */ + if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) { + + ret = send(handles[idx].client_qid, + handles[idx].server_qid, + &handles[idx].internal_server_qid, + PSA_IPC_CONNECT, + minor_version, + NULL); + + /* if connection accepted by RoT service */ + if (ret >= 0) { + handles[idx].valid = 1; + return idx; + } else { + ERROR("Server didn't like you"); + } + } else { + ERROR("Couldn't contact RoT service. Does it exist?"); + + if (__psa_ff_client_security_state == 0) { + ERROR("Invalid SID"); + } + } + } + + INFO("Couldn't obtain a free handle"); + return PSA_ERROR_CONNECTION_REFUSED; +} + +uint32_t psa_version(uint32_t sid) +{ + int idx; + psa_status_t ret; + char pathname[PATHNAMESIZE] = { 0 }; + + idx = get_next_free_handle(); + + if (idx >= 0) { + snprintf(pathname, PATHNAMESIZE, TMP_FILE_BASE_PATH "psa_service_%u", sid); + if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) { + ret = send(handles[idx].client_qid, + handles[idx].server_qid, + &handles[idx].internal_server_qid, + VERSION_REQUEST, + 0, + NULL); + INFO("psa_version: Recieved from server %d", ret); + if (ret > 0) { + return ret; + } + } + } + ERROR("psa_version failed: does the service exist?"); + return PSA_VERSION_NONE; +} + +psa_status_t psa_call(psa_handle_t handle, + int32_t type, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len) +{ + handle_is_valid(handle); + + if ((in_len + out_len) > PSA_MAX_IOVEC) { + ERROR("Too many iovecs: %lu + %lu", in_len, out_len); + } + + vectors_t vecs = { 0 }; + vecs.in_vec = in_vec; + vecs.in_len = in_len; + vecs.out_vec = out_vec; + vecs.out_len = out_len; + + return send(handles[handle].client_qid, + handles[handle].server_qid, + &handles[handle].internal_server_qid, + type, + 0, + &vecs); +} + +void psa_close(psa_handle_t handle) +{ + handle_is_valid(handle); + if (send(handles[handle].client_qid, handles[handle].server_qid, + &handles[handle].internal_server_qid, PSA_IPC_DISCONNECT, 0, NULL)) { + ERROR("ERROR: Couldn't send disconnect msg"); + } else { + if (msgctl(handles[handle].client_qid, IPC_RMID, NULL) != 0) { + ERROR("ERROR: Failed to delete msg queue"); + } + } + INFO("Closing handle %u", handle); + handles[handle].valid = 0; +} diff --git a/psasim/src/service.c b/psasim/src/psa_ff_server.c similarity index 89% rename from psasim/src/service.c rename to psasim/src/psa_ff_server.c index 9bfe20f78a..00c5272646 100644 --- a/psasim/src/service.c +++ b/psasim/src/psa_ff_server.c @@ -5,10 +5,10 @@ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ -#include #include #include #include +#include #include #include #include @@ -16,8 +16,12 @@ #include #include #include -#include + +#include "service.h" +#include "init.h" +#include "error_ext.h" #include "common.h" +#include "util.h" #define MAX_CLIENTS 128 #define MAX_MESSAGES 32 @@ -25,9 +29,12 @@ struct connection { uint32_t client; void *rhandle; - int client_to_server_q; // this should be called client to server + int client_to_server_q; }; +/* Note that this implementation is functional and not secure. */ +int __psa_ff_client_security_state = NON_SECURE; + static psa_msg_t messages[MAX_MESSAGES]; /* Message slots */ static uint8_t pending_message[MAX_MESSAGES] = { 0 }; /* Booleans indicating active message slots */ static uint32_t message_client[MAX_MESSAGES] = { 0 }; /* Each client's response queue */ @@ -69,7 +76,7 @@ void destroy_connection(uint32_t client) connections[idx].rhandle = 0; INFO("Destroying connection"); } else { - INFO("Couldn't destroy connection for %u", client); + ERROR("Couldn't destroy connection for %u", client); } } @@ -88,7 +95,6 @@ static void reply(psa_handle_t msg_handle, psa_status_t status) psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) { - psa_signal_t mask; struct message msg; vector_sizes_t sizes; @@ -112,7 +118,6 @@ psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) } else if (i == 3) { // this must be psa doorbell } else { - /* Check if this signal corresponds to a queue */ if (rot_svc_incoming_queue[i] >= 0 && (pending_message[i] == 0)) { @@ -124,8 +129,8 @@ psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) IPC_NOWAIT); if (len > 0) { - INFO("Storing that QID in message_client[%d]\n", i); - INFO("The message handle will be %d\n", i); + INFO("Storing that QID in message_client[%d]", i); + INFO("The message handle will be %d", i); msgctl(rot_svc_incoming_queue[i], IPC_STAT, &qinfo); messages[i].client_id = qinfo.msg_lspid; /* PID of last msgsnd(2) call */ @@ -149,9 +154,9 @@ psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) messages[i].client_id = messages[i].client_id * -1; } - INFO("Got a message from client ID %d\n", messages[i].client_id); - INFO("Message type is %lu\n", msg.message_type); - INFO("PSA message type is %d\n", msg.message_text.psa_type); + INFO("Got a message from client ID %d", messages[i].client_id); + INFO("Message type is %lu", msg.message_type); + INFO("PSA message type is %d", msg.message_text.psa_type); messages[i].handle = i; @@ -161,8 +166,8 @@ psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) if (len >= 16) { memcpy(&requested_version, msg.message_text.buf, sizeof(requested_version)); - INFO("Requesting version %u\n", requested_version); - INFO("Implemented version %u\n", rot_svc_versions[i]); + INFO("Requesting version %u", requested_version); + INFO("Implemented version %u", rot_svc_versions[i]); /* TODO: need to check whether the policy is strict, * and if so, then reject the client if the number doesn't match */ @@ -195,7 +200,7 @@ psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) } else { /* We've run out of system wide connections */ reply(i, PSA_ERROR_CONNECTION_BUSY); - INFO("Ran out of free connections"); + ERROR("Ran out of free connections"); continue; } @@ -221,7 +226,7 @@ psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) memcpy(&messages[i].out_size, &sizes.outvec_sizes, (sizeof(size_t) * PSA_MAX_IOVEC)); } else { - FATAL("UNKNOWN MESSAGE TYPE RECEIVED %li\n", + FATAL("UNKNOWN MESSAGE TYPE RECEIVED %li", msg.message_type); } break; @@ -251,19 +256,15 @@ psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) break; } else { /* There is no 'select' function in SysV to block on multiple queues, so busy-wait :( */ - usleep(50000); } } while (timeout == PSA_BLOCK); - INFO("\n"); - /* Assert signals */ return signal_mask & exposed_signals; } static int signal_to_index(psa_signal_t signal) { - int i; int count = 0; int ret = -1; @@ -277,7 +278,7 @@ static int signal_to_index(psa_signal_t signal) } if (count > 1) { - INFO("ERROR: Too many signals"); + ERROR("ERROR: Too many signals"); return -1; /* Too many signals */ } return ret; @@ -297,7 +298,7 @@ psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg) { int index = signal_to_index(signal); if (index < 0) { - PROGRAMMER_ERROR("Bad signal\n"); + ERROR("Bad signal"); } clear_signal(signal); @@ -316,12 +317,13 @@ psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg) return PSA_ERROR_DOES_NOT_EXIST; } -static int is_valid_msg_handle(psa_handle_t h) +static inline int is_valid_msg_handle(psa_handle_t h) { if (h > 0 && h < MAX_MESSAGES) { return 1; } - PROGRAMMER_ERROR("Not a valid message handle"); + ERROR("Not a valid message handle"); + return 0; } static inline int is_call_msg(psa_handle_t h) @@ -347,7 +349,6 @@ static void send_msg(psa_handle_t msg_handle, const void *data, size_t data_amount) { - struct message response; int flags = 0; @@ -367,7 +368,7 @@ static void send_msg(psa_handle_t msg_handle, /* TODO: sizeof doesn't need to be so big here for small responses */ if (msgsnd(message_client[msg_handle], &response, sizeof(response.message_text), flags) == -1) { - INFO("Failed to reply"); + ERROR("Failed to reply"); } } @@ -400,7 +401,7 @@ size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, is_call_msg(msg_handle); if (invec_idx >= PSA_MAX_IOVEC) { - PROGRAMMER_ERROR("Invalid iovec number"); + ERROR("Invalid iovec number"); } /* If user wants more data than what's available, truncate their request */ @@ -409,14 +410,14 @@ size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, } while (sofar < num_bytes) { - INFO("Server: requesting %lu bytes from client\n", (num_bytes - sofar)); + INFO("Server: requesting %lu bytes from client", (num_bytes - sofar)); send_msg(msg_handle, READ_REQUEST, invec_idx, (num_bytes - sofar), NULL, 0); idx = find_connection(message_client[msg_handle]); assert(idx >= 0); len = msgrcv(connections[idx].client_to_server_q, &msg, sizeof(struct message_text), 0, 0); - len = (len - sizeof(msg.message_text.qid)); + len = (len - offsetof(struct message_text, buf)); if (len < 0) { FATAL("Internal error: failed to dispatch read request to the client"); @@ -430,7 +431,7 @@ size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, memcpy(buffer + sofar, msg.message_text.buf, len); } - INFO("Printing what i got so far: %s\n", msg.message_text.buf); + INFO("Printing what i got so far: %s", msg.message_text.buf); sofar = sofar + len; } @@ -444,7 +445,6 @@ size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, const void *buffer, size_t num_bytes) { - size_t sofar = 0; struct message msg = { 0 }; int idx; @@ -454,23 +454,23 @@ void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, is_call_msg(msg_handle); if (outvec_idx >= PSA_MAX_IOVEC) { - PROGRAMMER_ERROR("Invalid iovec number"); + ERROR("Invalid iovec number"); } if (num_bytes > messages[msg_handle].out_size[outvec_idx]) { - PROGRAMMER_ERROR("Program tried to write too much data %lu/%lu", num_bytes, - messages[msg_handle].out_size[outvec_idx]); + ERROR("Program tried to write too much data %lu/%lu", num_bytes, + messages[msg_handle].out_size[outvec_idx]); } while (sofar < num_bytes) { size_t sending = (num_bytes - sofar); - if (sending >= MAX_FRAGMENT_SIZE) { + if (sending > (MAX_FRAGMENT_SIZE - (sizeof(size_t) * 2))) { sending = MAX_FRAGMENT_SIZE - (sizeof(size_t) * 2); } - INFO("Server: sending %lu bytes to client\n", sending); + INFO("Server: sending %lu bytes to client, sofar = %lu", sending, (long) sofar); - send_msg(msg_handle, WRITE_REQUEST, outvec_idx, sending, buffer, sending); + send_msg(msg_handle, WRITE_REQUEST, outvec_idx, sending, buffer + sofar, sending); idx = find_connection(message_client[msg_handle]); assert(idx >= 0); @@ -479,7 +479,7 @@ void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, if (len < 1) { FATAL("Client didn't give me a full response"); } - sofar = sofar + len; + sofar = sofar + sending; } /* Update the seek count */ @@ -488,7 +488,6 @@ void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes) { - is_valid_msg_handle(msg_handle); is_call_msg(msg_handle); @@ -501,7 +500,6 @@ size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes) static void destroy_temporary_queue(int myqid) { - if (msgctl(myqid, IPC_RMID, NULL) != 0) { INFO("ERROR: Failed to delete msg queue %d", myqid); } @@ -526,7 +524,7 @@ void psa_reply(psa_handle_t msg_handle, psa_status_t status) is_valid_msg_handle(msg_handle); if (pending_message[msg_handle] != 1) { - PROGRAMMER_ERROR("Not a valid message handle"); + ERROR("Not a valid message handle"); } if (messages[msg_handle].type == PSA_IPC_CONNECT) { @@ -551,7 +549,7 @@ void psa_reply(psa_handle_t msg_handle, psa_status_t status) destroy_connection(message_client[msg_handle]); break; default: - PROGRAMMER_ERROR("Not a valid reply %d\n", status); + ERROR("Not a valid reply %d", status); } } else if (messages[msg_handle].type == PSA_IPC_DISCONNECT) { idx = find_connection(message_client[msg_handle]); @@ -574,7 +572,7 @@ void psa_eoi(psa_signal_t signal) if (index >= 0 && (rot_svc_incoming_queue[index] >= 0)) { clear_signal(signal); } else { - PROGRAMMER_ERROR("Tried to EOI a signal that isn't an interrupt"); + ERROR("Tried to EOI a signal that isn't an interrupt"); } } @@ -583,7 +581,7 @@ void psa_notify(int32_t partition_id) char pathname[PATHNAMESIZE] = { 0 }; if (partition_id < 0) { - PROGRAMMER_ERROR("Not a valid secure partition"); + ERROR("Not a valid secure partition"); } snprintf(pathname, PATHNAMESIZE, "/tmp/psa_notify_%u", partition_id); @@ -603,13 +601,13 @@ void __init_psasim(const char **array, const uint32_t versions[32], const int strict_policy_array[32]) { - static uint8_t library_initialised = 0; key_t key; int qid; FILE *fp; - char doorbell_path[PATHNAMESIZE] = { 0 }; - snprintf(doorbell_path, PATHNAMESIZE, "/tmp/psa_notify_%u", getpid()); + char doorbell_file[PATHNAMESIZE] = { 0 }; + char queue_path[PATHNAMESIZE]; + snprintf(doorbell_file, PATHNAMESIZE, "psa_notify_%u", getpid()); if (library_initialised > 0) { return; @@ -621,19 +619,21 @@ void __init_psasim(const char **array, FATAL("Unsupported value. Aborting."); } - array[3] = doorbell_path; + array[3] = doorbell_file; for (int i = 0; i < 32; i++) { if (strncmp(array[i], "", 1) != 0) { INFO("Setting up %s", array[i]); + memset(queue_path, 0, sizeof(queue_path)); + snprintf(queue_path, sizeof(queue_path), "%s%s", TMP_FILE_BASE_PATH, array[i]); /* Create file if doesn't exist */ - fp = fopen(array[i], "ab+"); + fp = fopen(queue_path, "ab+"); if (fp) { fclose(fp); } - if ((key = ftok(array[i], PROJECT_ID)) == -1) { + if ((key = ftok(queue_path, PROJECT_ID)) == -1) { FATAL("Error finding message queue during initialisation"); } @@ -649,7 +649,7 @@ void __init_psasim(const char **array, memcpy(nsacl, allow_ns_clients_array, sizeof(int) * 32); memcpy(strict_policy, strict_policy_array, sizeof(int) * 32); memcpy(rot_svc_versions, versions, sizeof(uint32_t) * 32); - bzero(&connections, sizeof(struct connection) * MAX_CLIENTS); + memset(&connections, 0, sizeof(struct connection) * MAX_CLIENTS); __psa_ff_client_security_state = 0; /* Set the client status to SECURE */ } diff --git a/psasim/src/psa_functions_codes.h b/psasim/src/psa_functions_codes.h new file mode 100644 index 0000000000..74746b653b --- /dev/null +++ b/psasim/src/psa_functions_codes.h @@ -0,0 +1,107 @@ +/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef _PSA_FUNCTIONS_CODES_H_ +#define _PSA_FUNCTIONS_CODES_H_ + +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_ASYMMETRIC_DECRYPT, + PSA_ASYMMETRIC_ENCRYPT, + PSA_CAN_DO_HASH, + PSA_CIPHER_ABORT, + PSA_CIPHER_DECRYPT, + PSA_CIPHER_DECRYPT_SETUP, + PSA_CIPHER_ENCRYPT, + PSA_CIPHER_ENCRYPT_SETUP, + PSA_CIPHER_FINISH, + PSA_CIPHER_GENERATE_IV, + PSA_CIPHER_SET_IV, + PSA_CIPHER_UPDATE, + PSA_COPY_KEY, + PSA_DESTROY_KEY, + PSA_EXPORT_KEY, + PSA_EXPORT_PUBLIC_KEY, + PSA_EXPORT_PUBLIC_KEY_IOP_ABORT, + PSA_EXPORT_PUBLIC_KEY_IOP_COMPLETE, + PSA_EXPORT_PUBLIC_KEY_IOP_GET_NUM_OPS, + PSA_EXPORT_PUBLIC_KEY_IOP_SETUP, + PSA_GENERATE_KEY, + PSA_GENERATE_KEY_CUSTOM, + PSA_GENERATE_KEY_IOP_ABORT, + PSA_GENERATE_KEY_IOP_COMPLETE, + PSA_GENERATE_KEY_IOP_GET_NUM_OPS, + PSA_GENERATE_KEY_IOP_SETUP, + PSA_GENERATE_RANDOM, + PSA_GET_KEY_ATTRIBUTES, + PSA_HASH_ABORT, + PSA_HASH_CLONE, + PSA_HASH_COMPARE, + PSA_HASH_COMPUTE, + PSA_HASH_FINISH, + PSA_HASH_SETUP, + PSA_HASH_UPDATE, + PSA_HASH_VERIFY, + PSA_IMPORT_KEY, + PSA_INTERRUPTIBLE_GET_MAX_OPS, + PSA_INTERRUPTIBLE_SET_MAX_OPS, + PSA_KEY_AGREEMENT, + PSA_KEY_AGREEMENT_IOP_ABORT, + PSA_KEY_AGREEMENT_IOP_COMPLETE, + PSA_KEY_AGREEMENT_IOP_GET_NUM_OPS, + PSA_KEY_AGREEMENT_IOP_SETUP, + PSA_KEY_DERIVATION_ABORT, + PSA_KEY_DERIVATION_GET_CAPACITY, + PSA_KEY_DERIVATION_INPUT_BYTES, + PSA_KEY_DERIVATION_INPUT_INTEGER, + PSA_KEY_DERIVATION_INPUT_KEY, + PSA_KEY_DERIVATION_KEY_AGREEMENT, + PSA_KEY_DERIVATION_OUTPUT_BYTES, + PSA_KEY_DERIVATION_OUTPUT_KEY, + PSA_KEY_DERIVATION_OUTPUT_KEY_CUSTOM, + PSA_KEY_DERIVATION_SET_CAPACITY, + PSA_KEY_DERIVATION_SETUP, + PSA_MAC_ABORT, + PSA_MAC_COMPUTE, + PSA_MAC_SIGN_FINISH, + PSA_MAC_SIGN_SETUP, + PSA_MAC_UPDATE, + PSA_MAC_VERIFY, + PSA_MAC_VERIFY_FINISH, + PSA_MAC_VERIFY_SETUP, + PSA_PURGE_KEY, + PSA_RAW_KEY_AGREEMENT, + PSA_RESET_KEY_ATTRIBUTES, + PSA_SIGN_HASH, + PSA_SIGN_HASH_ABORT, + PSA_SIGN_HASH_COMPLETE, + PSA_SIGN_HASH_GET_NUM_OPS, + PSA_SIGN_HASH_START, + PSA_SIGN_MESSAGE, + PSA_VERIFY_HASH, + PSA_VERIFY_HASH_ABORT, + PSA_VERIFY_HASH_COMPLETE, + PSA_VERIFY_HASH_GET_NUM_OPS, + PSA_VERIFY_HASH_START, + PSA_VERIFY_MESSAGE, +}; + +#endif /* _PSA_FUNCTIONS_CODES_H_ */ diff --git a/psasim/src/psa_sim_crypto_client.c b/psasim/src/psa_sim_crypto_client.c new file mode 100644 index 0000000000..9051f20535 --- /dev/null +++ b/psasim/src/psa_sim_crypto_client.c @@ -0,0 +1,7906 @@ +/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */ + +/* client calls */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include +#include + +/* Includes from psasim */ +#include +#include +#include "psa_manifest/sid.h" +#include "psa_functions_codes.h" +#include "psa_sim_serialise.h" + +/* Includes from mbedtls */ +#include "mbedtls/version.h" +#include "psa/crypto.h" + +#define CLIENT_PRINT(fmt, ...) \ + INFO("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 + +int psa_crypto_call(int function, + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + // psa_outvec outvecs[1]; + if (handle < 0) { + fprintf(stderr, "NOT CONNECTED\n"); + exit(1); + } + + psa_invec invec; + invec.base = in_params; + invec.len = in_params_len; + + size_t max_receive = 24576; + uint8_t *receive = malloc(max_receive); + if (receive == NULL) { + fprintf(stderr, "FAILED to allocate %u bytes\n", (unsigned) max_receive); + exit(1); + } + + size_t actual_received = 0; + + psa_outvec outvecs[2]; + outvecs[0].base = &actual_received; + outvecs[0].len = sizeof(actual_received); + outvecs[1].base = receive; + outvecs[1].len = max_receive; + + psa_status_t status = psa_call(handle, function, &invec, 1, outvecs, 2); + if (status != PSA_SUCCESS) { + free(receive); + return 0; + } + + *out_params = receive; + *out_params_len = actual_received; + + return 1; // success +} + +psa_status_t psa_crypto_init(void) +{ + const char *mbedtls_version; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + mbedtls_version = mbedtls_version_get_string_full(); + CLIENT_PRINT("%s", mbedtls_version); + + CLIENT_PRINT("My PID: %d", getpid()); + + CLIENT_PRINT("PSA version: %u", psa_version(PSA_SID_CRYPTO_SID)); + handle = psa_connect(PSA_SID_CRYPTO_SID, 1); + + if (handle < 0) { + CLIENT_PRINT("Couldn't connect %d", handle); + return PSA_ERROR_COMMUNICATION_FAILURE; + } + + int ok = psa_crypto_call(PSA_CRYPTO_INIT, NULL, 0, &result, &result_length); + CLIENT_PRINT("PSA_CRYPTO_INIT returned: %d", ok); + + if (!ok) { + 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(result); + + return status; +} + +void mbedtls_psa_crypto_free(void) +{ + /* Do not try to close a connection that was never started.*/ + if (handle == -1) { + return; + } + + CLIENT_PRINT("Closing handle"); + psa_close(handle); + handle = -1; +} + + +psa_status_t psa_aead_abort( + psa_aead_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_AEAD_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(nonce, nonce_length) + + psasim_serialise_buffer_needs(additional_data, additional_data_length) + + psasim_serialise_buffer_needs(ciphertext, ciphertext_length) + + psasim_serialise_buffer_needs(plaintext, plaintext_size) + + psasim_serialise_size_t_needs(*plaintext_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + 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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_DECRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + plaintext, plaintext_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + plaintext_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_DECRYPT_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(nonce, nonce_length) + + psasim_serialise_buffer_needs(additional_data, additional_data_length) + + psasim_serialise_buffer_needs(plaintext, plaintext_length) + + psasim_serialise_buffer_needs(ciphertext, ciphertext_size) + + psasim_serialise_size_t_needs(*ciphertext_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + 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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_ENCRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + ciphertext, ciphertext_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + ciphertext_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_ENCRYPT_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(ciphertext, ciphertext_size) + + psasim_serialise_size_t_needs(*ciphertext_length) + + psasim_serialise_buffer_needs(tag, tag_size) + + psasim_serialise_size_t_needs(*tag_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_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(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(nonce, nonce_size) + + psasim_serialise_size_t_needs(*nonce_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_GENERATE_NONCE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_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(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_size_t_needs(ad_length) + + psasim_serialise_size_t_needs(plaintext_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_SET_LENGTHS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(nonce, nonce_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_SET_NONCE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_UPDATE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_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(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_UPDATE_AD server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(plaintext, plaintext_size) + + psasim_serialise_size_t_needs(*plaintext_length) + + psasim_serialise_buffer_needs(tag, tag_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_AEAD_VERIFY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_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(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_asymmetric_decrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *salt, size_t salt_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(salt, salt_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + salt, salt_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_ASYMMETRIC_DECRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_ASYMMETRIC_DECRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_asymmetric_encrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *salt, size_t salt_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(salt, salt_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + salt, salt_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_ASYMMETRIC_ENCRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_ASYMMETRIC_ENCRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +int psa_can_do_hash( + psa_algorithm_t hash_alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + int value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_algorithm_t_needs(hash_alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + hash_alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CAN_DO_HASH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CAN_DO_HASH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_int( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +psa_status_t psa_cipher_abort( + psa_cipher_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_decrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_DECRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_DECRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_decrypt_setup( + psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_DECRYPT_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_DECRYPT_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_encrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_ENCRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_ENCRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_encrypt_setup( + psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_ENCRYPT_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_ENCRYPT_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_finish( + psa_cipher_operation_t *operation, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_FINISH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_generate_iv( + psa_cipher_operation_t *operation, + uint8_t *iv, size_t iv_size, + size_t *iv_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(iv, iv_size) + + psasim_serialise_size_t_needs(*iv_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + iv, iv_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *iv_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_GENERATE_IV, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_GENERATE_IV server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + iv, iv_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + iv_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_set_iv( + psa_cipher_operation_t *operation, + const uint8_t *iv, size_t iv_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(iv, iv_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + iv, iv_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_SET_IV, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_SET_IV server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_update( + psa_cipher_operation_t *operation, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_UPDATE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_UPDATE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_copy_key( + mbedtls_svc_key_id_t source_key, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *target_key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(source_key) + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*target_key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + source_key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *target_key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_COPY_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_COPY_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + target_key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_destroy_key( + mbedtls_svc_key_id_t key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_DESTROY_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_DESTROY_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_export_key( + mbedtls_svc_key_id_t key, + uint8_t *data, size_t data_size, + size_t *data_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_buffer_needs(data, data_size) + + psasim_serialise_size_t_needs(*data_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + data, data_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *data_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_EXPORT_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_EXPORT_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + data, data_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + data_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_export_public_key( + mbedtls_svc_key_id_t key, + uint8_t *data, size_t data_size, + size_t *data_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_buffer_needs(data, data_size) + + psasim_serialise_size_t_needs(*data_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + data, data_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *data_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_EXPORT_PUBLIC_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_EXPORT_PUBLIC_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + data, data_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + data_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_export_public_key_iop_abort( + psa_export_public_key_iop_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_export_public_key_iop_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_export_public_key_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_EXPORT_PUBLIC_KEY_IOP_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_EXPORT_PUBLIC_KEY_IOP_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_export_public_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_export_public_key_iop_complete( + psa_export_public_key_iop_t *operation, + uint8_t *data, size_t data_size, + size_t *data_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_export_public_key_iop_t_needs(*operation) + + psasim_serialise_buffer_needs(data, data_size) + + psasim_serialise_size_t_needs(*data_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_export_public_key_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + data, data_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *data_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_EXPORT_PUBLIC_KEY_IOP_COMPLETE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_EXPORT_PUBLIC_KEY_IOP_COMPLETE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_export_public_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + data, data_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + data_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +uint32_t psa_export_public_key_iop_get_num_ops( + psa_export_public_key_iop_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + uint32_t value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_export_public_key_iop_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + value = 0; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_export_public_key_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_EXPORT_PUBLIC_KEY_IOP_GET_NUM_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_EXPORT_PUBLIC_KEY_IOP_GET_NUM_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_export_public_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +psa_status_t psa_export_public_key_iop_setup( + psa_export_public_key_iop_t *operation, + mbedtls_svc_key_id_t key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_export_public_key_iop_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_export_public_key_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_EXPORT_PUBLIC_KEY_IOP_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_EXPORT_PUBLIC_KEY_IOP_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_export_public_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_generate_key( + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_generate_key_custom( + const psa_key_attributes_t *attributes, + const psa_custom_key_parameters_t *custom, + const uint8_t *custom_data, size_t custom_data_length, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_psa_custom_key_parameters_t_needs(*custom) + + psasim_serialise_buffer_needs(custom_data, custom_data_length) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_custom_key_parameters_t( + &pos, &remaining, + *custom); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + custom_data, custom_data_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY_CUSTOM, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY_CUSTOM server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_generate_key_iop_abort( + psa_generate_key_iop_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_generate_key_iop_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_generate_key_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY_IOP_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY_IOP_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_generate_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_generate_key_iop_complete( + psa_generate_key_iop_t *operation, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_generate_key_iop_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_generate_key_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY_IOP_COMPLETE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY_IOP_COMPLETE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_generate_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +uint32_t psa_generate_key_iop_get_num_ops( + psa_generate_key_iop_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + uint32_t value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_generate_key_iop_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + value = 0; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_generate_key_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY_IOP_GET_NUM_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY_IOP_GET_NUM_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_generate_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +psa_status_t psa_generate_key_iop_setup( + psa_generate_key_iop_t *operation, + const psa_key_attributes_t *attributes + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_generate_key_iop_t_needs(*operation) + + psasim_serialise_psa_key_attributes_t_needs(*attributes); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_generate_key_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY_IOP_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY_IOP_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_generate_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_generate_random( + uint8_t *output, size_t output_size + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_buffer_needs(output, output_size); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_RANDOM, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_RANDOM server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_get_key_attributes( + mbedtls_svc_key_id_t key, + psa_key_attributes_t *attributes + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_key_attributes_t_needs(*attributes); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GET_KEY_ATTRIBUTES, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GET_KEY_ATTRIBUTES server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &rpos, &rremain, + attributes); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_hash_abort( + psa_hash_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_HASH_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_HASH_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_hash_clone( + const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*source_operation) + + psasim_serialise_psa_hash_operation_t_needs(*target_operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *source_operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *target_operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_HASH_CLONE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_HASH_CLONE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + target_operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_hash_compare( + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *hash, size_t hash_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(hash, hash_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_HASH_COMPARE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_HASH_COMPARE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_hash_compute( + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *hash, size_t hash_size, + size_t *hash_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(hash, hash_size) + + psasim_serialise_size_t_needs(*hash_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *hash_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_HASH_COMPUTE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_HASH_COMPUTE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + hash, hash_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + hash_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_hash_finish( + psa_hash_operation_t *operation, + uint8_t *hash, size_t hash_size, + size_t *hash_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(hash, hash_size) + + psasim_serialise_size_t_needs(*hash_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *hash_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_HASH_FINISH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_HASH_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + hash, hash_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + hash_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_hash_setup( + psa_hash_operation_t *operation, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_HASH_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_HASH_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_hash_update( + psa_hash_operation_t *operation, + const uint8_t *input, size_t input_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_hash_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_HASH_UPDATE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_HASH_UPDATE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_hash_verify( + psa_hash_operation_t *operation, + const uint8_t *hash, size_t hash_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(hash, hash_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_HASH_VERIFY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_HASH_VERIFY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + 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 *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_buffer_needs(data, data_length) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_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, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_IMPORT_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +uint32_t psa_interruptible_get_max_ops( + void + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + uint32_t value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + 0; + + ser_params = malloc(needed); + if (ser_params == NULL) { + value = 0; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_INTERRUPTIBLE_GET_MAX_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_INTERRUPTIBLE_GET_MAX_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +void psa_interruptible_set_max_ops( + uint32_t max_ops + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(max_ops); + + ser_params = malloc(needed); + if (ser_params == NULL) { + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_uint32_t( + &pos, &remaining, + max_ops); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_INTERRUPTIBLE_SET_MAX_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_INTERRUPTIBLE_SET_MAX_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); +} + + +psa_status_t psa_key_agreement( + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, size_t peer_key_length, + psa_algorithm_t alg, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(private_key) + + psasim_serialise_buffer_needs(peer_key, peer_key_length) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + private_key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + peer_key, peer_key_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_AGREEMENT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_AGREEMENT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_agreement_iop_abort( + psa_key_agreement_iop_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_agreement_iop_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_agreement_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_AGREEMENT_IOP_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_AGREEMENT_IOP_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_agreement_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_agreement_iop_complete( + psa_key_agreement_iop_t *operation, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_agreement_iop_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_agreement_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_AGREEMENT_IOP_COMPLETE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_AGREEMENT_IOP_COMPLETE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_agreement_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +uint32_t psa_key_agreement_iop_get_num_ops( + psa_key_agreement_iop_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + uint32_t value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_agreement_iop_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + value = 0; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_agreement_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_AGREEMENT_IOP_GET_NUM_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_AGREEMENT_IOP_GET_NUM_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_agreement_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +psa_status_t psa_key_agreement_iop_setup( + psa_key_agreement_iop_t *operation, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, size_t peer_key_length, + psa_algorithm_t alg, + const psa_key_attributes_t *attributes + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_agreement_iop_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(private_key) + + psasim_serialise_buffer_needs(peer_key, peer_key_length) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_psa_key_attributes_t_needs(*attributes); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_agreement_iop_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + private_key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + peer_key, peer_key_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_AGREEMENT_IOP_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_AGREEMENT_IOP_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_agreement_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_size_t_needs(*capacity); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *capacity); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_GET_CAPACITY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_GET_CAPACITY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + capacity); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, size_t data_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_key_derivation_step_t_needs(step) + + psasim_serialise_buffer_needs(data, data_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_step_t( + &pos, &remaining, + step); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + data, data_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_INPUT_BYTES, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_INPUT_BYTES server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_input_integer( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_key_derivation_step_t_needs(step) + + psasim_serialise_uint64_t_needs(value); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_step_t( + &pos, &remaining, + step); + if (!ok) { + goto fail; + } + ok = psasim_serialise_uint64_t( + &pos, &remaining, + value); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_INPUT_INTEGER, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_INPUT_INTEGER server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_key_derivation_step_t_needs(step) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_step_t( + &pos, &remaining, + step); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_INPUT_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_INPUT_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, size_t peer_key_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_key_derivation_step_t_needs(step) + + psasim_serialise_mbedtls_svc_key_id_t_needs(private_key) + + psasim_serialise_buffer_needs(peer_key, peer_key_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_step_t( + &pos, &remaining, + step); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + private_key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + peer_key, peer_key_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_KEY_AGREEMENT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_KEY_AGREEMENT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, size_t output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(output, output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_OUTPUT_BYTES, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_OUTPUT_BYTES server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_OUTPUT_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_OUTPUT_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_output_key_custom( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + const psa_custom_key_parameters_t *custom, + const uint8_t *custom_data, size_t custom_data_length, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_custom_key_parameters_t_needs(*custom) + + psasim_serialise_buffer_needs(custom_data, custom_data_length) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_custom_key_parameters_t( + &pos, &remaining, + *custom); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + custom_data, custom_data_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_OUTPUT_KEY_CUSTOM, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_OUTPUT_KEY_CUSTOM server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_size_t_needs(capacity); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + capacity); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_SET_CAPACITY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_SET_CAPACITY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_abort( + psa_mac_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_compute( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *mac, size_t mac_size, + size_t *mac_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(*mac_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + mac, mac_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_COMPUTE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_COMPUTE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + mac_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_sign_finish( + psa_mac_operation_t *operation, + uint8_t *mac, size_t mac_size, + size_t *mac_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(*mac_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + mac, mac_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_SIGN_FINISH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_SIGN_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + mac_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_sign_setup( + psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_SIGN_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_SIGN_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_update( + psa_mac_operation_t *operation, + const uint8_t *input, size_t input_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_UPDATE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_UPDATE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_verify( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *mac, size_t mac_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(mac, mac_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + mac, mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_VERIFY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_VERIFY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_verify_finish( + psa_mac_operation_t *operation, + const uint8_t *mac, size_t mac_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(mac, mac_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + mac, mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_VERIFY_FINISH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_VERIFY_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_verify_setup( + psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_VERIFY_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_VERIFY_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_purge_key( + mbedtls_svc_key_id_t key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_PURGE_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_PURGE_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_raw_key_agreement( + psa_algorithm_t alg, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, size_t peer_key_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_mbedtls_svc_key_id_t_needs(private_key) + + psasim_serialise_buffer_needs(peer_key, peer_key_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + private_key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + peer_key, peer_key_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_RAW_KEY_AGREEMENT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_RAW_KEY_AGREEMENT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +void psa_reset_key_attributes( + psa_key_attributes_t *attributes + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes); + + ser_params = malloc(needed); + if (ser_params == NULL) { + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_RESET_KEY_ATTRIBUTES, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_RESET_KEY_ATTRIBUTES server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &rpos, &rremain, + attributes); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); +} + + +psa_status_t psa_sign_hash( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, + size_t *signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(hash, hash_length) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(*signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_sign_hash_abort( + psa_sign_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_sign_hash_complete( + psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(*signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH_COMPLETE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH_COMPLETE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +uint32_t psa_sign_hash_get_num_ops( + const psa_sign_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + uint32_t value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + value = 0; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH_GET_NUM_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH_GET_NUM_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +psa_status_t psa_sign_hash_start( + psa_sign_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(hash, hash_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH_START, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH_START server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_sign_message( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *signature, size_t signature_size, + size_t *signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(*signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_MESSAGE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_MESSAGE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_verify_hash( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(hash, hash_length) + + psasim_serialise_buffer_needs(signature, signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_verify_hash_abort( + psa_verify_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_verify_hash_complete( + psa_verify_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH_COMPLETE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH_COMPLETE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +uint32_t psa_verify_hash_get_num_ops( + const psa_verify_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + uint32_t value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + value = 0; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH_GET_NUM_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH_GET_NUM_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +psa_status_t psa_verify_hash_start( + psa_verify_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(hash, hash_length) + + psasim_serialise_buffer_needs(signature, signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH_START, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH_START server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_verify_message( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *signature, size_t signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(signature, signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_MESSAGE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_MESSAGE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} diff --git a/psasim/src/psa_sim_crypto_server.c b/psasim/src/psa_sim_crypto_server.c new file mode 100644 index 0000000000..bd121c5433 --- /dev/null +++ b/psasim/src/psa_sim_crypto_server.c @@ -0,0 +1,9226 @@ +/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */ + +/* server implementations */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include +#include + +#include + +#include "psa_functions_codes.h" +#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 + +#if defined(MBEDTLS_TEST_HOOKS) +void (*mbedtls_test_hook_error_add)(int, int, const char *, int); +#endif + +// Returns 1 for success, 0 for failure +int psa_crypto_init_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + uint8_t *result = NULL; + int ok; + + // Now we call the actual target function + + status = psa_crypto_init( + ); + + // 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_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, 1); + 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, 0); + 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, 0); + 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, 1); + 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, 0); + 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, 0); + 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, 0); + 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, 0); + 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, 0); + 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, 0); + 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_asymmetric_decrypt_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *salt = NULL; + size_t salt_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &salt, &salt_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_asymmetric_decrypt( + key, + alg, + input, input_length, + salt, salt_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(salt); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(salt); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_asymmetric_encrypt_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *salt = NULL; + size_t salt_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &salt, &salt_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_asymmetric_encrypt( + key, + alg, + input, input_length, + salt, salt_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(salt); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(salt); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_can_do_hash_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + int value = 0; + psa_algorithm_t hash_alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &hash_alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + value = psa_can_do_hash( + hash_alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_int_needs(value); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_int( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_decrypt_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_decrypt( + key, + alg, + input, input_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_decrypt_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_decrypt_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_encrypt_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_encrypt( + key, + alg, + input, input_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_encrypt_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_encrypt_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_finish_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_finish( + operation, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(output); + + return 1; // success + +fail: + free(result); + + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_generate_iv_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + uint8_t *iv = NULL; + size_t iv_size; + size_t iv_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &iv, &iv_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &iv_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_generate_iv( + operation, + iv, iv_size, + &iv_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation) + + psasim_serialise_buffer_needs(iv, iv_size) + + psasim_serialise_size_t_needs(iv_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + iv, iv_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + iv_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(iv); + + return 1; // success + +fail: + free(result); + + free(iv); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_set_iv_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + uint8_t *iv = NULL; + size_t iv_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &iv, &iv_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_set_iv( + operation, + iv, iv_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(iv); + + return 1; // success + +fail: + free(result); + + free(iv); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_update_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + uint8_t *input = NULL; + size_t input_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_update( + operation, + input, input_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_copy_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t source_key; + psa_key_attributes_t attributes; + mbedtls_svc_key_id_t target_key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &source_key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &target_key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_copy_key( + source_key, + &attributes, + &target_key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_mbedtls_svc_key_id_t_needs(target_key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + target_key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_destroy_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + 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_export_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + uint8_t *data = NULL; + size_t data_size; + size_t data_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &data, &data_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &data_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_export_key( + key, + data, data_size, + &data_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(data, data_size) + + psasim_serialise_size_t_needs(data_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + data, data_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + data_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(data); + + return 1; // success + +fail: + free(result); + + free(data); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_export_public_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + uint8_t *data = NULL; + size_t data_size; + size_t data_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &data, &data_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &data_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_export_public_key( + key, + data, data_size, + &data_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(data, data_size) + + psasim_serialise_size_t_needs(data_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + data, data_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + data_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(data); + + return 1; // success + +fail: + free(result); + + free(data); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_export_public_key_iop_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_export_public_key_iop_t operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_export_public_key_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_export_public_key_iop_abort( + &operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_psa_export_public_key_iop_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_export_public_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_export_public_key_iop_complete_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_export_public_key_iop_t operation; + uint8_t *data = NULL; + size_t data_size; + size_t data_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_export_public_key_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &data, &data_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &data_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_export_public_key_iop_complete( + &operation, + data, data_size, + &data_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_psa_export_public_key_iop_t_needs(operation) + + psasim_serialise_buffer_needs(data, data_size) + + psasim_serialise_size_t_needs(data_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_export_public_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + data, data_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + data_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(data); + + return 1; // success + +fail: + free(result); + + free(data); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_export_public_key_iop_get_num_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t value = 0; + psa_export_public_key_iop_t operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_export_public_key_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + value = psa_export_public_key_iop_get_num_ops( + &operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(value) + + psasim_serialise_psa_export_public_key_iop_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_uint32_t( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_export_public_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_export_public_key_iop_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_export_public_key_iop_t operation; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_export_public_key_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_export_public_key_iop_setup( + &operation, + key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_psa_export_public_key_iop_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_export_public_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_key( + &attributes, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_key_custom_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + psa_custom_key_parameters_t custom; + uint8_t *custom_data = NULL; + size_t custom_data_length; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_custom_key_parameters_t( + &pos, &remaining, + &custom); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &custom_data, &custom_data_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_key_custom( + &attributes, + &custom, + custom_data, custom_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(custom_data); + + return 1; // success + +fail: + free(result); + + free(custom_data); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_key_iop_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_generate_key_iop_t operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_generate_key_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_key_iop_abort( + &operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_psa_generate_key_iop_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_generate_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_key_iop_complete_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_generate_key_iop_t operation; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_generate_key_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_key_iop_complete( + &operation, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_psa_generate_key_iop_t_needs(operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_generate_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_key_iop_get_num_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t value = 0; + psa_generate_key_iop_t operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_generate_key_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + value = psa_generate_key_iop_get_num_ops( + &operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(value) + + psasim_serialise_psa_generate_key_iop_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_uint32_t( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_generate_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_key_iop_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_generate_key_iop_t operation; + psa_key_attributes_t attributes; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_generate_key_iop_t( + &pos, &remaining, + &operation); + 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_generate_key_iop_setup( + &operation, + &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_generate_key_iop_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_generate_key_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_random_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t *output = NULL; + size_t output_size; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_random( + output, output_size + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(output); + + return 1; // success + +fail: + free(result); + + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_get_key_attributes_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + 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; + + 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_hash_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_hash_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_hash_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_hash_operation_t( + &rpos, &rremain, + operation, 1); + 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_clone_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 *source_operation; + psa_hash_operation_t *target_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_hash_operation_t( + &pos, &remaining, + &source_operation); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &target_operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_hash_clone( + 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_server_serialise_psa_hash_operation_t_needs(target_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_hash_operation_t( + &rpos, &rremain, + target_operation, 0); + 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_compare_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *hash = NULL; + size_t hash_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_hash_compare( + alg, + input, input_length, + hash, hash_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(hash); + + return 1; // success + +fail: + free(result); + + free(input); + free(hash); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_hash_compute_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *hash = NULL; + size_t hash_size; + size_t hash_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &hash_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_hash_compute( + alg, + input, input_length, + hash, hash_size, + &hash_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(hash, hash_size) + + psasim_serialise_size_t_needs(hash_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, + hash, hash_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + hash_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(hash); + + return 1; // success + +fail: + free(result); + + free(input); + free(hash); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_hash_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_hash_operation_t *operation; + uint8_t *hash = NULL; + size_t hash_size; + size_t hash_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &hash_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_hash_finish( + operation, + hash, hash_size, + &hash_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_hash_operation_t_needs(operation) + + psasim_serialise_buffer_needs(hash, hash_size) + + psasim_serialise_size_t_needs(hash_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_hash_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + hash, hash_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + hash_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + + return 1; // success + +fail: + free(result); + + free(hash); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_hash_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_hash_operation_t *operation; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_hash_setup( + operation, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_hash_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_hash_operation_t( + &rpos, &rremain, + operation, 0); + 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_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_hash_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_hash_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_hash_update( + operation, + input, input_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_hash_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_hash_operation_t( + &rpos, &rremain, + operation, 0); + 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_hash_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_hash_operation_t *operation; + uint8_t *hash = NULL; + size_t hash_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_hash_verify( + operation, + hash, hash_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_hash_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_hash_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + + return 1; // success + +fail: + free(result); + + free(hash); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_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! +} + +// Returns 1 for success, 0 for failure +int psa_interruptible_get_max_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t value = 0; + + uint8_t *result = NULL; + int ok; + + // Now we call the actual target function + + value = psa_interruptible_get_max_ops( + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(value); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_uint32_t( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_interruptible_set_max_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t max_ops; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &pos, &remaining, + &max_ops); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + psa_interruptible_set_max_ops( + max_ops + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs(); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_agreement_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t private_key; + uint8_t *peer_key = NULL; + size_t peer_key_length; + psa_algorithm_t alg; + psa_key_attributes_t attributes; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &private_key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &peer_key, &peer_key_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_agreement( + private_key, + peer_key, peer_key_length, + alg, + &attributes, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(peer_key); + + return 1; // success + +fail: + free(result); + + free(peer_key); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_agreement_iop_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_agreement_iop_t operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_agreement_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_agreement_iop_abort( + &operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_psa_key_agreement_iop_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_key_agreement_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_agreement_iop_complete_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_agreement_iop_t operation; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_agreement_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_agreement_iop_complete( + &operation, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_psa_key_agreement_iop_t_needs(operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_key_agreement_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_agreement_iop_get_num_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t value = 0; + psa_key_agreement_iop_t operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_agreement_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + value = psa_key_agreement_iop_get_num_ops( + &operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(value) + + psasim_serialise_psa_key_agreement_iop_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_uint32_t( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_key_agreement_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_agreement_iop_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_agreement_iop_t operation; + mbedtls_svc_key_id_t private_key; + uint8_t *peer_key = NULL; + size_t peer_key_length; + psa_algorithm_t alg; + psa_key_attributes_t attributes; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_agreement_iop_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &private_key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &peer_key, &peer_key_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + 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_key_agreement_iop_setup( + &operation, + private_key, + peer_key, peer_key_length, + alg, + &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_agreement_iop_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_key_agreement_iop_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(peer_key); + + return 1; // success + +fail: + free(result); + + free(peer_key); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_get_capacity_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + size_t capacity; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &capacity); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_get_capacity( + operation, + &capacity + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_size_t_needs(capacity); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + capacity); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_input_bytes_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_key_derivation_step_t step; + uint8_t *data = NULL; + size_t data_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_step_t( + &pos, &remaining, + &step); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &data, &data_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_input_bytes( + operation, + step, + data, data_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(data); + + return 1; // success + +fail: + free(result); + + free(data); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_input_integer_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_key_derivation_step_t step; + uint64_t value; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_step_t( + &pos, &remaining, + &step); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint64_t( + &pos, &remaining, + &value); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_input_integer( + operation, + step, + value + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_input_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_key_derivation_step_t step; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_step_t( + &pos, &remaining, + &step); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_input_key( + operation, + step, + key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_key_agreement_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_key_derivation_step_t step; + mbedtls_svc_key_id_t private_key; + uint8_t *peer_key = NULL; + size_t peer_key_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_step_t( + &pos, &remaining, + &step); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &private_key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &peer_key, &peer_key_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_key_agreement( + operation, + step, + private_key, + peer_key, peer_key_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(peer_key); + + return 1; // success + +fail: + free(result); + + free(peer_key); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_output_bytes_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + uint8_t *output = NULL; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_output_bytes( + operation, + output, output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation) + + psasim_serialise_buffer_needs(output, output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(output); + + return 1; // success + +fail: + free(result); + + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_output_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + psa_key_derivation_operation_t *operation; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_output_key( + &attributes, + operation, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_output_key_custom_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + psa_key_derivation_operation_t *operation; + psa_custom_key_parameters_t custom; + uint8_t *custom_data = NULL; + size_t custom_data_length; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_custom_key_parameters_t( + &pos, &remaining, + &custom); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &custom_data, &custom_data_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_output_key_custom( + &attributes, + operation, + &custom, + custom_data, custom_data_length, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 0); + 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(custom_data); + + return 1; // success + +fail: + free(result); + + free(custom_data); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_set_capacity_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + size_t capacity; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &capacity); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_set_capacity( + operation, + capacity + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_setup( + operation, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_compute_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *mac = NULL; + size_t mac_size; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &mac, &mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_compute( + key, + alg, + input, input_length, + mac, mac_size, + &mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(mac_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + mac_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(mac); + + return 1; // success + +fail: + free(result); + + free(input); + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_sign_finish_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + uint8_t *mac = NULL; + size_t mac_size; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &mac, &mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_sign_finish( + operation, + mac, mac_size, + &mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(mac_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + mac_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(mac); + + return 1; // success + +fail: + free(result); + + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_sign_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_sign_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_update_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + uint8_t *input = NULL; + size_t input_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_update( + operation, + input, input_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + + return 1; // success + +fail: + free(result); + + free(input); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_verify_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *mac = NULL; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &mac, &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_verify( + key, + alg, + input, input_length, + mac, mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(mac); + + return 1; // success + +fail: + free(result); + + free(input); + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_verify_finish_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + uint8_t *mac = NULL; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &mac, &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_verify_finish( + operation, + mac, mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(mac); + + return 1; // success + +fail: + free(result); + + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_verify_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_verify_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_purge_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_purge_key( + key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_raw_key_agreement_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t alg; + mbedtls_svc_key_id_t private_key; + uint8_t *peer_key = NULL; + size_t peer_key_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &private_key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &peer_key, &peer_key_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_raw_key_agreement( + alg, + private_key, + peer_key, peer_key_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(peer_key); + free(output); + + return 1; // success + +fail: + free(result); + + free(peer_key); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_reset_key_attributes_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_key_attributes_t attributes; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + psa_reset_key_attributes( + &attributes + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(attributes); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_key_attributes_t( + &rpos, &rremain, + attributes); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *hash = NULL; + size_t hash_length; + uint8_t *signature = NULL; + size_t signature_size; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_hash( + key, + alg, + hash, hash_length, + signature, signature_size, + &signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(signature_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + free(signature); + + return 1; // success + +fail: + free(result); + + free(hash); + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_sign_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_hash_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_complete_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_sign_hash_interruptible_operation_t *operation; + uint8_t *signature = NULL; + size_t signature_size; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_hash_complete( + operation, + signature, signature_size, + &signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(signature_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(signature); + + return 1; // success + +fail: + free(result); + + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_get_num_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t value = 0; + psa_sign_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + value = psa_sign_hash_get_num_ops( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(value); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_uint32_t( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_start_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_sign_hash_interruptible_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *hash = NULL; + size_t hash_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_hash_start( + operation, + key, + alg, + hash, hash_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + + return 1; // success + +fail: + free(result); + + free(hash); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_message_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *signature = NULL; + size_t signature_size; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_message( + key, + alg, + input, input_length, + signature, signature_size, + &signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(signature_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(signature); + + return 1; // success + +fail: + free(result); + + free(input); + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *hash = NULL; + size_t hash_length; + uint8_t *signature = NULL; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_hash( + key, + alg, + hash, hash_length, + signature, signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + free(signature); + + return 1; // success + +fail: + free(result); + + free(hash); + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_verify_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_hash_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation, 1); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_complete_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_verify_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_hash_complete( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_get_num_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t value = 0; + psa_verify_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + value = psa_verify_hash_get_num_ops( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(value); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_uint32_t( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_start_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_verify_hash_interruptible_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *hash = NULL; + size_t hash_length; + uint8_t *signature = NULL; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_hash_start( + operation, + key, + alg, + hash, hash_length, + signature, signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation, 0); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + free(signature); + + return 1; // success + +fail: + free(result); + + free(hash); + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_message_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *signature = NULL; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_message( + key, + alg, + input, input_length, + signature, signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(signature); + + return 1; // success + +fail: + free(result); + + free(input); + free(signature); + + return 0; // This shouldn't happen! +} + +psa_status_t psa_crypto_call(psa_msg_t msg) +{ + int ok = 0; + + int func = msg.type; + + /* We only expect a single input buffer, with everything serialised in it */ + if (msg.in_size[1] != 0 || msg.in_size[2] != 0 || msg.in_size[3] != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* We expect exactly 2 output buffers, one for size, the other for data */ + if (msg.out_size[0] != sizeof(size_t) || msg.out_size[1] == 0 || + msg.out_size[2] != 0 || msg.out_size[3] != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + uint8_t *in_params = NULL; + size_t in_params_len = 0; + uint8_t *out_params = NULL; + size_t out_params_len = 0; + + in_params_len = msg.in_size[0]; + in_params = malloc(in_params_len); + if (in_params == NULL) { + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + + /* Read the bytes from the client */ + size_t actual = psa_read(msg.handle, 0, in_params, in_params_len); + if (actual != in_params_len) { + free(in_params); + return PSA_ERROR_CORRUPTION_DETECTED; + } + + switch (func) { + case PSA_CRYPTO_INIT: + 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_ASYMMETRIC_DECRYPT: + ok = psa_asymmetric_decrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_ASYMMETRIC_ENCRYPT: + ok = psa_asymmetric_encrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CAN_DO_HASH: + ok = psa_can_do_hash_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_ABORT: + ok = psa_cipher_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_DECRYPT: + ok = psa_cipher_decrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_DECRYPT_SETUP: + ok = psa_cipher_decrypt_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_ENCRYPT: + ok = psa_cipher_encrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_ENCRYPT_SETUP: + ok = psa_cipher_encrypt_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_FINISH: + ok = psa_cipher_finish_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_GENERATE_IV: + ok = psa_cipher_generate_iv_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_SET_IV: + ok = psa_cipher_set_iv_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_UPDATE: + ok = psa_cipher_update_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_COPY_KEY: + ok = psa_copy_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_DESTROY_KEY: + ok = psa_destroy_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_EXPORT_KEY: + ok = psa_export_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_EXPORT_PUBLIC_KEY: + ok = psa_export_public_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_EXPORT_PUBLIC_KEY_IOP_ABORT: + ok = psa_export_public_key_iop_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_EXPORT_PUBLIC_KEY_IOP_COMPLETE: + ok = psa_export_public_key_iop_complete_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_EXPORT_PUBLIC_KEY_IOP_GET_NUM_OPS: + ok = psa_export_public_key_iop_get_num_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_EXPORT_PUBLIC_KEY_IOP_SETUP: + ok = psa_export_public_key_iop_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_KEY: + ok = psa_generate_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_KEY_CUSTOM: + ok = psa_generate_key_custom_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_KEY_IOP_ABORT: + ok = psa_generate_key_iop_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_KEY_IOP_COMPLETE: + ok = psa_generate_key_iop_complete_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_KEY_IOP_GET_NUM_OPS: + ok = psa_generate_key_iop_get_num_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_KEY_IOP_SETUP: + ok = psa_generate_key_iop_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_RANDOM: + ok = psa_generate_random_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GET_KEY_ATTRIBUTES: + ok = psa_get_key_attributes_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_HASH_ABORT: + ok = psa_hash_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_HASH_CLONE: + ok = psa_hash_clone_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_HASH_COMPARE: + ok = psa_hash_compare_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_HASH_COMPUTE: + ok = psa_hash_compute_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_HASH_FINISH: + ok = psa_hash_finish_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_HASH_SETUP: + ok = psa_hash_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_HASH_UPDATE: + ok = psa_hash_update_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_HASH_VERIFY: + 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; + case PSA_INTERRUPTIBLE_GET_MAX_OPS: + ok = psa_interruptible_get_max_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_INTERRUPTIBLE_SET_MAX_OPS: + ok = psa_interruptible_set_max_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_AGREEMENT: + ok = psa_key_agreement_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_AGREEMENT_IOP_ABORT: + ok = psa_key_agreement_iop_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_AGREEMENT_IOP_COMPLETE: + ok = psa_key_agreement_iop_complete_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_AGREEMENT_IOP_GET_NUM_OPS: + ok = psa_key_agreement_iop_get_num_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_AGREEMENT_IOP_SETUP: + ok = psa_key_agreement_iop_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_ABORT: + ok = psa_key_derivation_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_GET_CAPACITY: + ok = psa_key_derivation_get_capacity_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_INPUT_BYTES: + ok = psa_key_derivation_input_bytes_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_INPUT_INTEGER: + ok = psa_key_derivation_input_integer_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_INPUT_KEY: + ok = psa_key_derivation_input_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_KEY_AGREEMENT: + ok = psa_key_derivation_key_agreement_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_OUTPUT_BYTES: + ok = psa_key_derivation_output_bytes_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_OUTPUT_KEY: + ok = psa_key_derivation_output_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_OUTPUT_KEY_CUSTOM: + ok = psa_key_derivation_output_key_custom_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_SET_CAPACITY: + ok = psa_key_derivation_set_capacity_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_SETUP: + ok = psa_key_derivation_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_ABORT: + ok = psa_mac_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_COMPUTE: + ok = psa_mac_compute_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_SIGN_FINISH: + ok = psa_mac_sign_finish_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_SIGN_SETUP: + ok = psa_mac_sign_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_UPDATE: + ok = psa_mac_update_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_VERIFY: + ok = psa_mac_verify_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_VERIFY_FINISH: + ok = psa_mac_verify_finish_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_VERIFY_SETUP: + ok = psa_mac_verify_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_PURGE_KEY: + ok = psa_purge_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_RAW_KEY_AGREEMENT: + ok = psa_raw_key_agreement_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_RESET_KEY_ATTRIBUTES: + ok = psa_reset_key_attributes_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH: + ok = psa_sign_hash_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH_ABORT: + ok = psa_sign_hash_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH_COMPLETE: + ok = psa_sign_hash_complete_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH_GET_NUM_OPS: + ok = psa_sign_hash_get_num_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH_START: + ok = psa_sign_hash_start_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_MESSAGE: + ok = psa_sign_message_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH: + ok = psa_verify_hash_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH_ABORT: + ok = psa_verify_hash_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH_COMPLETE: + ok = psa_verify_hash_complete_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH_GET_NUM_OPS: + ok = psa_verify_hash_get_num_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH_START: + ok = psa_verify_hash_start_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_MESSAGE: + ok = psa_verify_message_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + } + + free(in_params); + + if (out_params_len > msg.out_size[1]) { + fprintf(stderr, "unable to write %zu bytes into buffer of %zu bytes\n", + out_params_len, msg.out_size[1]); + exit(1); + } + + /* Write the exact amount of data we're returning */ + psa_write(msg.handle, 0, &out_params_len, sizeof(out_params_len)); + + /* And write the data itself */ + if (out_params_len) { + psa_write(msg.handle, 1, out_params, out_params_len); + } + + free(out_params); + + return ok ? PSA_SUCCESS : PSA_ERROR_GENERIC_ERROR; +} + +void psa_crypto_close(void) +{ + psa_sim_serialize_reset(); +} diff --git a/psasim/src/psa_sim_generate.pl b/psasim/src/psa_sim_generate.pl new file mode 100755 index 0000000000..0f4c86f817 --- /dev/null +++ b/psasim/src/psa_sim_generate.pl @@ -0,0 +1,1208 @@ +#!/usr/bin/env perl +# +# This is a proof-of-concept script to show that the client and server wrappers +# can be created by a script. It is not hooked into the build, so is run +# manually and the output files are what are to be reviewed. In due course +# this will be replaced by a Python script based on the +# code_wrapper.psa_wrapper module. +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +use strict; +use Data::Dumper; +use File::Basename; +use JSON qw(encode_json); + +my $debug = 0; + +# Globals (sorry!) +my $output_dir = dirname($0); + +my %functions = get_functions(); +my @functions = sort keys %functions; + +# We don't want these functions (e.g. because they are not implemented, etc) +my @skip_functions = ( + 'mbedtls_psa_crypto_free', # redefined rather than wrapped + 'mbedtls_psa_external_get_random', # not in the default config, uses unsupported type + 'mbedtls_psa_get_stats', # uses unsupported type + 'mbedtls_psa_platform_get_builtin_key', # not in the default config, uses unsupported type + 'psa_get_key_slot_number', # not in the default config, uses unsupported type + 'psa_key_derivation_verify_bytes', # not implemented yet + 'psa_key_derivation_verify_key', # not implemented yet +); + +my $skip_functions_re = '\A(' . join('|', @skip_functions). ')\Z'; +@functions = grep(!/$skip_functions_re + |_pake_ # Skip everything PAKE + |_init\Z # constructors + /x, @functions); +# Restore psa_crypto_init() and put it first. +unshift @functions, 'psa_crypto_init'; + +# get_functions(), called above, returns a data structure for each function +# that we need to create client and server stubs for. The functions are +# listed from PSA header files. +# +# In this script, the data for psa_crypto_init() looks like: +# +# "psa_crypto_init": { +# "return": { # Info on return type +# "type": "psa_status_t", # Return type +# "name": "status", # Name to be used for this in C code +# "default": "PSA_ERROR_CORRUPTION_DETECTED" # Default value +# }, +# "args": [], # void function, so args empty +# } +# +# The data for psa_hash_compute() looks like: +# +# "psa_hash_compute": { +# "return": { # Information on return type +# "type": "psa_status_t", +# "name": "status", +# "default": "PSA_ERROR_CORRUPTION_DETECTED" +# }, +# "args": [{ +# "type": "psa_algorithm_t", # Type of first argument +# "ctypename": "psa_algorithm_t ", # C type with trailing spaces +# # (so that e.g. `char *` looks ok) +# "name": "alg", +# "is_output": 0 +# }, { +# "type": "const buffer", # Specially created +# "ctypename": "", # (so no C type) +# "name": "input, input_length", # A pair of arguments +# "is_output": 0 # const, so not an output argument +# }, { +# "type": "buffer", # Specially created +# "ctypename": "", +# "name": "hash, hash_size", +# "is_output": 1 # Not const, so output argument +# }, { +# "type": "size_t", # size_t *hash_length +# "ctypename": "size_t ", +# "name": "*hash_length", # * comes into the name +# "is_output": 1 +# } +# ], +# }, +# +# It's possible that a production version might not need both type and ctypename; +# that was done for convenience and future-proofing during development. + +write_function_codes("$output_dir/psa_functions_codes.h"); + +write_client_calls("$output_dir/psa_sim_crypto_client.c"); + +write_server_implementations("$output_dir/psa_sim_crypto_server.c"); + +sub write_function_codes +{ + my ($file) = @_; + + open(my $fh, ">", $file) || die("$0: $file: $!\n"); + + # NOTE: psa_crypto_init() is written manually + + print $fh <", $file) || die("$0: $file: $!\n"); + + print $fh client_calls_header(); + + for my $function (@functions) { + # psa_crypto_init() is hand written to establish connection to server + if ($function ne "psa_crypto_init") { + my $f = $functions{$function}; + output_client($fh, $f, $function); + } + } + + close($fh); +} + +sub write_server_implementations +{ + my ($file) = @_; + + open(my $fh, ">", $file) || die("$0: $file: $!\n"); + + print $fh server_implementations_header(); + + print $fh debug_functions() if $debug; + + for my $function (@functions) { + my $f = $functions{$function}; + output_server_wrapper($fh, $f, $function); + } + + # Now output a switch statement that calls each of the wrappers + + print $fh < msg.out_size[1]) { + fprintf(stderr, "unable to write %zu bytes into buffer of %zu bytes\\n", + out_params_len, msg.out_size[1]); + exit(1); + } + + /* Write the exact amount of data we're returning */ + psa_write(msg.handle, 0, &out_params_len, sizeof(out_params_len)); + + /* And write the data itself */ + if (out_params_len) { + psa_write(msg.handle, 1, out_params, out_params_len); + } + + free(out_params); + + return ok ? PSA_SUCCESS : PSA_ERROR_GENERIC_ERROR; +} +EOF + + # Finally, add psa_crypto_close() + + print $fh < +#include + +#include + +#include "psa_functions_codes.h" +#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 + +#if defined(MBEDTLS_TEST_HOOKS) +void (*mbedtls_test_hook_error_add)(int, int, const char *, int); +#endif +EOF +} + +sub client_calls_header +{ + my $code = <<'EOF'; +/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */ + +/* client calls */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include +#include + +/* Includes from psasim */ +#include +#include +#include "psa_manifest/sid.h" +#include "psa_functions_codes.h" +#include "psa_sim_serialise.h" + +/* Includes from mbedtls */ +#include "mbedtls/version.h" +#include "psa/crypto.h" + +#define CLIENT_PRINT(fmt, ...) \ + INFO("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; + + $code .= <<'EOF'; + +int psa_crypto_call(int function, + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + // psa_outvec outvecs[1]; + if (handle < 0) { + fprintf(stderr, "NOT CONNECTED\n"); + exit(1); + } + + psa_invec invec; + invec.base = in_params; + invec.len = in_params_len; + + size_t max_receive = 24576; + uint8_t *receive = malloc(max_receive); + if (receive == NULL) { + fprintf(stderr, "FAILED to allocate %u bytes\n", (unsigned) max_receive); + exit(1); + } + + size_t actual_received = 0; + + psa_outvec outvecs[2]; + outvecs[0].base = &actual_received; + outvecs[0].len = sizeof(actual_received); + outvecs[1].base = receive; + outvecs[1].len = max_receive; + + psa_status_t status = psa_call(handle, function, &invec, 1, outvecs, 2); + if (status != PSA_SUCCESS) { + free(receive); + return 0; + } + + *out_params = receive; + *out_params_len = actual_received; + + return 1; // success +} + +psa_status_t psa_crypto_init(void) +{ + const char *mbedtls_version; + uint8_t *result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + mbedtls_version = mbedtls_version_get_string_full(); + CLIENT_PRINT("%s", mbedtls_version); + + CLIENT_PRINT("My PID: %d", getpid()); + + CLIENT_PRINT("PSA version: %u", psa_version(PSA_SID_CRYPTO_SID)); + handle = psa_connect(PSA_SID_CRYPTO_SID, 1); + + if (handle < 0) { + CLIENT_PRINT("Couldn't connect %d", handle); + return PSA_ERROR_COMMUNICATION_FAILURE; + } + + int ok = psa_crypto_call(PSA_CRYPTO_INIT, NULL, 0, &result, &result_length); + CLIENT_PRINT("PSA_CRYPTO_INIT returned: %d", ok); + + if (!ok) { + 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(result); + + return status; +} + +void mbedtls_psa_crypto_free(void) +{ + /* Do not try to close a connection that was never started.*/ + if (handle == -1) { + return; + } + + CLIENT_PRINT("Closing handle"); + psa_close(handle); + handle = -1; +} +EOF +} + +sub debug_functions +{ + return <> 4); + p[1] = hex_digit(b & 0x0F); + + return 2; +} + +int hex_uint16(char *p, uint16_t b) +{ + hex_byte(p, b >> 8); + hex_byte(p + 2, b & 0xFF); + + return 4; +} + +char human_char(uint8_t c) +{ + return (c >= ' ' && c <= '~') ? (char)c : '.'; +} + +void dump_buffer(const uint8_t *buffer, size_t len) +{ + char line[80]; + + const uint8_t *p = buffer; + + size_t max = (len > 0xFFFF) ? 0xFFFF : len; + + for (size_t i = 0; i < max; i += 16) { + + char *q = line; + + q += hex_uint16(q, (uint16_t)i); + *q++ = ' '; + *q++ = ' '; + + size_t ll = (i + 16 > max) ? (max % 16) : 16; + + size_t j; + for (j = 0; j < ll; j++) { + q += hex_byte(q, p[i + j]); + *q++ = ' '; + } + + while (j++ < 16) { + *q++ = ' '; + *q++ = ' '; + *q++ = ' '; + } + + *q++ = ' '; + + for (j = 0; j < ll; j++) { + *q++ = human_char(p[i + j]); + } + + *q = '\\0'; + + printf("%s\\n", line); + } +} + +void hex_dump(uint8_t *p, size_t n) +{ + for (size_t i = 0; i < n; i++) { + printf("0x%02X ", p[i]); + } + printf("\\n"); +} +EOF +} + +sub output_server_wrapper +{ + my ($fh, $f, $name) = @_; + + my $ret_type = $f->{return}->{type}; + my $ret_name = $f->{return}->{name}; + my $ret_default = $f->{return}->{default}; + + my @buffers = (); # We need to free() these on exit + + print $fh <{args}; + + for my $i (0 .. $#$args) { + my $arg = $args->[$i]; + my $argtype = $arg->{type}; # e.g. int, psa_algorithm_t, or "buffer" + my $argname = $arg->{name}; + $argtype =~ s/^const //; + + if ($argtype =~ /^(const )?buffer$/) { + my ($n1, $n2) = split(/,\s*/, $argname); + print $fh <= 0) { # If we have any args (>= 0) + print $fh <= 0) { # If we have any args (>= 0) + print $fh <[$i]; + my $argtype = $arg->{type}; # e.g. int, psa_algorithm_t, or "buffer" + my $argname = $arg->{name}; + my $sep = ($i == $#$args) ? ";" : " +"; + $argtype =~ s/^const //; + + if ($argtype =~ /^(const )?buffer$/) { + my ($n1, $n2) = split(/,\s*/, $argname); + print $fh <{is_output}, @$args); + + my $sep1 = (($ret_type eq "void") and ($#outputs < 0)) ? ";" : " +"; + + print $fh <{is_output}; + my $argtype = $arg->{type}; # e.g. int, psa_algorithm_t, or "buffer" + my $argname = $arg->{name}; + my $sep = ($i == $#outputs) ? ";" : " +"; + $argtype =~ s/^const //; + $argname =~ s/^\*//; # Remove any leading * + my $server_specific = ($argtype =~ /^psa_\w+_operation_t/) ? "server_" : ""; + + print $fh <{is_output}, @$args); + + for my $i (0 .. $#outputs) { + my $arg = $outputs[$i]; + die("$i: this should have been filtered out by grep") unless $arg->{is_output}; + my $argtype = $arg->{type}; # e.g. int, psa_algorithm_t, or "buffer" + my $argname = $arg->{name}; + my $sep = ($i == $#outputs) ? ";" : " +"; + $argtype =~ s/^const //; + + if ($argtype eq "buffer") { + print $fh <{return}->{type}; + my $ret_name = $f->{return}->{name}; + my $ret_default = $f->{return}->{default}; + + print $fh <{args}; + + for my $i (0 .. $#$args) { + my $arg = $args->[$i]; + my $argtype = $arg->{type}; # e.g. int, psa_algorithm_t, or "buffer" + my $argname = $arg->{name}; + my $sep = ($i == $#$args) ? ";" : " +"; + $argtype =~ s/^const //; + + print $fh <[$i]; + my $argtype = $arg->{type}; # e.g. int, psa_algorithm_t, or "buffer" + my $argname = $arg->{name}; + my $sep = ($i == $#$args) ? ";" : " +"; + $argtype =~ s/^const //; + + print $fh <{is_output}, @$args); + + for my $i (0 .. $#outputs) { + my $arg = $outputs[$i]; + die("$i: this should have been filtered out by grep") unless $arg->{is_output}; + my $argtype = $arg->{type}; # e.g. int, psa_algorithm_t, or "buffer" + my $argname = $arg->{name}; + my $sep = ($i == $#outputs) ? ";" : " +"; + $argtype =~ s/^const //; + + if ($argtype eq "buffer") { + print $fh <{return}->{type}; + my $ret_name = $f->{return}->{name}; + my $args = $f->{args}; + + if ($ret_type eq "void") { + print $fh "\n $name(\n"; + } else { + print $fh "\n $ret_name = $name(\n"; + } + + print $fh " );\n" if $#$args < 0; # If no arguments, empty arg list + + for my $i (0 .. $#$args) { + my $arg = $args->[$i]; + my $argtype = $arg->{type}; # e.g. int, psa_algorithm_t, or "buffer" + my $argname = $arg->{name}; + + if ($argtype =~ /^(const )?buffer$/) { + my ($n1, $n2) = split(/,\s*/, $argname); + 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 );" : ","; + print $fh "$sep\n"; + } +} + +sub output_signature +{ + my ($fh, $f, $name, $what) = @_; + + my $ret_type = $f->{return}->{type}; + my $args = $f->{args}; + + my $final_sep = ($what eq "declaration") ? "\n);" : "\n )"; + + print $fh "\n$ret_type $name(\n"; + + print $fh " void\n )\n" if $#$args < 0; # No arguments + + for my $i (0 .. $#$args) { + my $arg = $args->[$i]; + my $argtype = $arg->{type}; # e.g. int, psa_algorithm_t, or "buffer" + my $ctypename = $arg->{ctypename}; # e.g. "int ", "char *"; empty for buffer + my $argname = $arg->{name}; + + if ($argtype =~ /^(const )?buffer$/) { + my $const = length($1) ? "const " : ""; + my ($n1, $n2) = split(/,/, $argname); + print $fh " ${const}uint8_t *$n1, size_t $n2"; + } else { + print $fh " $ctypename$argname"; + } + my $sep = ($i == $#$args) ? $final_sep : ","; + print $fh "$sep\n"; + } +} + +sub get_functions +{ + my $header_dir = 'tf-psa-crypto/include'; + my $src = ""; + for my $header_file ('psa/crypto.h', 'psa/crypto_extra.h') { + local *HEADER; + open HEADER, '<', "$header_dir/$header_file" + or die "$header_dir/$header_file: $!"; + while (
) { + chomp; + s/\/\/.*//; + s/\s+^//; + s/\s+/ /g; + $_ .= "\n"; + $src .= $_; + } + close HEADER; + } + + $src =~ s/\/\*.*?\*\///gs; + + my @src = split(/\n+/, $src); + + my @rebuild = (); + my %funcs = (); + for (my $i = 0; $i <= $#src; $i++) { + my $line = $src[$i]; + if ($line =~ /^(static(?:\s+inline)?\s+)? + ((?:(?:enum|struct|union)\s+)?\w+\s*\**\s*)\s+ + ((?:mbedtls|psa)_\w*)\(/x) { + # begin function declaration + #print "have one $line\n"; + while ($line !~ /;/) { + $line .= $src[$i + 1]; + $i++; + } + if ($line =~ /^static/) { + # IGNORE static inline functions: they're local. + next; + } + $line =~ s/\s+/ /g; + if ($line =~ /(\w+)\s+\b(\w+)\s*\(\s*(.*\S)\s*\)\s*[;{]/s) { + my ($ret_type, $func, $args) = ($1, $2, $3); + + my $copy = $line; + $copy =~ s/{$//; + my $f = { + "orig" => $copy, + }; + + my @args = split(/\s*,\s*/, $args); + + my $ret_name = ""; + $ret_name = "status" if $ret_type eq "psa_status_t"; + $ret_name = "value" if $ret_type eq "uint32_t"; + $ret_name = "value" if $ret_type eq "int"; + $ret_name = "(void)" if $ret_type eq "void"; + die("ret_name for $ret_type?") unless length($ret_name); + my $ret_default = ""; + $ret_default = "PSA_ERROR_CORRUPTION_DETECTED" if $ret_type eq "psa_status_t"; + $ret_default = "0" if $ret_type eq "uint32_t"; + $ret_default = "0" if $ret_type eq "int"; + $ret_default = "(void)" if $ret_type eq "void"; + die("ret_default for $ret_type?") unless length($ret_default); + + #print "FUNC $func RET_NAME $ret_name RET_TYPE $ret_type ARGS (", join("; ", @args), ")\n"; + + $f->{return} = { + "type" => $ret_type, + "default" => $ret_default, + "name" => $ret_name, + }; + $f->{args} = []; + # psa_algorithm_t alg; const uint8_t *input; size_t input_length; uint8_t *hash; size_t hash_size; size_t *hash_length + for (my $i = 0; $i <= $#args; $i++) { + my $arg = $args[$i]; + # "type" => "psa_algorithm_t", + # "ctypename" => "psa_algorithm_t ", + # "name" => "alg", + # "is_output" => 0, + my ($type, $ctype, $name, $is_output); + if ($arg =~ /^(\w+)\s+(\w+)$/) { # e.g. psa_algorithm_t alg + ($type, $name) = ($1, $2); + $ctype = $type . " "; + $is_output = 0; + } elsif ($arg =~ /^((const)\s+)?uint8_t\s*\*\s*(\w+)$/) { + $type = "buffer"; + $is_output = (length($1) == 0) ? 1 : 0; + $type = "const buffer" if !$is_output; + $ctype = ""; + $name = $3; + #print("$arg: $name: might be a buffer?\n"); + die("$arg: not a buffer 1!\n") if $i == $#args; + my $next = $args[$i + 1]; + if ($func eq "psa_key_derivation_verify_bytes" && + $arg eq "const uint8_t *expected_output" && + $next eq "size_t output_length") { + $next = "size_t expected_output_length"; # doesn't follow naming convention, so override + } + die("$arg: not a buffer 2!\n") if $next !~ /^size_t\s+(${name}_\w+)$/; + $i++; # We're using the next param here + my $nname = $1; + $name .= ", " . $nname; + } elsif ($arg =~ /^((const)\s+)?(\w+)\s*\*(\w+)$/) { + ($type, $name) = ($3, "*" . $4); + $ctype = $1 . $type . " "; + $is_output = (length($1) == 0) ? 1 : 0; + } elsif ($arg eq "void") { + # we'll just ignore this one + } else { + die("ARG HELP $arg\n"); + } + #print "$arg => <$type><$ctype><$name><$is_output>\n"; + if ($arg ne "void") { + push(@{$f->{args}}, { + "type" => $type, + "ctypename" => $ctype, + "name" => $name, + "is_output" => $is_output, + }); + } + } + $funcs{$func} = $f; + } else { + die("FAILED"); + } + push(@rebuild, $line); + } elsif ($line =~ /^#/i) { + # IGNORE directive + while ($line =~ /\\$/) { + $i++; + $line = $src[$i]; + } + } elsif ($line =~ /^(?:typedef +)?(enum|struct|union)[^;]*$/) { + # IGNORE compound type definition + while ($line !~ /^\}/) { + $i++; + $line = $src[$i]; + } + } elsif ($line =~ /^typedef /i) { + # IGNORE type definition + } elsif ($line =~ / = .*;$/) { + # IGNORE assignment in inline function definition + } else { + if ($line =~ /psa_/) { + print "NOT PARSED: $line\n"; + } + push(@rebuild, $line); + } + } + + #print ::Dumper(\%funcs); + #exit; + + return %funcs; +} diff --git a/psasim/src/psa_sim_serialise.c b/psasim/src/psa_sim_serialise.c new file mode 100644 index 0000000000..0dde934ada --- /dev/null +++ b/psasim/src/psa_sim_serialise.c @@ -0,0 +1,1765 @@ +/** + * \file psa_sim_serialise.c + * + * \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa_sim_serialise.h" +#include "util.h" +#include +#include + +/* Basic idea: + * + * All arguments to a function will be serialised into a single buffer to + * be sent to the server with the PSA crypto function to be called. + * + * All returned data (the function's return value and any values returned + * via `out` parameters) will similarly be serialised into a buffer to be + * sent back to the client from the server. + * + * For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer" + * where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions, + * psasim_serialise_foo() and psasim_deserialise_foo(). + * + * We also have psasim_serialise_foo_needs() functions, which return a + * size_t giving the number of bytes that serialising that instance of that + * type will need. This allows callers to size buffers for serialisation. + * + * Each serialised buffer starts with a version byte, bytes that indicate + * the size of basic C types, and four bytes that indicate the endianness + * (to avoid incompatibilities if we ever run this over a network - we are + * not aiming for universality, just for correctness and simplicity). + * + * Most types are serialised as a fixed-size (per type) octet string, with + * no type indication. This is acceptable as (a) this is for the test PSA crypto + * simulator only, not production, and (b) these functions are called by + * code that itself is written by script. + * + * We also want to keep serialised data reasonably compact as communication + * between client and server goes in messages of less than 200 bytes each. + * + * Many serialisation functions can be created by a script; an exemplar Perl + * script is included. It is not hooked into the build and so must be run + * manually, but is expected to be replaced by a Python script in due course. + * Types that can have their functions created by script include plain old C + * data types (e.g. int), types typedef'd to those, and even structures that + * 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 */ + FATAL("Hash operation handle wrapped"); + } + + 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; + } + } + + ERROR("All slots are currently used. Unable to allocate a new one."); + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_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; + } + } + + ERROR("Unable to find slot by handle %u", handle); + + return -1; /* not found */ +} + +static psa_aead_operation_t aead_operations[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t aead_operation_handles[ + MAX_LIVE_HANDLES_PER_CLASS]; +static 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 */ + FATAL("Aead operation handle wrapped"); + } + + 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; + } + } + + ERROR("All slots are currently used. Unable to allocate a new one."); + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_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; + } + } + + ERROR("Unable to find slot by handle %u", handle); + + return -1; /* not found */ +} + +static psa_mac_operation_t mac_operations[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t mac_operation_handles[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t next_mac_operation_handle = 1; + +/* Get a free slot */ +static ssize_t allocate_mac_operation_slot(void) +{ + psasim_client_handle_t handle = next_mac_operation_handle++; + if (next_mac_operation_handle == 0) { /* wrapped around */ + FATAL("Mac operation handle wrapped"); + } + + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (mac_operation_handles[i] == 0) { + mac_operation_handles[i] = handle; + return i; + } + } + + ERROR("All slots are currently used. Unable to allocate a new one."); + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_mac_slot_by_handle(psasim_client_handle_t handle) +{ + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (mac_operation_handles[i] == handle) { + return i; + } + } + + ERROR("Unable to find slot by handle %u", handle); + + return -1; /* not found */ +} + +static psa_cipher_operation_t cipher_operations[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t cipher_operation_handles[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t next_cipher_operation_handle = 1; + +/* Get a free slot */ +static ssize_t allocate_cipher_operation_slot(void) +{ + psasim_client_handle_t handle = next_cipher_operation_handle++; + if (next_cipher_operation_handle == 0) { /* wrapped around */ + FATAL("Cipher operation handle wrapped"); + } + + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (cipher_operation_handles[i] == 0) { + cipher_operation_handles[i] = handle; + return i; + } + } + + ERROR("All slots are currently used. Unable to allocate a new one."); + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_cipher_slot_by_handle(psasim_client_handle_t handle) +{ + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (cipher_operation_handles[i] == handle) { + return i; + } + } + + ERROR("Unable to find slot by handle %u", handle); + + return -1; /* not found */ +} + +static psa_key_derivation_operation_t key_derivation_operations[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t key_derivation_operation_handles[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t next_key_derivation_operation_handle = 1; + +/* Get a free slot */ +static ssize_t allocate_key_derivation_operation_slot(void) +{ + psasim_client_handle_t handle = next_key_derivation_operation_handle++; + if (next_key_derivation_operation_handle == 0) { /* wrapped around */ + FATAL("Key_derivation operation handle wrapped"); + } + + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (key_derivation_operation_handles[i] == 0) { + key_derivation_operation_handles[i] = handle; + return i; + } + } + + ERROR("All slots are currently used. Unable to allocate a new one."); + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_key_derivation_slot_by_handle(psasim_client_handle_t handle) +{ + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (key_derivation_operation_handles[i] == handle) { + return i; + } + } + + ERROR("Unable to find slot by handle %u", handle); + + return -1; /* not found */ +} + +static psa_sign_hash_interruptible_operation_t sign_hash_interruptible_operations[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t sign_hash_interruptible_operation_handles[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t next_sign_hash_interruptible_operation_handle = 1; + +/* Get a free slot */ +static ssize_t allocate_sign_hash_interruptible_operation_slot(void) +{ + psasim_client_handle_t handle = next_sign_hash_interruptible_operation_handle++; + if (next_sign_hash_interruptible_operation_handle == 0) { /* wrapped around */ + FATAL("Sign_hash_interruptible operation handle wrapped"); + } + + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (sign_hash_interruptible_operation_handles[i] == 0) { + sign_hash_interruptible_operation_handles[i] = handle; + return i; + } + } + + ERROR("All slots are currently used. Unable to allocate a new one."); + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_sign_hash_interruptible_slot_by_handle(psasim_client_handle_t handle) +{ + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (sign_hash_interruptible_operation_handles[i] == handle) { + return i; + } + } + + ERROR("Unable to find slot by handle %u", handle); + + return -1; /* not found */ +} + +static psa_verify_hash_interruptible_operation_t verify_hash_interruptible_operations[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t verify_hash_interruptible_operation_handles[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t next_verify_hash_interruptible_operation_handle = 1; + +/* Get a free slot */ +static ssize_t allocate_verify_hash_interruptible_operation_slot(void) +{ + psasim_client_handle_t handle = next_verify_hash_interruptible_operation_handle++; + if (next_verify_hash_interruptible_operation_handle == 0) { /* wrapped around */ + FATAL("Verify_hash_interruptible operation handle wrapped"); + } + + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (verify_hash_interruptible_operation_handles[i] == 0) { + verify_hash_interruptible_operation_handles[i] = handle; + return i; + } + } + + ERROR("All slots are currently used. Unable to allocate a new one."); + + return -1; /* all in use */ +} + +/* Find the slot given the handle */ +static ssize_t find_verify_hash_interruptible_slot_by_handle(psasim_client_handle_t handle) +{ + for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) { + if (verify_hash_interruptible_operation_handles[i] == handle) { + return i; + } + } + + ERROR("Unable to find slot by handle %u", handle); + + return -1; /* not found */ +} + +size_t psasim_serialise_begin_needs(void) +{ + /* The serialisation buffer will + * start with a byte of 0 to indicate version 0, + * then have 1 byte each for length of int, long, void *, + * then have 4 bytes to indicate endianness. */ + return 4 + sizeof(uint32_t); +} + +int psasim_serialise_begin(uint8_t **pos, size_t *remaining) +{ + uint32_t endian = 0x1234; + + if (*remaining < 4 + sizeof(endian)) { + return 0; + } + + *(*pos)++ = 0; /* version */ + *(*pos)++ = (uint8_t) sizeof(int); + *(*pos)++ = (uint8_t) sizeof(long); + *(*pos)++ = (uint8_t) sizeof(void *); + + memcpy(*pos, &endian, sizeof(endian)); + + *pos += sizeof(endian); + + return 1; +} + +int psasim_deserialise_begin(uint8_t **pos, size_t *remaining) +{ + uint8_t version = 255; + uint8_t int_size = 0; + uint8_t long_size = 0; + uint8_t ptr_size = 0; + uint32_t endian; + + if (*remaining < 4 + sizeof(endian)) { + return 0; + } + + memcpy(&version, (*pos)++, sizeof(version)); + if (version != 0) { + return 0; + } + + memcpy(&int_size, (*pos)++, sizeof(int_size)); + if (int_size != sizeof(int)) { + return 0; + } + + memcpy(&long_size, (*pos)++, sizeof(long_size)); + if (long_size != sizeof(long)) { + return 0; + } + + memcpy(&ptr_size, (*pos)++, sizeof(ptr_size)); + if (ptr_size != sizeof(void *)) { + return 0; + } + + *remaining -= 4; + + memcpy(&endian, *pos, sizeof(endian)); + if (endian != 0x1234) { + return 0; + } + + *pos += sizeof(endian); + *remaining -= sizeof(endian); + + return 1; +} + +size_t psasim_serialise_unsigned_int_needs( + unsigned int value) +{ + return sizeof(value); +} + +int psasim_serialise_unsigned_int(uint8_t **pos, + size_t *remaining, + unsigned int value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_unsigned_int(uint8_t **pos, + size_t *remaining, + unsigned int *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_serialise_int_needs( + int value) +{ + return sizeof(value); +} + +int psasim_serialise_int(uint8_t **pos, + size_t *remaining, + int value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_int(uint8_t **pos, + size_t *remaining, + int *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_serialise_size_t_needs( + size_t value) +{ + return sizeof(value); +} + +int psasim_serialise_size_t(uint8_t **pos, + size_t *remaining, + size_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_size_t(uint8_t **pos, + size_t *remaining, + size_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_uint16_t_needs( + uint16_t value) +{ + return sizeof(value); +} + +int psasim_serialise_uint16_t(uint8_t **pos, + size_t *remaining, + uint16_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_uint16_t(uint8_t **pos, + size_t *remaining, + uint16_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_serialise_uint32_t_needs( + uint32_t value) +{ + return sizeof(value); +} + +int psasim_serialise_uint32_t(uint8_t **pos, + size_t *remaining, + uint32_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_uint32_t(uint8_t **pos, + size_t *remaining, + uint32_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_serialise_uint64_t_needs( + uint64_t value) +{ + return sizeof(value); +} + +int psasim_serialise_uint64_t(uint8_t **pos, + size_t *remaining, + uint64_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_uint64_t(uint8_t **pos, + size_t *remaining, + uint64_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size) +{ + (void) buffer; + return sizeof(buffer_size) + buffer_size; +} + +int psasim_serialise_buffer(uint8_t **pos, + size_t *remaining, + const uint8_t *buffer, + size_t buffer_length) +{ + if (*remaining < sizeof(buffer_length) + buffer_length) { + return 0; + } + + memcpy(*pos, &buffer_length, sizeof(buffer_length)); + *pos += sizeof(buffer_length); + + if (buffer_length > 0) { // To be able to serialise (NULL, 0) + memcpy(*pos, buffer, buffer_length); + *pos += buffer_length; + } + + return 1; +} + +int psasim_deserialise_buffer(uint8_t **pos, + size_t *remaining, + uint8_t **buffer, + size_t *buffer_length) +{ + if (*remaining < sizeof(*buffer_length)) { + return 0; + } + + memcpy(buffer_length, *pos, sizeof(*buffer_length)); + + *pos += sizeof(buffer_length); + *remaining -= sizeof(buffer_length); + + if (*buffer_length == 0) { // Deserialise (NULL, 0) + *buffer = NULL; + return 1; + } + + if (*remaining < *buffer_length) { + return 0; + } + + uint8_t *data = malloc(*buffer_length); + if (data == NULL) { + return 0; + } + + memcpy(data, *pos, *buffer_length); + *pos += *buffer_length; + *remaining -= *buffer_length; + + *buffer = data; + + return 1; +} + +/* When the client is deserialising a buffer returned from the server, it needs + * to use this function to deserialised the returned buffer. It should use the + * usual \c psasim_serialise_buffer() function to serialise the outbound + * buffer. */ +int psasim_deserialise_return_buffer(uint8_t **pos, + size_t *remaining, + uint8_t *buffer, + size_t buffer_length) +{ + if (*remaining < sizeof(buffer_length)) { + return 0; + } + + size_t length_check; + + memcpy(&length_check, *pos, sizeof(buffer_length)); + + *pos += sizeof(buffer_length); + *remaining -= sizeof(buffer_length); + + if (buffer_length != length_check) { // Make sure we're sent back the same we sent to the server + return 0; + } + + if (length_check == 0) { // Deserialise (NULL, 0) + return 1; + } + + if (*remaining < buffer_length) { + return 0; + } + + memcpy(buffer, *pos, buffer_length); + *pos += buffer_length; + *remaining -= buffer_length; + + return 1; +} + +size_t psasim_serialise_psa_custom_key_parameters_t_needs( + psa_custom_key_parameters_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_custom_key_parameters_t(uint8_t **pos, + size_t *remaining, + psa_custom_key_parameters_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_custom_key_parameters_t(uint8_t **pos, + size_t *remaining, + psa_custom_key_parameters_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_psa_status_t_needs( + psa_status_t value) +{ + return psasim_serialise_int_needs(value); +} + +int psasim_serialise_psa_status_t(uint8_t **pos, + size_t *remaining, + psa_status_t value) +{ + return psasim_serialise_int(pos, remaining, value); +} + +int psasim_deserialise_psa_status_t(uint8_t **pos, + size_t *remaining, + psa_status_t *value) +{ + return psasim_deserialise_int(pos, remaining, value); +} + +size_t psasim_serialise_psa_algorithm_t_needs( + psa_algorithm_t value) +{ + return psasim_serialise_unsigned_int_needs(value); +} + +int psasim_serialise_psa_algorithm_t(uint8_t **pos, + size_t *remaining, + psa_algorithm_t value) +{ + return psasim_serialise_unsigned_int(pos, remaining, value); +} + +int psasim_deserialise_psa_algorithm_t(uint8_t **pos, + size_t *remaining, + psa_algorithm_t *value) +{ + return psasim_deserialise_unsigned_int(pos, remaining, value); +} + +size_t psasim_serialise_psa_key_derivation_step_t_needs( + psa_key_derivation_step_t value) +{ + return psasim_serialise_uint16_t_needs(value); +} + +int psasim_serialise_psa_key_derivation_step_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_step_t value) +{ + return psasim_serialise_uint16_t(pos, remaining, value); +} + +int psasim_deserialise_psa_key_derivation_step_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_step_t *value) +{ + return psasim_deserialise_uint16_t(pos, remaining, value); +} + +size_t psasim_serialise_psa_hash_operation_t_needs( + psa_hash_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_hash_operation_t(uint8_t **pos, + size_t *remaining, + psa_hash_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_hash_operation_t(uint8_t **pos, + size_t *remaining, + psa_hash_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_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, + int completed) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - hash_operations; + + if (completed) { + memset(&hash_operations[slot], + 0, + sizeof(psa_hash_operation_t)); + hash_operation_handles[slot] = 0; + } + + 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, + int completed) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - aead_operations; + + if (completed) { + memset(&aead_operations[slot], + 0, + sizeof(psa_aead_operation_t)); + aead_operation_handles[slot] = 0; + } + + 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_psa_mac_operation_t_needs( + psa_mac_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_mac_operation_t_needs( + psa_mac_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *operation, + int completed) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - mac_operations; + + if (completed) { + memset(&mac_operations[slot], + 0, + sizeof(psa_mac_operation_t)); + mac_operation_handles[slot] = 0; + } + + client_operation.handle = mac_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_mac_operation_slot(); + } else { + slot = find_mac_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &mac_operations[slot]; + + return 1; +} + +size_t psasim_serialise_psa_cipher_operation_t_needs( + psa_cipher_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_cipher_operation_t_needs( + psa_cipher_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t *operation, + int completed) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - cipher_operations; + + if (completed) { + memset(&cipher_operations[slot], + 0, + sizeof(psa_cipher_operation_t)); + cipher_operation_handles[slot] = 0; + } + + client_operation.handle = cipher_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_cipher_operation_slot(); + } else { + slot = find_cipher_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &cipher_operations[slot]; + + return 1; +} + +size_t psasim_serialise_psa_key_derivation_operation_t_needs( + psa_key_derivation_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_key_derivation_operation_t_needs( + psa_key_derivation_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t *operation, + int completed) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - key_derivation_operations; + + if (completed) { + memset(&key_derivation_operations[slot], + 0, + sizeof(psa_key_derivation_operation_t)); + key_derivation_operation_handles[slot] = 0; + } + + client_operation.handle = key_derivation_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_key_derivation_operation_slot(); + } else { + slot = find_key_derivation_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &key_derivation_operations[slot]; + + return 1; +} + +size_t psasim_serialise_psa_sign_hash_interruptible_operation_t_needs( + psa_sign_hash_interruptible_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs( + psa_sign_hash_interruptible_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t *operation, + int completed) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - sign_hash_interruptible_operations; + + if (completed) { + memset(&sign_hash_interruptible_operations[slot], + 0, + sizeof(psa_sign_hash_interruptible_operation_t)); + sign_hash_interruptible_operation_handles[slot] = 0; + } + + client_operation.handle = sign_hash_interruptible_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_sign_hash_interruptible_operation_slot(); + } else { + slot = find_sign_hash_interruptible_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &sign_hash_interruptible_operations[slot]; + + return 1; +} + +size_t psasim_serialise_psa_verify_hash_interruptible_operation_t_needs( + psa_verify_hash_interruptible_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs( + psa_verify_hash_interruptible_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t *operation, + int completed) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - verify_hash_interruptible_operations; + + if (completed) { + memset(&verify_hash_interruptible_operations[slot], + 0, + sizeof(psa_verify_hash_interruptible_operation_t)); + verify_hash_interruptible_operation_handles[slot] = 0; + } + + client_operation.handle = verify_hash_interruptible_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_verify_hash_interruptible_operation_slot(); + } else { + slot = find_verify_hash_interruptible_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &verify_hash_interruptible_operations[slot]; + + return 1; +} + +size_t psasim_serialise_mbedtls_svc_key_id_t_needs( + mbedtls_svc_key_id_t value) +{ + return sizeof(value); +} + +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; +} + +size_t psasim_serialise_psa_key_agreement_iop_t_needs( + psa_key_agreement_iop_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_key_agreement_iop_t(uint8_t **pos, + size_t *remaining, + psa_key_agreement_iop_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_key_agreement_iop_t(uint8_t **pos, + size_t *remaining, + psa_key_agreement_iop_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_psa_generate_key_iop_t_needs( + psa_generate_key_iop_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_generate_key_iop_t(uint8_t **pos, + size_t *remaining, + psa_generate_key_iop_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_generate_key_iop_t(uint8_t **pos, + size_t *remaining, + psa_generate_key_iop_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_psa_export_public_key_iop_t_needs( + psa_export_public_key_iop_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_export_public_key_iop_t(uint8_t **pos, + size_t *remaining, + psa_export_public_key_iop_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_export_public_key_iop_t(uint8_t **pos, + size_t *remaining, + psa_export_public_key_iop_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +void psa_sim_serialize_reset(void) +{ + memset(hash_operation_handles, 0, + sizeof(hash_operation_handles)); + memset(hash_operations, 0, + sizeof(hash_operations)); + memset(aead_operation_handles, 0, + sizeof(aead_operation_handles)); + memset(aead_operations, 0, + sizeof(aead_operations)); + memset(mac_operation_handles, 0, + sizeof(mac_operation_handles)); + memset(mac_operations, 0, + sizeof(mac_operations)); + memset(cipher_operation_handles, 0, + sizeof(cipher_operation_handles)); + memset(cipher_operations, 0, + sizeof(cipher_operations)); + memset(key_derivation_operation_handles, 0, + sizeof(key_derivation_operation_handles)); + memset(key_derivation_operations, 0, + sizeof(key_derivation_operations)); + memset(sign_hash_interruptible_operation_handles, 0, + sizeof(sign_hash_interruptible_operation_handles)); + memset(sign_hash_interruptible_operations, 0, + sizeof(sign_hash_interruptible_operations)); + memset(verify_hash_interruptible_operation_handles, 0, + sizeof(verify_hash_interruptible_operation_handles)); + memset(verify_hash_interruptible_operations, 0, + sizeof(verify_hash_interruptible_operations)); +} diff --git a/psasim/src/psa_sim_serialise.h b/psasim/src/psa_sim_serialise.h new file mode 100644 index 0000000000..3b6f08e19d --- /dev/null +++ b/psasim/src/psa_sim_serialise.h @@ -0,0 +1,1432 @@ +/** + * \file psa_sim_serialise.h + * + * \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include +#include + +#include "psa/crypto.h" +#include "psa/crypto_types.h" +#include "psa/crypto_values.h" + +/* Basic idea: + * + * All arguments to a function will be serialised into a single buffer to + * be sent to the server with the PSA crypto function to be called. + * + * All returned data (the function's return value and any values returned + * via `out` parameters) will similarly be serialised into a buffer to be + * sent back to the client from the server. + * + * For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer" + * where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions, + * psasim_serialise_foo() and psasim_deserialise_foo(). + * + * We also have psasim_serialise_foo_needs() functions, which return a + * size_t giving the number of bytes that serialising that instance of that + * type will need. This allows callers to size buffers for serialisation. + * + * Each serialised buffer starts with a version byte, bytes that indicate + * the size of basic C types, and four bytes that indicate the endianness + * (to avoid incompatibilities if we ever run this over a network - we are + * not aiming for universality, just for correctness and simplicity). + * + * Most types are serialised as a fixed-size (per type) octet string, with + * no type indication. This is acceptable as (a) this is for the test PSA crypto + * simulator only, not production, and (b) these functions are called by + * code that itself is written by script. + * + * We also want to keep serialised data reasonably compact as communication + * between client and server goes in messages of less than 200 bytes each. + * + * Many serialisation functions can be created by a script; an exemplar Perl + * script is included. It is not hooked into the build and so must be run + * manually, but is expected to be replaced by a Python script in due course. + * Types that can have their functions created by script include plain old C + * data types (e.g. int), types typedef'd to those, and even structures that + * don't contain pointers. + */ + +/** Reset all operation slots. + * + * Should be called when all clients have disconnected. + */ +void psa_sim_serialize_reset(void); + +/** Return how much buffer space is needed by \c psasim_serialise_begin(). + * + * \return The number of bytes needed in the buffer for + * \c psasim_serialise_begin()'s output. + */ +size_t psasim_serialise_begin_needs(void); + +/** Begin serialisation into a buffer. + * + * This must be the first serialisation API called + * on 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. + * + * \return \c 1 on success ("okay"), \c 0 on error (likely + * no space). + */ +int psasim_serialise_begin(uint8_t **pos, size_t *remaining); + +/** Begin deserialisation of a buffer. + * + * This must be the first deserialisation API called + * on 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. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_begin(uint8_t **pos, size_t *remaining); + +/** Return how much buffer space is needed by \c psasim_serialise_unsigned_int() + * to serialise an `unsigned int`. + * + * \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_unsigned_int() to serialise + * the given value. + */ +size_t psasim_serialise_unsigned_int_needs( + unsigned int value); + +/** Serialise an `unsigned int` 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_unsigned_int(uint8_t **pos, + size_t *remaining, + unsigned int value); + +/** Deserialise an `unsigned int` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to an `unsigned int` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_unsigned_int(uint8_t **pos, + size_t *remaining, + unsigned int *value); + +/** Return how much buffer space is needed by \c psasim_serialise_int() + * to serialise an `int`. + * + * \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_int() to serialise + * the given value. + */ +size_t psasim_serialise_int_needs( + int value); + +/** Serialise an `int` 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_int(uint8_t **pos, + size_t *remaining, + int value); + +/** Deserialise an `int` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to an `int` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_int(uint8_t **pos, + size_t *remaining, + int *value); + +/** Return how much buffer space is needed by \c psasim_serialise_size_t() + * to serialise a `size_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_size_t() to serialise + * the given value. + */ +size_t psasim_serialise_size_t_needs( + size_t value); + +/** Serialise a `size_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_size_t(uint8_t **pos, + size_t *remaining, + size_t value); + +/** Deserialise a `size_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 `size_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_size_t(uint8_t **pos, + size_t *remaining, + size_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_uint16_t() + * to serialise an `uint16_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_uint16_t() to serialise + * the given value. + */ +size_t psasim_serialise_uint16_t_needs( + uint16_t value); + +/** Serialise an `uint16_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_uint16_t(uint8_t **pos, + size_t *remaining, + uint16_t value); + +/** Deserialise an `uint16_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to an `uint16_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_uint16_t(uint8_t **pos, + size_t *remaining, + uint16_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_uint32_t() + * to serialise an `uint32_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_uint32_t() to serialise + * the given value. + */ +size_t psasim_serialise_uint32_t_needs( + uint32_t value); + +/** Serialise an `uint32_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_uint32_t(uint8_t **pos, + size_t *remaining, + uint32_t value); + +/** Deserialise an `uint32_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to an `uint32_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_uint32_t(uint8_t **pos, + size_t *remaining, + uint32_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_uint64_t() + * to serialise an `uint64_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_uint64_t() to serialise + * the given value. + */ +size_t psasim_serialise_uint64_t_needs( + uint64_t value); + +/** Serialise an `uint64_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_uint64_t(uint8_t **pos, + size_t *remaining, + uint64_t value); + +/** Deserialise an `uint64_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to an `uint64_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_uint64_t(uint8_t **pos, + size_t *remaining, + uint64_t *value); + +/** Return how much space is needed by \c psasim_serialise_buffer() + * to serialise a buffer: a (`uint8_t *`, `size_t`) pair. + * + * \param buffer Pointer to the buffer to be serialised + * (needed in case some serialisations are value- + * dependent). + * \param buffer_size Number of bytes in the buffer to be serialised. + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_buffer() to serialise + * the specified buffer. + */ +size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size); + +/** Serialise 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 buffer Pointer to the buffer to be serialised. + * \param buffer_length Number of bytes in the buffer to be serialised. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_buffer(uint8_t **pos, size_t *remaining, + const uint8_t *buffer, size_t buffer_length); + +/** Deserialise a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the serialisation buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the serialisation buffer. + * \param buffer Pointer to a `uint8_t *` to receive the address + * of a newly-allocated buffer, which the caller + * must `free()`. + * \param buffer_length Pointer to a `size_t` to receive the number of + * bytes in the deserialised buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_buffer(uint8_t **pos, size_t *remaining, + uint8_t **buffer, size_t *buffer_length); + +/** Deserialise a buffer returned from the server. + * + * When the client is deserialising a buffer returned from the server, it needs + * to use this function to deserialised the returned buffer. It should use the + * usual \c psasim_serialise_buffer() function to serialise the outbound + * buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the serialisation buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the serialisation buffer. + * \param buffer Pointer to a `uint8_t *` to receive the address + * of a newly-allocated buffer, which the caller + * must `free()`. + * \param buffer_length Pointer to a `size_t` to receive the number of + * bytes in the deserialised buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_return_buffer(uint8_t **pos, size_t *remaining, + uint8_t *buffer, size_t buffer_length); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_custom_key_parameters_t() + * to serialise a `psa_custom_key_parameters_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_custom_key_parameters_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_custom_key_parameters_t_needs( + psa_custom_key_parameters_t value); + +/** Serialise a `psa_custom_key_parameters_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_custom_key_parameters_t(uint8_t **pos, + size_t *remaining, + psa_custom_key_parameters_t value); + +/** Deserialise a `psa_custom_key_parameters_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_custom_key_parameters_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_custom_key_parameters_t(uint8_t **pos, + size_t *remaining, + psa_custom_key_parameters_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_status_t() + * to serialise a `psa_status_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_status_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_status_t_needs( + psa_status_t value); + +/** Serialise a `psa_status_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_status_t(uint8_t **pos, + size_t *remaining, + psa_status_t value); + +/** Deserialise a `psa_status_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_status_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_status_t(uint8_t **pos, + size_t *remaining, + psa_status_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_algorithm_t() + * to serialise a `psa_algorithm_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_algorithm_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_algorithm_t_needs( + psa_algorithm_t value); + +/** Serialise a `psa_algorithm_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_algorithm_t(uint8_t **pos, + size_t *remaining, + psa_algorithm_t value); + +/** Deserialise a `psa_algorithm_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_algorithm_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_algorithm_t(uint8_t **pos, + size_t *remaining, + psa_algorithm_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_key_derivation_step_t() + * to serialise a `psa_key_derivation_step_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_key_derivation_step_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_key_derivation_step_t_needs( + psa_key_derivation_step_t value); + +/** Serialise a `psa_key_derivation_step_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_key_derivation_step_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_step_t value); + +/** Deserialise a `psa_key_derivation_step_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_key_derivation_step_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_key_derivation_step_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_step_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_hash_operation_t() + * to serialise a `psa_hash_operation_t`. + * + * \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_serialise_psa_hash_operation_t_needs( + psa_hash_operation_t value); + +/** Serialise a `psa_hash_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_hash_operation_t(uint8_t **pos, + size_t *remaining, + psa_hash_operation_t value); + +/** Deserialise a `psa_hash_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_hash_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +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. + * \param completed Non-zero if the operation is now completed (set by + * finish and abort calls). + * + * \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, + int completed); + +/** 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. + * \param completed Non-zero if the operation is now completed (set by + * finish and abort calls). + * + * \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, + int completed); + +/** 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_psa_mac_operation_t() + * to serialise a `psa_mac_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_mac_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_mac_operation_t_needs( + psa_mac_operation_t value); + +/** Serialise a `psa_mac_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t value); + +/** Deserialise a `psa_mac_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_mac_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_mac_operation_t() + * to serialise a `psa_mac_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_mac_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_mac_operation_t_needs( + psa_mac_operation_t *value); + +/** Serialise a `psa_mac_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * \param completed Non-zero if the operation is now completed (set by + * finish and abort calls). + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *value, + int completed); + +/** Deserialise a `psa_mac_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_mac_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t **value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_cipher_operation_t() + * to serialise a `psa_cipher_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_cipher_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_cipher_operation_t_needs( + psa_cipher_operation_t value); + +/** Serialise a `psa_cipher_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t value); + +/** Deserialise a `psa_cipher_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_cipher_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_cipher_operation_t() + * to serialise a `psa_cipher_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_cipher_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_cipher_operation_t_needs( + psa_cipher_operation_t *value); + +/** Serialise a `psa_cipher_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * \param completed Non-zero if the operation is now completed (set by + * finish and abort calls). + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t *value, + int completed); + +/** Deserialise a `psa_cipher_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_cipher_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t **value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_key_derivation_operation_t() + * to serialise a `psa_key_derivation_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_key_derivation_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_key_derivation_operation_t_needs( + psa_key_derivation_operation_t value); + +/** Serialise a `psa_key_derivation_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t value); + +/** Deserialise a `psa_key_derivation_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_key_derivation_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_key_derivation_operation_t() + * to serialise a `psa_key_derivation_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_key_derivation_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_key_derivation_operation_t_needs( + psa_key_derivation_operation_t *value); + +/** Serialise a `psa_key_derivation_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * \param completed Non-zero if the operation is now completed (set by + * finish and abort calls). + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t *value, + int completed); + +/** Deserialise a `psa_key_derivation_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_key_derivation_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t **value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_sign_hash_interruptible_operation_t() + * to serialise a `psa_sign_hash_interruptible_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_sign_hash_interruptible_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_sign_hash_interruptible_operation_t_needs( + psa_sign_hash_interruptible_operation_t value); + +/** Serialise a `psa_sign_hash_interruptible_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t value); + +/** Deserialise a `psa_sign_hash_interruptible_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_sign_hash_interruptible_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_sign_hash_interruptible_operation_t() + * to serialise a `psa_sign_hash_interruptible_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_sign_hash_interruptible_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs( + psa_sign_hash_interruptible_operation_t *value); + +/** Serialise a `psa_sign_hash_interruptible_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * \param completed Non-zero if the operation is now completed (set by + * finish and abort calls). + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t *value, + int completed); + +/** Deserialise a `psa_sign_hash_interruptible_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_sign_hash_interruptible_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t **value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_verify_hash_interruptible_operation_t() + * to serialise a `psa_verify_hash_interruptible_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_verify_hash_interruptible_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_verify_hash_interruptible_operation_t_needs( + psa_verify_hash_interruptible_operation_t value); + +/** Serialise a `psa_verify_hash_interruptible_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t value); + +/** Deserialise a `psa_verify_hash_interruptible_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_verify_hash_interruptible_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_verify_hash_interruptible_operation_t() + * to serialise a `psa_verify_hash_interruptible_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_verify_hash_interruptible_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs( + psa_verify_hash_interruptible_operation_t *value); + +/** Serialise a `psa_verify_hash_interruptible_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * \param completed Non-zero if the operation is now completed (set by + * finish and abort calls). + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t *value, + int completed); + +/** Deserialise a `psa_verify_hash_interruptible_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_verify_hash_interruptible_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t **value); + +/** Return how much buffer space is needed by \c psasim_serialise_mbedtls_svc_key_id_t() + * to serialise a `mbedtls_svc_key_id_t`. + * + * \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); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_key_agreement_iop_t() + * to serialise a `psa_key_agreement_iop_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_key_agreement_iop_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_key_agreement_iop_t_needs( + psa_key_agreement_iop_t value); + +/** Serialise a `psa_key_agreement_iop_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_key_agreement_iop_t(uint8_t **pos, + size_t *remaining, + psa_key_agreement_iop_t value); + +/** Deserialise a `psa_key_agreement_iop_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_key_agreement_iop_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_key_agreement_iop_t(uint8_t **pos, + size_t *remaining, + psa_key_agreement_iop_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_generate_key_iop_t() + * to serialise a `psa_generate_key_iop_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_generate_key_iop_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_generate_key_iop_t_needs( + psa_generate_key_iop_t value); + +/** Serialise a `psa_generate_key_iop_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_generate_key_iop_t(uint8_t **pos, + size_t *remaining, + psa_generate_key_iop_t value); + +/** Deserialise a `psa_generate_key_iop_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_generate_key_iop_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_generate_key_iop_t(uint8_t **pos, + size_t *remaining, + psa_generate_key_iop_t *value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_export_public_key_iop_t() + * to serialise a `psa_export_public_key_iop_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_export_public_key_iop_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_export_public_key_iop_t_needs( + psa_export_public_key_iop_t value); + +/** Serialise a `psa_export_public_key_iop_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_export_public_key_iop_t(uint8_t **pos, + size_t *remaining, + psa_export_public_key_iop_t value); + +/** Deserialise a `psa_export_public_key_iop_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_export_public_key_iop_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_export_public_key_iop_t(uint8_t **pos, + size_t *remaining, + psa_export_public_key_iop_t *value); diff --git a/psasim/src/psa_sim_serialise.pl b/psasim/src/psa_sim_serialise.pl new file mode 100755 index 0000000000..0c9faf42ef --- /dev/null +++ b/psasim/src/psa_sim_serialise.pl @@ -0,0 +1,1048 @@ +#!/usr/bin/env perl +# +# psa_sim_serialise.pl - Sample Perl script to show how many serialisation +# functions can be created by templated scripting. +# +# This is an example only, and is expected to be replaced by a Python script +# for production use. It is not hooked into the build: it needs to be run +# manually: +# +# perl psa_sim_serialise.pl h > psa_sim_serialise.h +# perl psa_sim_serialise.pl c > psa_sim_serialise.c +# +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# +use strict; + +my $usage = "$0: usage: $0 c|h\n"; +my $which = lc(shift) || die($usage); +die($usage) unless $which eq "c" || $which eq "h"; + +# Most types are serialised as a fixed-size (per type) octet string, with +# no type indication. This is acceptable as (a) this is for the test PSA crypto +# simulator only, not production, and (b) these functions are called by +# code that itself is written by script. +# +# We also want to keep serialised data reasonably compact as communication +# between client and server goes in messages of less than 200 bytes each. +# +# This script is able to create serialisation functions for plain old C data +# types (e.g. unsigned int), types typedef'd to those, and even structures +# that don't contain pointers. +# +# Structures that contain pointers will need to have their serialisation and +# deserialisation functions written manually (like those for the "buffer" type +# are). +# +my @types = qw(unsigned-int int size_t + uint16_t uint32_t uint64_t + buffer + psa_custom_key_parameters_t + psa_status_t psa_algorithm_t psa_key_derivation_step_t + psa_hash_operation_t + psa_aead_operation_t + psa_key_attributes_t + psa_mac_operation_t + psa_cipher_operation_t + psa_key_derivation_operation_t + psa_sign_hash_interruptible_operation_t + psa_verify_hash_interruptible_operation_t + mbedtls_svc_key_id_t + psa_key_agreement_iop_t + psa_generate_key_iop_t + psa_export_public_key_iop_t); + +grep(s/-/ /g, @types); + +# IS-A: Some data types are typedef'd; we serialise them as the other type +my %isa = ( + "psa_status_t" => "int", + "psa_algorithm_t" => "unsigned int", + "psa_key_derivation_step_t" => "uint16_t", +); + +if ($which eq "h") { + + print h_header(); + + for my $type (@types) { + if ($type eq "buffer") { + print declare_buffer_functions(); + } else { + 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") { + print define_buffer_functions(); + } elsif (exists($isa{$type})) { + print define_needs_isa($type, $isa{$type}); + print define_serialise_isa($type, $isa{$type}); + print define_deserialise_isa($type, $isa{$type}); + } else { + 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); + } + } + } + + print define_server_serialize_reset(@types); +} else { + die("internal error - shouldn't happen"); +} + +sub declare_needs +{ + my ($type, $server) = @_; + + my $an = ($type =~ /^[ui]/) ? "an" : "a"; + my $type_d = $type; + $type_d =~ s/ /_/g; + + my $ptr = (length($server)) ? "*" : ""; + + return < +#include + +#include "psa/crypto.h" +#include "psa/crypto_types.h" +#include "psa/crypto_values.h" + +/* Basic idea: + * + * All arguments to a function will be serialised into a single buffer to + * be sent to the server with the PSA crypto function to be called. + * + * All returned data (the function's return value and any values returned + * via `out` parameters) will similarly be serialised into a buffer to be + * sent back to the client from the server. + * + * For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer" + * where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions, + * psasim_serialise_foo() and psasim_deserialise_foo(). + * + * We also have psasim_serialise_foo_needs() functions, which return a + * size_t giving the number of bytes that serialising that instance of that + * type will need. This allows callers to size buffers for serialisation. + * + * Each serialised buffer starts with a version byte, bytes that indicate + * the size of basic C types, and four bytes that indicate the endianness + * (to avoid incompatibilities if we ever run this over a network - we are + * not aiming for universality, just for correctness and simplicity). + * + * Most types are serialised as a fixed-size (per type) octet string, with + * no type indication. This is acceptable as (a) this is for the test PSA crypto + * simulator only, not production, and (b) these functions are called by + * code that itself is written by script. + * + * We also want to keep serialised data reasonably compact as communication + * between client and server goes in messages of less than 200 bytes each. + * + * Many serialisation functions can be created by a script; an exemplar Perl + * script is included. It is not hooked into the build and so must be run + * manually, but is expected to be replaced by a Python script in due course. + * Types that can have their functions created by script include plain old C + * data types (e.g. int), types typedef'd to those, and even structures that + * don't contain pointers. + */ + +/** Reset all operation slots. + * + * Should be called when all clients have disconnected. + */ +void psa_sim_serialize_reset(void); + +/** Return how much buffer space is needed by \c psasim_serialise_begin(). + * + * \return The number of bytes needed in the buffer for + * \c psasim_serialise_begin()'s output. + */ +size_t psasim_serialise_begin_needs(void); + +/** Begin serialisation into a buffer. + * + * This must be the first serialisation API called + * on 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. + * + * \return \c 1 on success ("okay"), \c 0 on error (likely + * no space). + */ +int psasim_serialise_begin(uint8_t **pos, size_t *remaining); + +/** Begin deserialisation of a buffer. + * + * This must be the first deserialisation API called + * on 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. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_begin(uint8_t **pos, size_t *remaining); +EOF +} + +sub define_needs +{ + my ($type) = @_; + + my $type_d = $type; + $type_d =~ s/ /_/g; + + return < 0) { // To be able to serialise (NULL, 0) + memcpy(*pos, buffer, buffer_length); + *pos += buffer_length; + } + + return 1; +} + +int psasim_deserialise_buffer(uint8_t **pos, + size_t *remaining, + uint8_t **buffer, + size_t *buffer_length) +{ + if (*remaining < sizeof(*buffer_length)) { + return 0; + } + + memcpy(buffer_length, *pos, sizeof(*buffer_length)); + + *pos += sizeof(buffer_length); + *remaining -= sizeof(buffer_length); + + if (*buffer_length == 0) { // Deserialise (NULL, 0) + *buffer = NULL; + return 1; + } + + if (*remaining < *buffer_length) { + return 0; + } + + uint8_t *data = malloc(*buffer_length); + if (data == NULL) { + return 0; + } + + memcpy(data, *pos, *buffer_length); + *pos += *buffer_length; + *remaining -= *buffer_length; + + *buffer = data; + + return 1; +} + +/* When the client is deserialising a buffer returned from the server, it needs + * to use this function to deserialised the returned buffer. It should use the + * usual \c psasim_serialise_buffer() function to serialise the outbound + * buffer. */ +int psasim_deserialise_return_buffer(uint8_t **pos, + size_t *remaining, + uint8_t *buffer, + size_t buffer_length) +{ + if (*remaining < sizeof(buffer_length)) { + return 0; + } + + size_t length_check; + + memcpy(&length_check, *pos, sizeof(buffer_length)); + + *pos += sizeof(buffer_length); + *remaining -= sizeof(buffer_length); + + if (buffer_length != length_check) { // Make sure we're sent back the same we sent to the server + return 0; + } + + if (length_check == 0) { // Deserialise (NULL, 0) + return 1; + } + + if (*remaining < buffer_length) { + return 0; + } + + memcpy(buffer, *pos, buffer_length); + *pos += buffer_length; + *remaining -= buffer_length; + + return 1; +} +EOF +} + + +sub c_header +{ + return <<'EOF'; +/** + * \file psa_sim_serialise.c + * + * \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa_sim_serialise.h" +#include "util.h" +#include +#include + +/* Basic idea: + * + * All arguments to a function will be serialised into a single buffer to + * be sent to the server with the PSA crypto function to be called. + * + * All returned data (the function's return value and any values returned + * via `out` parameters) will similarly be serialised into a buffer to be + * sent back to the client from the server. + * + * For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer" + * where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions, + * psasim_serialise_foo() and psasim_deserialise_foo(). + * + * We also have psasim_serialise_foo_needs() functions, which return a + * size_t giving the number of bytes that serialising that instance of that + * type will need. This allows callers to size buffers for serialisation. + * + * Each serialised buffer starts with a version byte, bytes that indicate + * the size of basic C types, and four bytes that indicate the endianness + * (to avoid incompatibilities if we ever run this over a network - we are + * not aiming for universality, just for correctness and simplicity). + * + * Most types are serialised as a fixed-size (per type) octet string, with + * no type indication. This is acceptable as (a) this is for the test PSA crypto + * simulator only, not production, and (b) these functions are called by + * code that itself is written by script. + * + * We also want to keep serialised data reasonably compact as communication + * between client and server goes in messages of less than 200 bytes each. + * + * Many serialisation functions can be created by a script; an exemplar Perl + * script is included. It is not hooked into the build and so must be run + * manually, but is expected to be replaced by a Python script in due course. + * Types that can have their functions created by script include plain old C + * 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' + + my $utype = ucfirst($type); + + return < $#code; + + # Find where the ( is + my $idx = index($code[$i], "("); + die("can't find (") if $idx < 0; + + my $indent = " " x ($idx + 1); + do { + # Indent each line up until the one with the ; on it + $code[++$i] =~ s/^\s+/$indent/; + } while ($code[$i] !~ /;/); + + return join("\n", @code) . "\n"; +} diff --git a/psasim/src/server.c b/psasim/src/server.c new file mode 100644 index 0000000000..aa0c75a488 --- /dev/null +++ b/psasim/src/server.c @@ -0,0 +1,117 @@ +/* psasim test server */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include +#include + +/* Includes from psasim */ +#include "service.h" +#include "error_ext.h" +#include "util.h" +#include "psa_manifest/manifest.h" +#include "psa_functions_codes.h" + +/* Includes from mbedtls */ +#include "mbedtls/version.h" +#include "psa/crypto.h" + +#ifdef DEBUG +#define SERVER_PRINT(fmt, ...) \ + PRINT("Server: " fmt, ##__VA_ARGS__) +#else +#define SERVER_PRINT(...) +#endif + +#define BUF_SIZE 25 + +static int kill_on_disconnect = 0; /* Kill the server on client disconnection. */ + +void parse_input_args(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "k")) != -1) { + switch (opt) { + case 'k': + kill_on_disconnect = 1; + break; + default: + fprintf(stderr, "Usage: %s [-k]\n", argv[0]); + exit(EXIT_FAILURE); + } + } +} + +int psa_server_main(int argc, char *argv[]) +{ + psa_status_t ret = PSA_ERROR_PROGRAMMER_ERROR; + psa_msg_t msg = { -1 }; + const int magic_num = 66; + int client_disconnected = 0; + extern psa_status_t psa_crypto_call(psa_msg_t msg); + extern psa_status_t psa_crypto_close(void); + +#if defined(MBEDTLS_VERSION_C) + const char *mbedtls_version = mbedtls_version_get_string_full(); + SERVER_PRINT("%s", mbedtls_version); +#endif + + parse_input_args(argc, argv); + SERVER_PRINT("Starting"); + + while (!(kill_on_disconnect && client_disconnected)) { + psa_signal_t signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK); + + if (signals > 0) { + SERVER_PRINT("Signals: 0x%08x", signals); + } + + if (signals & PSA_CRYPTO_SIGNAL) { + if (PSA_SUCCESS == psa_get(PSA_CRYPTO_SIGNAL, &msg)) { + SERVER_PRINT("handle: %d - rhandle: %p", msg.handle, (int *) msg.rhandle); + switch (msg.type) { + case PSA_IPC_CONNECT: + SERVER_PRINT("Got a connection message"); + psa_set_rhandle(msg.handle, (void *) &magic_num); + ret = PSA_SUCCESS; + break; + case PSA_IPC_DISCONNECT: + SERVER_PRINT("Got a disconnection message"); + ret = PSA_SUCCESS; + client_disconnected = 1; + psa_crypto_close(); + break; + default: + SERVER_PRINT("Got an IPC call of type %d", msg.type); + ret = psa_crypto_call(msg); + SERVER_PRINT("Internal function call returned %d", ret); + + if (msg.client_id > 0) { + psa_notify(msg.client_id); + } else { + SERVER_PRINT("Client is non-secure, so won't notify"); + } + } + + psa_reply(msg.handle, ret); + } else { + SERVER_PRINT("Failed to retrieve message"); + } + } else if (SIGSTP_SIG & signals) { + SERVER_PRINT("Recieved SIGSTP signal. Gonna EOI it."); + psa_eoi(SIGSTP_SIG); + } else if (SIGINT_SIG & signals) { + SERVER_PRINT("Handling interrupt!"); + SERVER_PRINT("Gracefully quitting"); + psa_panic(); + } else { + SERVER_PRINT("No signal asserted"); + } + } + + return 0; +} diff --git a/psasim/test/Makefile b/psasim/test/Makefile deleted file mode 100644 index 07d1586cd6..0000000000 --- a/psasim/test/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -INCLUDE := -I../include/ -I./psa_manifest - -.PHONY: all clean - -all: - psa_autogen manifest.json - $(CC) psa_ff_bootstrap_TEST_PARTITION.c -lpsaff -o partition - $(CC) client.c -lpsaff -o client - -clean: - rm -rf psa_manifest - rm -f client partition psa_ff_bootstrap_TEST_PARTITION.c diff --git a/psasim/test/client.c b/psasim/test/client.c deleted file mode 100644 index c768a71a97..0000000000 --- a/psasim/test/client.c +++ /dev/null @@ -1,48 +0,0 @@ -/* psasim test client */ - -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -#include -#include "psa_manifest/sid.h" -#include -#include - -int main() -{ - - const char *text = "FOOBARCOOL!!"; - - char output[100] = { 0 }; - printf("My PID is %d\n", getpid()); - - printf("The version of the service is %u\n", psa_version(PSA_SID_SHA256_SID)); - psa_handle_t h = psa_connect(PSA_SID_SHA256_SID, 1); - - if (h < 0) { - printf("Couldn't connect %d\n", h); - return 1; - } else { - int type = 2; - puts("Calling!"); - puts("Trying without invec"); - printf("Answer to my call was %d (no invec)\n", psa_call(h, type, NULL, 0, NULL, 0)); - psa_invec invecs[1]; - psa_outvec outvecs[1]; - invecs[0].base = text; - invecs[0].len = 24; - outvecs[0].base = output; - outvecs[0].len = 99; - - printf("My iovec size should be %lu\n", invecs[0].len); - printf("Answer to my call was %d (with invec)\n", psa_call(h, type, invecs, 1, outvecs, 1)); - printf("Here's the payload I recieved: %s\n", output); - printf("Apparently the server wrote %lu bytes in outvec %d\n", outvecs[0].len, 0); - puts("Closing handle"); - psa_close(h); - } - - return 0; -} diff --git a/psasim/test/kill_servers.sh b/psasim/test/kill_servers.sh new file mode 100755 index 0000000000..d72263791f --- /dev/null +++ b/psasim/test/kill_servers.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +set -e + +pkill psa_server || true + +# Remove temporary files +rm -f psa_notify_* + +# Remove all IPCs +# Not just ipcrm -all=msg as it is not supported on macOS. +# Filter out header and empty lines, choosing to select based on keys being +# output in hex. +ipcs -q | fgrep 0x | awk '{ printf " -q " $2 }' | xargs ipcrm > /dev/null 2>&1 || true diff --git a/psasim/test/run_test.sh b/psasim/test/run_test.sh new file mode 100755 index 0000000000..f54e352532 --- /dev/null +++ b/psasim/test/run_test.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +# This is a simple bash script that tests psa_client/psa_server interaction. +# This script is automatically executed when "make run" is launched by the +# "psasim" root folder. The script can also be launched manually once +# binary files are built (i.e. after "make test" is executed from the "psasim" +# root folder). + +set -e + +cd "$(dirname "$0")" + +CLIENT_BIN=$1 +shift + +./kill_servers.sh + +./start_server.sh +./$CLIENT_BIN "$@" + +./kill_servers.sh diff --git a/psasim/test/server.c b/psasim/test/server.c deleted file mode 100644 index bbd90f20fc..0000000000 --- a/psasim/test/server.c +++ /dev/null @@ -1,105 +0,0 @@ -/* psasim test server */ - -/* - * Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later - */ - -#include -#include "psa_manifest/manifest.h" -#include -#include - -void printbits(uint32_t num) -{ - for (int i = 0; i < 32; i++) { - if ((num >> (31-i) & 0x1)) { - printf("1"); - } else { - printf("0"); - } - } - printf("\n"); -} - -#define BUF_SIZE 25 - -int psa_sha256_main() -{ - psa_status_t ret = PSA_ERROR_PROGRAMMER_ERROR; - psa_msg_t msg = { -1 }; - char foo[BUF_SIZE] = { 0 }; - const int magic_num = 66; - - puts("Starting"); - - while (1) { - puts("Calling psa_wait"); - psa_signal_t signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK); - - if (signals > 0) { - printbits(signals); - } - - if (signals & PSA_SHA256_SIGNAL) { - puts("Oooh a signal!"); - - if (PSA_SUCCESS == psa_get(PSA_SHA256_SIGNAL, &msg)) { - printf("My handle is %d\n", msg.handle); - printf("My rhandle is %p\n", (int *) msg.rhandle); - switch (msg.type) { - case PSA_IPC_CONNECT: - puts("Got a connection message"); - psa_set_rhandle(msg.handle, (void *) &magic_num); - ret = PSA_SUCCESS; - break; - case PSA_IPC_DISCONNECT: - puts("Got a disconnection message"); - ret = PSA_SUCCESS; - break; - - default: - printf("Got an IPC call of type %d\n", msg.type); - ret = 42; - size_t size = msg.in_size[0]; - - if ((size > 0) && (size <= sizeof(foo))) { - psa_read(msg.handle, 0, foo, 6); - foo[(BUF_SIZE-1)] = '\0'; - printf("Reading payload: %s\n", foo); - psa_read(msg.handle, 0, foo+6, 6); - foo[(BUF_SIZE-1)] = '\0'; - printf("Reading payload: %s\n", foo); - } - - size = msg.out_size[0]; - if ((size > 0)) { - puts("Writing response"); - psa_write(msg.handle, 0, "RESP", 4); - psa_write(msg.handle, 0, "ONSE", 4); - } - - if (msg.client_id > 0) { - psa_notify(msg.client_id); - } else { - puts("Client is non-secure, so won't notify"); - } - - } - - psa_reply(msg.handle, ret); - } else { - puts("Failed to retrieve message"); - } - } else if (SIGSTP_SIG & signals) { - puts("Recieved SIGSTP signal. Gonna EOI it."); - psa_eoi(SIGSTP_SIG); - } else if (SIGINT_SIG & signals) { - puts("Handling interrupt!\n"); - puts("Gracefully quitting"); - psa_panic(); - } else { - puts("No signal asserted"); - } - } -} diff --git a/psasim/test/start_server.sh b/psasim/test/start_server.sh new file mode 100755 index 0000000000..1249930af1 --- /dev/null +++ b/psasim/test/start_server.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +set -e + +# The server creates some local files when it starts up so we can wait for this +# event as signal that the server is ready so that we can start client(s). +function wait_for_server_startup() { + SECONDS=0 + TIMEOUT=10 + + while [ $(find . -name "psa_notify_*" | wc -l) -eq 0 ]; do + if [ "$SECONDS" -ge "$TIMEOUT" ]; then + echo "Timeout: psa_server not started within $TIMEOUT seconds." + return 1 + fi + sleep 0.1 + done +} + +$(dirname "$0")/psa_server & +wait_for_server_startup diff --git a/psasim/tools/psa_autogen.py b/psasim/tools/psa_autogen.py index 685320733e..fbc98060fe 100755 --- a/psasim/tools/psa_autogen.py +++ b/psasim/tools/psa_autogen.py @@ -15,6 +15,13 @@ FILENAME = str(sys.argv[1]) +SCRIPT_PATH = os.path.dirname(__file__) +GENERATED_H_PATH = os.path.join(SCRIPT_PATH, "..", "include", "psa_manifest") +GENERATED_C_PATH = os.path.join(SCRIPT_PATH, "..", "src") + +MANIFEST_FILE = os.path.join(GENERATED_H_PATH, "manifest.h") +PID_FILE = os.path.join(GENERATED_H_PATH, "pid.h") +SID_FILE = os.path.join(GENERATED_H_PATH, "sid.h") with open(str(FILENAME), "r") as read_file: data = json.load(read_file) @@ -32,58 +39,58 @@ irqs = [] try: - os.mkdir("psa_manifest") + os.mkdir(GENERATED_H_PATH) print("Generating psa_manifest directory") except OSError: - print ("PSA manifest directory already exists") + print("PSA manifest directory already exists") - man = open(str("psa_manifest/" + FILENAME + ".h"), "w") - pids = open("psa_manifest/pid.h", "a") - sids = open("psa_manifest/sid.h", "a") + manifest_content = [] + pids_content = [] + sids_content = [] if len(services) > 28: print ("Unsupported number of services") count = 4 # For creating SID array - nsacl = "const int ns_allowed[32] = {" - policy = "const int strict_policy[32] = {" - qcode = "const char * psa_queues[] = { " - versions = "const uint32_t versions[32] = {" - queue_path = "/tmp/psa_service_" + nsacl = "const int ns_allowed[32] = { " + policy = "const int strict_policy[32] = { " + qcode = "const char *psa_queues[] = { " + versions = "const uint32_t versions[32] = { " + queue_path = "psa_service_" start = False for x in range(0, count): qcode = qcode + "\"\", " - nsacl = nsacl + " 0," - policy = policy + "0," - versions = versions + " 0," + nsacl = nsacl + "0, " + policy = policy + "0, " + versions = versions + "0, " # Go through all the services to make sid.h and pid.h for svc in services: - man.write("#define " + str(svc['signal']) + "_SIGNAL " + str(2 ** (count)) + 'u\n') - sids.write("#define " + str(svc['name']) + "_SID " + str(svc['sid'] + '\n')) + manifest_content.append("#define {}_SIGNAL 0x{:08x}".format(svc['signal'], 2**count)) + sids_content.append("#define {}_SID {}".format(svc['name'], svc['sid'])) qcode = qcode + "\"" + queue_path + str(int(svc['sid'], 16)) + "\"," ns_clients = svc['non_secure_clients'] print(str(svc)) if ns_clients == "true": - nsacl = nsacl + " 1," + nsacl = nsacl + "1, " else: - nsacl = nsacl + " 0," + nsacl = nsacl + "0, " try: - versions = versions + str(svc['minor_version']) + "," + versions = versions + str(svc['minor_version']) + ", " except KeyError: - versions = versions + "1," + versions = versions + "1, " strict = 0 try: if str(svc['minor_policy']).lower() == "strict": strict = 1 - policy = policy + "1," + policy = policy + "1, " else: - policy = policy + "0," + policy = policy + "0, " except KeyError: strict = 0 - policy = policy + "0," + policy = policy + "0, " count = count+1 @@ -91,18 +98,19 @@ handlercode = "void __sig_handler(int signo) {\n" irqcount = count for irq in irqs: - man.write("#define " + str(irq['signal']) + " " + str(2 ** (irqcount)) + 'u\n') - sigcode = sigcode + " signal(" + str(irq['source']) + ", __sig_handler);\n" - handlercode = handlercode + " if (signo == " + str(irq['source']) + ") { raise_signal(" + str(2 ** (irqcount)) + 'u);' + " };\n" + manifest_content.append("#define {} 0x{:08x}".format(irq['signal'], 2**irqcount)) + sigcode = sigcode + " signal({}, __sig_handler);\n".format(irq['source']) + handlercode = handlercode + \ + " if (signo == {}) {{ raise_signal(0x{:08x}); }};\n".format(irq['source'], 2**irqcount) irqcount = irqcount+1 handlercode = handlercode + "}\n" while (count < 32): - qcode = qcode + "\"\"," - nsacl = nsacl + "0," - versions = versions + "0," - policy = policy + "0," + qcode = qcode + "\"\", " + nsacl = nsacl + "0, " + versions = versions + "0, " + policy = policy + "0, " count = count + 1 qcode = qcode + "};\n" @@ -110,28 +118,28 @@ versions = versions + "};\n" policy = policy + "};\n" - pids.close() - sids.close() - man.close() + with open(MANIFEST_FILE, "wt") as output: + output.write("\n".join(manifest_content)) + with open(SID_FILE, "wt") as output: + output.write("\n".join(sids_content)) + with open(PID_FILE, "wt") as output: + output.write("\n".join(pids_content)) symbols = [] - # Go through all the files in the current directory and look for the entrypoint - for root, directories, filenames in os.walk('.'): + # Go through source files and look for the entrypoint + for root, directories, filenames in os.walk(GENERATED_C_PATH): for filename in filenames: - if "psa_ff_bootstrap" in filename or filename == "psa_manifest": continue - try: fullpath = os.path.join(root,filename) with open(fullpath, encoding='utf-8') as currentFile: text = currentFile.read() if str(entry_point + "(") in text: - symbols.append(fullpath) + symbols.append(filename) except IOError: print("Couldn't open " + filename) - except UnicodeDecodeError: pass @@ -143,21 +151,24 @@ print("Duplicate entrypoint symbol detected: " + str(symbols)) sys.exit(2) else: - bs = open(str("psa_ff_bootstrap_" + str(partition_name) + ".c"), "w") - bs.write("#include \n") - bs.write("#include \"" + symbols[0] + "\"\n") - bs.write("#include \n") - bs.write(qcode) - bs.write("\n") - bs.write(nsacl + "\n") - bs.write(policy + "\n") - bs.write(versions + "\n") - bs.write(handlercode) - bs.write("\n") - bs.write("int main() {\n") - bs.write(sigcode) - bs.write(" __init_psasim(psa_queues, 32, ns_allowed, versions, strict_policy);\n") - bs.write(" " + entry_point + "();\nfor(;;);\n}\n") - bs.close() + C_FILENAME = os.path.join(GENERATED_C_PATH, "psa_ff_bootstrap_" + partition_name + ".c") + c_content = [] + c_content.append("#include ") + c_content.append("#include \"" + symbols[0] + "\"") + c_content.append("#include ") + c_content.append(qcode) + c_content.append(nsacl) + c_content.append(policy) + c_content.append(versions) + c_content.append(handlercode) + c_content.append("int main(int argc, char *argv[]) {") + c_content.append(" (void) argc;") + c_content.append(sigcode) + c_content.append(" __init_psasim(psa_queues, 32, ns_allowed, versions," + "strict_policy);") + c_content.append(" " + entry_point + "(argc, argv);") + c_content.append("}") + with open(C_FILENAME, "wt") as output: + output.write("\n".join(c_content)) print("Success") diff --git a/scripts/all-core.sh b/scripts/all-core.sh index a9070a8e20..50038c10a4 100644 --- a/scripts/all-core.sh +++ b/scripts/all-core.sh @@ -267,7 +267,7 @@ pre_initialize_variables () { # defined in this script whose name starts with "component_". ALL_COMPONENTS=$(compgen -A function component_ | sed 's/component_//') - PSASIM_PATH='tests/psa-client-server/psasim/' + PSASIM_PATH='framework/psasim/' # Delay determining SUPPORTED_COMPONENTS until the command line options have a chance to override # the commands set by the environment