diff --git a/tests/psa-client-server/psasim/Makefile b/tests/psa-client-server/psasim/Makefile index a7e22e131e..4b0c46e47c 100644 --- a/tests/psa-client-server/psasim/Makefile +++ b/tests/psa-client-server/psasim/Makefile @@ -1,5 +1,3 @@ -MAIN ?= src/client.c - CFLAGS += -Wall -Werror -std=c99 -D_XOPEN_SOURCE=1 -D_POSIX_C_SOURCE=200809L ifeq ($(DEBUG),1) @@ -16,11 +14,15 @@ GENERATED_H_FILES = include/psa_manifest/manifest.h \ include/psa_manifest/pid.h \ include/psa_manifest/sid.h -PSA_CLIENT_SRC = src/psa_ff_client.c \ - $(MAIN) \ +PSA_CLIENT_COMMON_SRC = src/psa_ff_client.c \ src/psa_sim_crypto_client.c \ src/psa_sim_serialise.c +PSA_CLIENT_BASE_SRC = $(PSA_CLIENT_COMMON_SRC) src/client.c + +PSA_CLIENT_FULL_SRC = $(PSA_CLIENT_COMMON_SRC) \ + $(wildcard src/aut_*.c) + PARTITION_SERVER_BOOTSTRAP = src/psa_ff_bootstrap_TEST_PARTITION.c PSA_SERVER_SRC = $(PARTITION_SERVER_BOOTSTRAP) \ @@ -35,8 +37,11 @@ all: test/seedfile: dd if=/dev/urandom of=./test/seedfile bs=64 count=1 -test/psa_client: $(PSA_CLIENT_SRC) $(GENERATED_H_FILES) - $(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_SRC) $(LIBPSACLIENT) $(LDFLAGS) -o $@ +test/psa_client_base: $(PSA_CLIENT_BASE_SRC) $(GENERATED_H_FILES) + $(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_BASE_SRC) $(LIBPSACLIENT) $(LDFLAGS) -o $@ + +test/psa_client_full: $(PSA_CLIENT_FULL_SRC) $(GENERATED_H_FILES) + $(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_FULL_SRC) $(LIBPSACLIENT) $(LDFLAGS) -o $@ test/psa_partition: $(PSA_SERVER_SRC) $(GENERATED_H_FILES) test/seedfile $(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_SERVER_SRC) $(LIBPSASERVER) $(LDFLAGS) -o $@ @@ -56,7 +61,7 @@ libpsaclient libpsaserver: $(MAKE) -C $(MBEDTLS_ROOT_PATH) clean clean: - rm -f test/psa_client test/psa_partition + rm -f test/psa_client_base test/psa_client_full test/psa_partition rm -f $(PARTITION_SERVER_BOOTSTRAP) rm -rf libpsaclient libpsaserver rm -rf include/psa_manifest diff --git a/tests/psa-client-server/psasim/src/aut_main.c b/tests/psa-client-server/psasim/src/aut_main.c new file mode 100644 index 0000000000..ed198790c6 --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_main.c @@ -0,0 +1,71 @@ +/** + * This is the base AUT that exectues all other AUTs meant to test PSA APIs + * through PSASIM. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +/* First include Mbed TLS headers to get the Mbed TLS configuration and + * platform definitions that we'll use in this program. Also include + * standard C headers for functions we'll use here. */ +#include "mbedtls/build_info.h" + +#include "psa/crypto.h" + +#include +#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/tests/psa-client-server/psasim/src/aut_psa_aead_demo.c b/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt.c similarity index 76% rename from tests/psa-client-server/psasim/src/aut_psa_aead_demo.c rename to tests/psa-client-server/psasim/src/aut_psa_aead_encrypt.c index 4a46c4039c..64463f57fc 100644 --- a/tests/psa-client-server/psasim/src/aut_psa_aead_demo.c +++ b/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt.c @@ -1,37 +1,8 @@ -/** - * PSA API multi-part AEAD demonstration. - * - * This program AEAD-encrypts a message, using the algorithm and key size - * specified on the command line, using the multi-part API. - * - * It comes with a companion program cipher/cipher_aead_demo.c, which does the - * same operations with the legacy Cipher API. The goal is that comparing the - * two programs will help people migrating to the PSA Crypto API. - * - * When used with multi-part AEAD operations, the `mbedtls_cipher_context` - * serves a triple purpose (1) hold the key, (2) store the algorithm when no - * operation is active, and (3) save progress information for the current - * operation. With PSA those roles are held by disinct objects: (1) a - * psa_key_id_t to hold the key, a (2) psa_algorithm_t to represent the - * algorithm, and (3) a psa_operation_t for multi-part progress. - * - * On the other hand, with PSA, the algorithms encodes the desired tag length; - * with Cipher the desired tag length needs to be tracked separately. - * - * This program and its companion cipher/cipher_aead_demo.c illustrate this by - * doing the same sequence of multi-part AEAD computation with both APIs; - * looking at the two side by side should make the differences and - * similarities clear. - */ - /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ -/* First include Mbed TLS headers to get the Mbed TLS configuration and - * platform definitions that we'll use in this program. Also include - * standard C headers for functions we'll use here. */ #include "mbedtls/build_info.h" #include "psa/crypto.h" @@ -40,25 +11,6 @@ #include #include -/* If the build options we need are not enabled, compile a placeholder. */ -#if !defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \ - (!defined(MBEDTLS_PSA_CRYPTO_C) || \ - !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_GCM_C) || \ - !defined(MBEDTLS_CHACHAPOLY_C) || \ - defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)) -int main(void) -{ - printf("MBEDTLS_PSA_CRYPTO_CLIENT or " - "MBEDTLS_PSA_CRYPTO_C and/or " - "MBEDTLS_AES_C and/or MBEDTLS_GCM_C and/or " - "MBEDTLS_CHACHAPOLY_C not defined, and/or " - "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined\r\n"); - return 0; -} -#else - -/* The real program starts here. */ - const char usage[] = "Usage: aead_demo [aes128-gcm|aes256-gcm|aes128-gcm_8|chachapoly]"; @@ -257,21 +209,15 @@ exit: /* * Main function */ -int main(int argc, char **argv) +int psa_aead_encrypt_main(char *cipher_name) { psa_status_t status = PSA_SUCCESS; - /* Check usage */ - if (argc != 2) { - puts(usage); - return EXIT_FAILURE; - } - /* Initialize the PSA crypto library. */ PSA_CHECK(psa_crypto_init()); /* Run the demo */ - PSA_CHECK(aead_demo(argv[1])); + PSA_CHECK(aead_demo(cipher_name)); /* Deinitialize the PSA crypto library. */ mbedtls_psa_crypto_free(); @@ -279,5 +225,3 @@ int main(int argc, char **argv) exit: return status == PSA_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE; } - -#endif diff --git a/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt_decrypt.c b/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt_decrypt.c new file mode 100644 index 0000000000..ca090ccc66 --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_psa_aead_encrypt_decrypt.c @@ -0,0 +1,109 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#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!"; + const uint8_t key_bytes[32] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + uint8_t nonce[PSA_AEAD_NONCE_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CCM)]; + size_t nonce_length = sizeof(nonce); + size_t ciphertext_length; + size_t plaintext_length; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_CCM); + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, 256); + + status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id); + if (status != PSA_SUCCESS) { + printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + status = psa_generate_random(nonce, nonce_length); + if (status != PSA_SUCCESS) { + printf("psa_generate_random failed\n"); + return EXIT_FAILURE; + } + + status = psa_aead_encrypt(key_id, // key + PSA_ALG_CCM, // algorithm + nonce, nonce_length, // nonce + NULL, 0, // additional data + plaintext, sizeof(plaintext), // plaintext + encrypt, sizeof(encrypt), // ciphertext + &ciphertext_length); // length of output + if (status != PSA_SUCCESS) { + printf("psa_aead_encrypt failed\n"); + return EXIT_FAILURE; + } + + printf("AES-CCM encryption:\n"); + printf("- Plaintext: '%s':\n", plaintext); + printf("- Key: "); + print_bytestr(key_bytes, sizeof(key_bytes)); + printf("\n- Nonce: "); + print_bytestr(nonce, nonce_length); + printf("\n- No additional data\n"); + printf("- Ciphertext:\n"); + + for (size_t j = 0; j < ciphertext_length; j++) { + if (j % 8 == 0) { + printf("\n "); + } + printf("%02x ", encrypt[j]); + } + + printf("\n"); + + status = psa_aead_decrypt(key_id, // key + PSA_ALG_CCM, // algorithm + nonce, nonce_length, // nonce + NULL, 0, // additional data + encrypt, ciphertext_length, // ciphertext + decrypt, sizeof(decrypt), // plaintext + &plaintext_length); // length of output + if (status != PSA_SUCCESS) { + printf("psa_aead_decrypt failed\n"); + return EXIT_FAILURE; + } + + if (memcmp(plaintext, decrypt, sizeof(plaintext)) != 0) { + printf("\nEncryption/Decryption failed!\n"); + } else { + printf("\nEncryption/Decryption successful!\n"); + } + + psa_destroy_key(key_id); + mbedtls_psa_crypto_free(); + return 0; +} diff --git a/tests/psa-client-server/psasim/src/aut_psa_asymmetric_encrypt_decrypt.c b/tests/psa-client-server/psasim/src/aut_psa_asymmetric_encrypt_decrypt.c new file mode 100644 index 0000000000..02d8cf486d --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_psa_asymmetric_encrypt_decrypt.c @@ -0,0 +1,81 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#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/tests/psa-client-server/psasim/src/aut_psa_cipher_encrypt_decrypt.c b/tests/psa-client-server/psasim/src/aut_psa_cipher_encrypt_decrypt.c new file mode 100644 index 0000000000..a923feb618 --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_psa_cipher_encrypt_decrypt.c @@ -0,0 +1,81 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#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 }; + const uint8_t key_bytes[32] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + size_t encrypted_length; + size_t decrypted_length; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + status = psa_generate_random(original, sizeof(original)); + if (status != PSA_SUCCESS) { + printf("psa_generate_random() failed\n"); + return EXIT_FAILURE; + } + + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING); + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, 256); + + status = psa_import_key(&attributes, key_bytes, sizeof(key_bytes), &key_id); + if (status != PSA_SUCCESS) { + printf("psa_import_key failed\n"); + return EXIT_FAILURE; + } + + status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, + original, sizeof(original), + encrypt, sizeof(encrypt), &encrypted_length); + if (status != PSA_SUCCESS) { + printf("psa_cipher_encrypt failed\n"); + return EXIT_FAILURE; + } + + status = psa_cipher_decrypt(key_id, PSA_ALG_ECB_NO_PADDING, + encrypt, encrypted_length, + decrypt, sizeof(decrypt), &decrypted_length); + if (status != PSA_SUCCESS) { + printf("psa_cipher_decrypt failed\n"); + return EXIT_FAILURE; + } + + if (memcmp(original, decrypt, sizeof(original)) != 0) { + printf("\nEncryption/Decryption failed!\n"); + } else { + printf("\nEncryption/Decryption successful!\n"); + } + + psa_destroy_key(key_id); + mbedtls_psa_crypto_free(); + return 0; +} diff --git a/tests/psa-client-server/psasim/src/aut_psa_hash.c b/tests/psa-client-server/psasim/src/aut_psa_hash.c index 6c2c07e062..0446e7a76a 100644 --- a/tests/psa-client-server/psasim/src/aut_psa_hash.c +++ b/tests/psa-client-server/psasim/src/aut_psa_hash.c @@ -1,13 +1,4 @@ /* - * Example computing a SHA-256 hash using the PSA Crypto API - * - * The example computes the SHA-256 hash of a test string using the - * one-shot API call psa_hash_compute() and the using multi-part - * operation, which requires psa_hash_setup(), psa_hash_update() and - * psa_hash_finish(). The multi-part operation is popular on embedded - * devices where a rolling hash needs to be computed. - * - * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ @@ -20,33 +11,13 @@ #include "mbedtls/build_info.h" #include "mbedtls/platform.h" -/* Information about hashing with the PSA API can be - * found here: - * https://arm-software.github.io/psa-api/crypto/1.1/api/ops/hashes.html - * - * The algorithm used by this demo is SHA 256. - * Please see include/psa/crypto_values.h to see the other - * algorithms that are supported by Mbed TLS. - * If you switch to a different algorithm you will need to update - * the hash data in the EXAMPLE_HASH_VALUE macro below. */ - -#if !defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \ - (!defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256)) -int main(void) -{ - mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256" - "not defined, and not MBEDTLS_PSA_CRYPTO_CLIENT.\r\n"); - return EXIT_SUCCESS; -} -#else - #define HASH_ALG PSA_ALG_SHA_256 -const uint8_t sample_message[] = "Hello World!"; +static const uint8_t sample_message[] = "Hello World!"; /* sample_message is terminated with a null byte which is not part of * the message itself so we make sure to subtract it in order to get * the message length. */ -const size_t sample_message_length = sizeof(sample_message) - 1; +static const size_t sample_message_length = sizeof(sample_message) - 1; #define EXPECTED_HASH_VALUE { \ 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \ @@ -54,10 +25,10 @@ const size_t sample_message_length = sizeof(sample_message) - 1; 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \ } -const uint8_t expected_hash[] = EXPECTED_HASH_VALUE; -const size_t expected_hash_len = sizeof(expected_hash); +static const uint8_t expected_hash[] = EXPECTED_HASH_VALUE; +static const size_t expected_hash_len = sizeof(expected_hash); -int main(void) +int psa_hash_main(void) { psa_status_t status; uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)]; @@ -157,4 +128,3 @@ cleanup: psa_hash_abort(&cloned_hash_operation); return EXIT_FAILURE; } -#endif /* !MBEDTLS_PSA_CRYPTO_C || !PSA_WANT_ALG_SHA_256 */ diff --git a/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c b/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c index 70c3e5be4f..959e0c38ab 100644 --- a/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c +++ b/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c @@ -1,15 +1,4 @@ /* - * API(s) under test: psa_hash_compute() - * - * Taken from programs/psa/psa_hash.c, and calls to all hash APIs - * but psa_hash_compute() removed. - * - * Example computing a SHA-256 hash using the PSA Crypto API - * - * The example computes the SHA-256 hash of a test string using the - * one-shot API call psa_hash_compute(). - * - * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ @@ -22,33 +11,13 @@ #include "mbedtls/build_info.h" #include "mbedtls/platform.h" -/* Information about hashing with the PSA API can be - * found here: - * https://arm-software.github.io/psa-api/crypto/1.1/api/ops/hashes.html - * - * The algorithm used by this demo is SHA 256. - * Please see include/psa/crypto_values.h to see the other - * algorithms that are supported by Mbed TLS. - * If you switch to a different algorithm you will need to update - * the hash data in the EXAMPLE_HASH_VALUE macro below. */ - -#if !defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \ - (!defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256)) -int main(void) -{ - mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256" - "not defined, and not MBEDTLS_PSA_CRYPTO_CLIENT.\r\n"); - return EXIT_SUCCESS; -} -#else - #define HASH_ALG PSA_ALG_SHA_256 -const uint8_t sample_message[] = "Hello World!"; +static const uint8_t sample_message[] = "Hello World!"; /* sample_message is terminated with a null byte which is not part of * the message itself so we make sure to subtract it in order to get * the message length. */ -const size_t sample_message_length = sizeof(sample_message) - 1; +static const size_t sample_message_length = sizeof(sample_message) - 1; #define EXPECTED_HASH_VALUE { \ 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \ @@ -56,10 +25,10 @@ const size_t sample_message_length = sizeof(sample_message) - 1; 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \ } -const uint8_t expected_hash[] = EXPECTED_HASH_VALUE; -const size_t expected_hash_len = sizeof(expected_hash); +static const uint8_t expected_hash[] = EXPECTED_HASH_VALUE; +static const size_t expected_hash_len = sizeof(expected_hash); -int main(void) +int psa_hash_compute_main(void) { psa_status_t status; uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)]; @@ -110,4 +79,3 @@ int main(void) cleanup: return EXIT_FAILURE; } -#endif /* !MBEDTLS_PSA_CRYPTO_C || !PSA_WANT_ALG_SHA_256 */ diff --git a/tests/psa-client-server/psasim/src/aut_psa_hkdf.c b/tests/psa-client-server/psasim/src/aut_psa_hkdf.c new file mode 100644 index 0000000000..891fdb3f92 --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_psa_hkdf.c @@ -0,0 +1,121 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#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/tests/psa-client-server/psasim/src/aut_psa_key_agreement.c b/tests/psa-client-server/psasim/src/aut_psa_key_agreement.c new file mode 100644 index 0000000000..4a0aab1477 --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_psa_key_agreement.c @@ -0,0 +1,146 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + + +#include "psa/crypto.h" +#include +#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/tests/psa-client-server/psasim/src/aut_psa_mac.c b/tests/psa-client-server/psasim/src/aut_psa_mac.c new file mode 100644 index 0000000000..18b4b571a3 --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_psa_mac.c @@ -0,0 +1,162 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "psa/crypto.h" +#include +#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/tests/psa-client-server/psasim/src/aut_psa_random.c b/tests/psa-client-server/psasim/src/aut_psa_random.c new file mode 100644 index 0000000000..5880c4deb9 --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_psa_random.c @@ -0,0 +1,47 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include "mbedtls/build_info.h" + +#include +#include +#include +#include + +#include "mbedtls/entropy.h" + +#define BUFFER_SIZE 100 + +int psa_random_main(void) +{ + psa_status_t status; + uint8_t output[BUFFER_SIZE] = { 0 }; + + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + printf("psa_crypto_init failed\n"); + return EXIT_FAILURE; + } + + status = psa_generate_random(output, BUFFER_SIZE); + if (status != PSA_SUCCESS) { + printf("psa_generate_random failed\n"); + return EXIT_FAILURE; + } + + printf("Random bytes generated:\n"); + + for (size_t j = 0; j < BUFFER_SIZE; j++) { + if (j % 8 == 0) { + printf("\n "); + } + printf("%02x ", output[j]); + } + + printf("\n"); + + mbedtls_psa_crypto_free(); + return 0; +} diff --git a/tests/psa-client-server/psasim/src/aut_psa_sign_verify.c b/tests/psa-client-server/psasim/src/aut_psa_sign_verify.c new file mode 100644 index 0000000000..98df9e5162 --- /dev/null +++ b/tests/psa-client-server/psasim/src/aut_psa_sign_verify.c @@ -0,0 +1,93 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + + +#include "psa/crypto.h" +#include +#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/tests/psa-client-server/psasim/src/psa_functions_codes.h b/tests/psa-client-server/psasim/src/psa_functions_codes.h index c68b416096..bc1b84442a 100644 --- a/tests/psa-client-server/psasim/src/psa_functions_codes.h +++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h @@ -24,7 +24,24 @@ enum { PSA_AEAD_UPDATE, PSA_AEAD_UPDATE_AD, PSA_AEAD_VERIFY, + PSA_ASYMMETRIC_DECRYPT, + PSA_ASYMMETRIC_ENCRYPT, + PSA_CIPHER_ABORT, + PSA_CIPHER_DECRYPT, + PSA_CIPHER_DECRYPT_SETUP, + PSA_CIPHER_ENCRYPT, + PSA_CIPHER_ENCRYPT_SETUP, + PSA_CIPHER_FINISH, + PSA_CIPHER_GENERATE_IV, + PSA_CIPHER_SET_IV, + PSA_CIPHER_UPDATE, + PSA_COPY_KEY, PSA_DESTROY_KEY, + PSA_EXPORT_KEY, + PSA_EXPORT_PUBLIC_KEY, + PSA_GENERATE_KEY, + PSA_GENERATE_KEY_EXT, + PSA_GENERATE_RANDOM, PSA_GET_KEY_ATTRIBUTES, PSA_HASH_ABORT, PSA_HASH_CLONE, @@ -35,6 +52,42 @@ enum { PSA_HASH_UPDATE, PSA_HASH_VERIFY, PSA_IMPORT_KEY, + PSA_INTERRUPTIBLE_GET_MAX_OPS, + PSA_INTERRUPTIBLE_SET_MAX_OPS, + PSA_KEY_DERIVATION_ABORT, + PSA_KEY_DERIVATION_GET_CAPACITY, + PSA_KEY_DERIVATION_INPUT_BYTES, + PSA_KEY_DERIVATION_INPUT_INTEGER, + PSA_KEY_DERIVATION_INPUT_KEY, + PSA_KEY_DERIVATION_KEY_AGREEMENT, + PSA_KEY_DERIVATION_OUTPUT_BYTES, + PSA_KEY_DERIVATION_OUTPUT_KEY, + PSA_KEY_DERIVATION_OUTPUT_KEY_EXT, + PSA_KEY_DERIVATION_SET_CAPACITY, + PSA_KEY_DERIVATION_SETUP, + PSA_MAC_ABORT, + PSA_MAC_COMPUTE, + PSA_MAC_SIGN_FINISH, + PSA_MAC_SIGN_SETUP, + PSA_MAC_UPDATE, + PSA_MAC_VERIFY, + PSA_MAC_VERIFY_FINISH, + PSA_MAC_VERIFY_SETUP, + PSA_PURGE_KEY, + PSA_RAW_KEY_AGREEMENT, + PSA_RESET_KEY_ATTRIBUTES, + PSA_SIGN_HASH, + PSA_SIGN_HASH_ABORT, + PSA_SIGN_HASH_COMPLETE, + PSA_SIGN_HASH_GET_NUM_OPS, + PSA_SIGN_HASH_START, + PSA_SIGN_MESSAGE, + PSA_VERIFY_HASH, + PSA_VERIFY_HASH_ABORT, + PSA_VERIFY_HASH_COMPLETE, + PSA_VERIFY_HASH_GET_NUM_OPS, + PSA_VERIFY_HASH_START, + PSA_VERIFY_MESSAGE, }; #endif /* _PSA_FUNCTIONS_CODES_H_ */ diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c index 758e9b2ec6..28dff38d02 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c +++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c @@ -129,40 +129,43 @@ psa_status_t psa_aead_abort( psa_aead_operation_t *operation ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_ABORT, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_ABORT server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -170,19 +173,23 @@ psa_status_t psa_aead_abort( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -198,70 +205,85 @@ psa_status_t psa_aead_decrypt( size_t *plaintext_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_mbedtls_svc_key_id_t_needs(key) + - psasim_serialise_psa_algorithm_t_needs(alg) + - psasim_serialise_buffer_needs(nonce, nonce_length) + - psasim_serialise_buffer_needs(additional_data, additional_data_length) + - psasim_serialise_buffer_needs(ciphertext, ciphertext_length) + - psasim_serialise_buffer_needs(plaintext, plaintext_size) + - psasim_serialise_size_t_needs(*plaintext_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(nonce, nonce_length) + + psasim_serialise_buffer_needs(additional_data, additional_data_length) + + psasim_serialise_buffer_needs(ciphertext, ciphertext_length) + + psasim_serialise_buffer_needs(plaintext, plaintext_size) + + psasim_serialise_size_t_needs(*plaintext_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); if (!ok) { goto fail; } - ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, nonce, nonce_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + nonce, nonce_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, additional_data, additional_data_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + additional_data, additional_data_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, ciphertext, ciphertext_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + ciphertext, ciphertext_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, plaintext, plaintext_size); + ok = psasim_serialise_buffer( + &pos, &remaining, + plaintext, plaintext_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, *plaintext_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + *plaintext_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_DECRYPT, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_DECRYPT server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -269,24 +291,30 @@ psa_status_t psa_aead_decrypt( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_return_buffer(&rpos, &rremain, plaintext, plaintext_size); + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + plaintext, plaintext_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&rpos, &rremain, plaintext_length); + ok = psasim_deserialise_size_t( + &rpos, &rremain, + plaintext_length); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -298,50 +326,57 @@ psa_status_t psa_aead_decrypt_setup( psa_algorithm_t alg ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation) + - psasim_serialise_mbedtls_svc_key_id_t_needs(key) + - psasim_serialise_psa_algorithm_t_needs(alg); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); if (!ok) { goto fail; } - ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_DECRYPT_SETUP, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_DECRYPT_SETUP server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -349,19 +384,23 @@ psa_status_t psa_aead_decrypt_setup( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -377,70 +416,85 @@ psa_status_t psa_aead_encrypt( size_t *ciphertext_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_mbedtls_svc_key_id_t_needs(key) + - psasim_serialise_psa_algorithm_t_needs(alg) + - psasim_serialise_buffer_needs(nonce, nonce_length) + - psasim_serialise_buffer_needs(additional_data, additional_data_length) + - psasim_serialise_buffer_needs(plaintext, plaintext_length) + - psasim_serialise_buffer_needs(ciphertext, ciphertext_size) + - psasim_serialise_size_t_needs(*ciphertext_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(nonce, nonce_length) + + psasim_serialise_buffer_needs(additional_data, additional_data_length) + + psasim_serialise_buffer_needs(plaintext, plaintext_length) + + psasim_serialise_buffer_needs(ciphertext, ciphertext_size) + + psasim_serialise_size_t_needs(*ciphertext_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); if (!ok) { goto fail; } - ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, nonce, nonce_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + nonce, nonce_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, additional_data, additional_data_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + additional_data, additional_data_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, plaintext, plaintext_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + plaintext, plaintext_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, ciphertext, ciphertext_size); + ok = psasim_serialise_buffer( + &pos, &remaining, + ciphertext, ciphertext_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, *ciphertext_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + *ciphertext_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_ENCRYPT, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_ENCRYPT server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -448,24 +502,30 @@ psa_status_t psa_aead_encrypt( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_return_buffer(&rpos, &rremain, ciphertext, ciphertext_size); + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + ciphertext, ciphertext_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&rpos, &rremain, ciphertext_length); + ok = psasim_deserialise_size_t( + &rpos, &rremain, + ciphertext_length); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -477,50 +537,57 @@ psa_status_t psa_aead_encrypt_setup( psa_algorithm_t alg ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation) + - psasim_serialise_mbedtls_svc_key_id_t_needs(key) + - psasim_serialise_psa_algorithm_t_needs(alg); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); if (!ok) { goto fail; } - ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_ENCRYPT_SETUP, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_ENCRYPT_SETUP server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -528,19 +595,23 @@ psa_status_t psa_aead_encrypt_setup( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -554,60 +625,71 @@ psa_status_t psa_aead_finish( size_t *tag_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation) + - psasim_serialise_buffer_needs(ciphertext, ciphertext_size) + - psasim_serialise_size_t_needs(*ciphertext_length) + - psasim_serialise_buffer_needs(tag, tag_size) + - psasim_serialise_size_t_needs(*tag_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(ciphertext, ciphertext_size) + + psasim_serialise_size_t_needs(*ciphertext_length) + + psasim_serialise_buffer_needs(tag, tag_size) + + psasim_serialise_size_t_needs(*tag_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, ciphertext, ciphertext_size); + ok = psasim_serialise_buffer( + &pos, &remaining, + ciphertext, ciphertext_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, *ciphertext_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + *ciphertext_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, tag, tag_size); + ok = psasim_serialise_buffer( + &pos, &remaining, + tag, tag_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, *tag_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + *tag_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_FINISH, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_FINISH server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -615,39 +697,51 @@ psa_status_t psa_aead_finish( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_deserialise_return_buffer(&rpos, &rremain, ciphertext, ciphertext_size); + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + ciphertext, ciphertext_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&rpos, &rremain, ciphertext_length); + ok = psasim_deserialise_size_t( + &rpos, &rremain, + ciphertext_length); if (!ok) { goto fail; } - ok = psasim_deserialise_return_buffer(&rpos, &rremain, tag, tag_size); + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + tag, tag_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&rpos, &rremain, tag_length); + ok = psasim_deserialise_size_t( + &rpos, &rremain, + tag_length); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -659,50 +753,57 @@ psa_status_t psa_aead_generate_nonce( size_t *nonce_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation) + - psasim_serialise_buffer_needs(nonce, nonce_size) + - psasim_serialise_size_t_needs(*nonce_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(nonce, nonce_size) + + psasim_serialise_size_t_needs(*nonce_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, nonce, nonce_size); + ok = psasim_serialise_buffer( + &pos, &remaining, + nonce, nonce_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, *nonce_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + *nonce_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_GENERATE_NONCE, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_GENERATE_NONCE server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -710,29 +811,37 @@ psa_status_t psa_aead_generate_nonce( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_deserialise_return_buffer(&rpos, &rremain, nonce, nonce_size); + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + nonce, nonce_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&rpos, &rremain, nonce_length); + ok = psasim_deserialise_size_t( + &rpos, &rremain, + nonce_length); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -744,50 +853,57 @@ psa_status_t psa_aead_set_lengths( size_t plaintext_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation) + - psasim_serialise_size_t_needs(ad_length) + - psasim_serialise_size_t_needs(plaintext_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_size_t_needs(ad_length) + + psasim_serialise_size_t_needs(plaintext_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, ad_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + ad_length); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, plaintext_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + plaintext_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_SET_LENGTHS, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_SET_LENGTHS server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -795,19 +911,23 @@ psa_status_t psa_aead_set_lengths( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -818,45 +938,50 @@ psa_status_t psa_aead_set_nonce( const uint8_t *nonce, size_t nonce_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation) + - psasim_serialise_buffer_needs(nonce, nonce_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(nonce, nonce_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, nonce, nonce_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + nonce, nonce_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_SET_NONCE, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_SET_NONCE server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -864,19 +989,23 @@ psa_status_t psa_aead_set_nonce( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -889,55 +1018,64 @@ psa_status_t psa_aead_update( size_t *output_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation) + - psasim_serialise_buffer_needs(input, input_length) + - psasim_serialise_buffer_needs(output, output_size) + - psasim_serialise_size_t_needs(*output_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, output, output_size); + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, *output_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_UPDATE, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_UPDATE server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -945,29 +1083,37 @@ psa_status_t psa_aead_update( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_deserialise_return_buffer(&rpos, &rremain, output, output_size); + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&rpos, &rremain, output_length); + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -978,45 +1124,50 @@ psa_status_t psa_aead_update_ad( const uint8_t *input, size_t input_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation) + - psasim_serialise_buffer_needs(input, input_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_UPDATE_AD, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_UPDATE_AD server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1024,19 +1175,23 @@ psa_status_t psa_aead_update_ad( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1049,55 +1204,64 @@ psa_status_t psa_aead_verify( const uint8_t *tag, size_t tag_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_aead_operation_t_needs(*operation) + - psasim_serialise_buffer_needs(plaintext, plaintext_size) + - psasim_serialise_size_t_needs(*plaintext_length) + - psasim_serialise_buffer_needs(tag, tag_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_aead_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(plaintext, plaintext_size) + + psasim_serialise_size_t_needs(*plaintext_length) + + psasim_serialise_buffer_needs(tag, tag_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_aead_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_aead_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, plaintext, plaintext_size); + ok = psasim_serialise_buffer( + &pos, &remaining, + plaintext, plaintext_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, *plaintext_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + *plaintext_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, tag, tag_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + tag, tag_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_AEAD_VERIFY, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_AEAD_VERIFY server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1105,29 +1269,1203 @@ psa_status_t psa_aead_verify( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_deserialise_return_buffer(&rpos, &rremain, plaintext, plaintext_size); + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + plaintext, plaintext_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&rpos, &rremain, plaintext_length); + ok = psasim_deserialise_size_t( + &rpos, &rremain, + plaintext_length); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_asymmetric_decrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *salt, size_t salt_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(salt, salt_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + salt, salt_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_ASYMMETRIC_DECRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_ASYMMETRIC_DECRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_asymmetric_encrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *salt, size_t salt_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(salt, salt_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + salt, salt_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_ASYMMETRIC_ENCRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_ASYMMETRIC_ENCRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_abort( + psa_cipher_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_decrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_DECRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_DECRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_decrypt_setup( + psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_DECRYPT_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_DECRYPT_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_encrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_ENCRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_ENCRYPT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_encrypt_setup( + psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_ENCRYPT_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_ENCRYPT_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_finish( + psa_cipher_operation_t *operation, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_FINISH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_generate_iv( + psa_cipher_operation_t *operation, + uint8_t *iv, size_t iv_size, + size_t *iv_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(iv, iv_size) + + psasim_serialise_size_t_needs(*iv_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + iv, iv_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *iv_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_GENERATE_IV, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_GENERATE_IV server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + iv, iv_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + iv_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_set_iv( + psa_cipher_operation_t *operation, + const uint8_t *iv, size_t iv_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(iv, iv_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + iv, iv_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_SET_IV, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_SET_IV server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_cipher_update( + psa_cipher_operation_t *operation, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_cipher_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_cipher_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_CIPHER_UPDATE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_CIPHER_UPDATE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_copy_key( + mbedtls_svc_key_id_t source_key, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *target_key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(source_key) + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*target_key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + source_key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *target_key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_COPY_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_COPY_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + target_key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); return status; } @@ -1137,40 +2475,43 @@ psa_status_t psa_destroy_key( mbedtls_svc_key_id_t key ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_mbedtls_svc_key_id_t_needs(key); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_DESTROY_KEY, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_DESTROY_KEY server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1178,14 +2519,436 @@ psa_status_t psa_destroy_key( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_export_key( + mbedtls_svc_key_id_t key, + uint8_t *data, size_t data_size, + size_t *data_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_buffer_needs(data, data_size) + + psasim_serialise_size_t_needs(*data_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + data, data_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *data_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_EXPORT_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_EXPORT_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + data, data_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + data_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_export_public_key( + mbedtls_svc_key_id_t key, + uint8_t *data, size_t data_size, + size_t *data_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_buffer_needs(data, data_size) + + psasim_serialise_size_t_needs(*data_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + data, data_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *data_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_EXPORT_PUBLIC_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_EXPORT_PUBLIC_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + data, data_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + data_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_generate_key( + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_generate_key_ext( + const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, size_t params_data_length, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_psa_key_production_parameters_t_needs(params, params_data_length) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_production_parameters_t( + &pos, &remaining, + params, params_data_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY_EXT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY_EXT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_generate_random( + uint8_t *output, size_t output_size + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_buffer_needs(output, output_size); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_RANDOM, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_RANDOM server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); return status; } @@ -1196,45 +2959,50 @@ psa_status_t psa_get_key_attributes( psa_key_attributes_t *attributes ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_mbedtls_svc_key_id_t_needs(key) + - psasim_serialise_psa_key_attributes_t_needs(*attributes); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_key_attributes_t_needs(*attributes); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, key); + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); if (!ok) { goto fail; } - ok = psasim_serialise_psa_key_attributes_t(&pos, &remaining, *attributes); + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_GET_KEY_ATTRIBUTES, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_GET_KEY_ATTRIBUTES server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1242,19 +3010,23 @@ psa_status_t psa_get_key_attributes( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_key_attributes_t(&rpos, &rremain, attributes); + ok = psasim_deserialise_psa_key_attributes_t( + &rpos, &rremain, + attributes); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1264,40 +3036,43 @@ psa_status_t psa_hash_abort( psa_hash_operation_t *operation ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_hash_operation_t_needs(*operation); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_HASH_ABORT, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_HASH_ABORT server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1305,19 +3080,23 @@ psa_status_t psa_hash_abort( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1328,45 +3107,50 @@ psa_status_t psa_hash_clone( psa_hash_operation_t *target_operation ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_hash_operation_t_needs(*source_operation) + - psasim_serialise_psa_hash_operation_t_needs(*target_operation); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*source_operation) + + psasim_serialise_psa_hash_operation_t_needs(*target_operation); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *source_operation); + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *source_operation); if (!ok) { goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *target_operation); + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *target_operation); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_HASH_CLONE, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_HASH_CLONE server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1374,19 +3158,23 @@ psa_status_t psa_hash_clone( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, target_operation); + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + target_operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1398,50 +3186,57 @@ psa_status_t psa_hash_compare( const uint8_t *hash, size_t hash_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_algorithm_t_needs(alg) + - psasim_serialise_buffer_needs(input, input_length) + - psasim_serialise_buffer_needs(hash, hash_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(hash, hash_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_HASH_COMPARE, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_HASH_COMPARE server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1449,14 +3244,16 @@ psa_status_t psa_hash_compare( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1469,55 +3266,64 @@ psa_status_t psa_hash_compute( size_t *hash_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_algorithm_t_needs(alg) + - psasim_serialise_buffer_needs(input, input_length) + - psasim_serialise_buffer_needs(hash, hash_size) + - psasim_serialise_size_t_needs(*hash_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(hash, hash_size) + + psasim_serialise_size_t_needs(*hash_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_size); + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, *hash_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + *hash_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_HASH_COMPUTE, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_HASH_COMPUTE server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1525,24 +3331,30 @@ psa_status_t psa_hash_compute( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_return_buffer(&rpos, &rremain, hash, hash_size); + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + hash, hash_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&rpos, &rremain, hash_length); + ok = psasim_deserialise_size_t( + &rpos, &rremain, + hash_length); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1554,50 +3366,57 @@ psa_status_t psa_hash_finish( size_t *hash_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_hash_operation_t_needs(*operation) + - psasim_serialise_buffer_needs(hash, hash_size) + - psasim_serialise_size_t_needs(*hash_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(hash, hash_size) + + psasim_serialise_size_t_needs(*hash_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_size); + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&pos, &remaining, *hash_length); + ok = psasim_serialise_size_t( + &pos, &remaining, + *hash_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_HASH_FINISH, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_HASH_FINISH server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1605,29 +3424,37 @@ psa_status_t psa_hash_finish( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_deserialise_return_buffer(&rpos, &rremain, hash, hash_size); + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + hash, hash_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&rpos, &rremain, hash_length); + ok = psasim_deserialise_size_t( + &rpos, &rremain, + hash_length); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1638,45 +3465,50 @@ psa_status_t psa_hash_setup( psa_algorithm_t alg ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_hash_operation_t_needs(*operation) + - psasim_serialise_psa_algorithm_t_needs(alg); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation) + + psasim_serialise_psa_algorithm_t_needs(alg); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_HASH_SETUP, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_HASH_SETUP server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1684,19 +3516,23 @@ psa_status_t psa_hash_setup( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1707,45 +3543,50 @@ psa_status_t psa_hash_update( const uint8_t *input, size_t input_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_hash_operation_t_needs(*operation) + - psasim_serialise_buffer_needs(input, input_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_HASH_UPDATE, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_HASH_UPDATE server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1753,19 +3594,23 @@ psa_status_t psa_hash_update( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1776,45 +3621,50 @@ psa_status_t psa_hash_verify( const uint8_t *hash, size_t hash_length ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_hash_operation_t_needs(*operation) + - psasim_serialise_buffer_needs(hash, hash_length); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_hash_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(hash, hash_length); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation); + ok = psasim_serialise_psa_hash_operation_t( + &pos, &remaining, + *operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_HASH_VERIFY, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_HASH_VERIFY server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1822,19 +3672,23 @@ psa_status_t psa_hash_verify( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_deserialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); return status; } @@ -1846,50 +3700,57 @@ psa_status_t psa_import_key( mbedtls_svc_key_id_t *key ) { - uint8_t *params = NULL; - uint8_t *result = NULL; + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; size_t result_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - size_t needed = psasim_serialise_begin_needs() + - psasim_serialise_psa_key_attributes_t_needs(*attributes) + - psasim_serialise_buffer_needs(data, data_length) + - psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_buffer_needs(data, data_length) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); - params = malloc(needed); - if (params == NULL) { + ser_params = malloc(needed); + if (ser_params == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto fail; } - uint8_t *pos = params; + uint8_t *pos = ser_params; size_t remaining = needed; int ok; ok = psasim_serialise_begin(&pos, &remaining); if (!ok) { goto fail; } - ok = psasim_serialise_psa_key_attributes_t(&pos, &remaining, *attributes); + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&pos, &remaining, data, data_length); + ok = psasim_serialise_buffer( + &pos, &remaining, + data, data_length); if (!ok) { goto fail; } - ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, *key); + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); if (!ok) { goto fail; } ok = psa_crypto_call(PSA_IMPORT_KEY, - params, (size_t) (pos - params), &result, &result_length); + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); if (!ok) { printf("PSA_IMPORT_KEY server call failed\n"); goto fail; } - uint8_t *rpos = result; + uint8_t *rpos = ser_result; size_t rremain = result_length; ok = psasim_deserialise_begin(&rpos, &rremain); @@ -1897,19 +3758,3016 @@ psa_status_t psa_import_key( goto fail; } - ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); if (!ok) { goto fail; } - ok = psasim_deserialise_mbedtls_svc_key_id_t(&rpos, &rremain, key); + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); if (!ok) { goto fail; } fail: - free(params); - free(result); + free(ser_params); + free(ser_result); + + return status; +} + + +uint32_t psa_interruptible_get_max_ops( + void + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + uint32_t value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + 0; + + ser_params = malloc(needed); + if (ser_params == NULL) { + value = 0; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_INTERRUPTIBLE_GET_MAX_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_INTERRUPTIBLE_GET_MAX_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +void psa_interruptible_set_max_ops( + uint32_t max_ops + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(max_ops); + + ser_params = malloc(needed); + if (ser_params == NULL) { + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_uint32_t( + &pos, &remaining, + max_ops); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_INTERRUPTIBLE_SET_MAX_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_INTERRUPTIBLE_SET_MAX_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); +} + + +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_size_t_needs(*capacity); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *capacity); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_GET_CAPACITY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_GET_CAPACITY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + capacity); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, size_t data_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_key_derivation_step_t_needs(step) + + psasim_serialise_buffer_needs(data, data_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_step_t( + &pos, &remaining, + step); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + data, data_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_INPUT_BYTES, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_INPUT_BYTES server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_input_integer( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_key_derivation_step_t_needs(step) + + psasim_serialise_uint64_t_needs(value); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_step_t( + &pos, &remaining, + step); + if (!ok) { + goto fail; + } + ok = psasim_serialise_uint64_t( + &pos, &remaining, + value); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_INPUT_INTEGER, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_INPUT_INTEGER server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_key_derivation_step_t_needs(step) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_step_t( + &pos, &remaining, + step); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_INPUT_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_INPUT_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, size_t peer_key_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_key_derivation_step_t_needs(step) + + psasim_serialise_mbedtls_svc_key_id_t_needs(private_key) + + psasim_serialise_buffer_needs(peer_key, peer_key_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_step_t( + &pos, &remaining, + step); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + private_key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + peer_key, peer_key_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_KEY_AGREEMENT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_KEY_AGREEMENT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, size_t output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(output, output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_OUTPUT_BYTES, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_OUTPUT_BYTES server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_OUTPUT_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_OUTPUT_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_output_key_ext( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + const psa_key_production_parameters_t *params, size_t params_data_length, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_key_production_parameters_t_needs(params, params_data_length) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_production_parameters_t( + &pos, &remaining, + params, params_data_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_OUTPUT_KEY_EXT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_OUTPUT_KEY_EXT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_size_t_needs(capacity); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + capacity); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_SET_CAPACITY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_SET_CAPACITY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_derivation_operation_t_needs(*operation) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_derivation_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_KEY_DERIVATION_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_KEY_DERIVATION_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_abort( + psa_mac_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_compute( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *mac, size_t mac_size, + size_t *mac_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(*mac_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + mac, mac_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_COMPUTE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_COMPUTE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + mac_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_sign_finish( + psa_mac_operation_t *operation, + uint8_t *mac, size_t mac_size, + size_t *mac_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(*mac_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + mac, mac_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_SIGN_FINISH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_SIGN_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + mac_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_sign_setup( + psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_SIGN_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_SIGN_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_update( + psa_mac_operation_t *operation, + const uint8_t *input, size_t input_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(input, input_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_UPDATE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_UPDATE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_verify( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *mac, size_t mac_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(mac, mac_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + mac, mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_VERIFY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_VERIFY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_verify_finish( + psa_mac_operation_t *operation, + const uint8_t *mac, size_t mac_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(mac, mac_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + mac, mac_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_VERIFY_FINISH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_VERIFY_FINISH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_mac_verify_setup( + psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_mac_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_mac_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_MAC_VERIFY_SETUP, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_MAC_VERIFY_SETUP server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_purge_key( + mbedtls_svc_key_id_t key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_PURGE_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_PURGE_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_raw_key_agreement( + psa_algorithm_t alg, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, size_t peer_key_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_mbedtls_svc_key_id_t_needs(private_key) + + psasim_serialise_buffer_needs(peer_key, peer_key_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + private_key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + peer_key, peer_key_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_RAW_KEY_AGREEMENT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_RAW_KEY_AGREEMENT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +void psa_reset_key_attributes( + psa_key_attributes_t *attributes + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes); + + ser_params = malloc(needed); + if (ser_params == NULL) { + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t( + &pos, &remaining, + *attributes); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_RESET_KEY_ATTRIBUTES, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_RESET_KEY_ATTRIBUTES server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &rpos, &rremain, + attributes); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); +} + + +psa_status_t psa_sign_hash( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, + size_t *signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(hash, hash_length) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(*signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_sign_hash_abort( + psa_sign_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_sign_hash_complete( + psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(*signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH_COMPLETE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH_COMPLETE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +uint32_t psa_sign_hash_get_num_ops( + const psa_sign_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + uint32_t value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + value = 0; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH_GET_NUM_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH_GET_NUM_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +psa_status_t psa_sign_hash_start( + psa_sign_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_sign_hash_interruptible_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(hash, hash_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_HASH_START, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_HASH_START server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_sign_message( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *signature, size_t signature_size, + size_t *signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(*signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t( + &pos, &remaining, + *signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_SIGN_MESSAGE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_SIGN_MESSAGE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_return_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_verify_hash( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(hash, hash_length) + + psasim_serialise_buffer_needs(signature, signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_verify_hash_abort( + psa_verify_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH_ABORT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH_ABORT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_verify_hash_complete( + psa_verify_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH_COMPLETE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH_COMPLETE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +uint32_t psa_verify_hash_get_num_ops( + const psa_verify_hash_interruptible_operation_t *operation + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + uint32_t value = 0; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation); + + ser_params = malloc(needed); + if (ser_params == NULL) { + value = 0; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH_GET_NUM_OPS, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH_GET_NUM_OPS server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &rpos, &rremain, + &value); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return value; +} + + +psa_status_t psa_verify_hash_start( + psa_verify_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_psa_verify_hash_interruptible_operation_t_needs(*operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(hash, hash_length) + + psasim_serialise_buffer_needs(signature, signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + *operation); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + hash, hash_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_HASH_START, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_HASH_START server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_verify_message( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *signature, size_t signature_length + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = + psasim_serialise_begin_needs() + + psasim_serialise_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(signature, signature_length); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t( + &pos, &remaining, + key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t( + &pos, &remaining, + alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer( + &pos, &remaining, + signature, signature_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_VERIFY_MESSAGE, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_VERIFY_MESSAGE server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t( + &rpos, &rremain, + &status); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); return status; } diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c index 30d4b26dc8..52597516cf 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c +++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c @@ -54,7 +54,9 @@ int psa_crypto_init_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } @@ -88,7 +90,9 @@ int psa_aead_abort_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } @@ -118,12 +122,16 @@ int psa_aead_abort_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -167,37 +175,51 @@ int psa_aead_decrypt_wrapper( goto fail; } - ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &nonce, &nonce_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &additional_data, &additional_data_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &additional_data, &additional_data_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &ciphertext, &ciphertext_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &ciphertext, &ciphertext_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &plaintext, &plaintext_size); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &plaintext, &plaintext_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &plaintext_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &plaintext_length); if (!ok) { goto fail; } @@ -234,17 +256,23 @@ int psa_aead_decrypt_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&rpos, &rremain, plaintext, plaintext_size); + ok = psasim_serialise_buffer( + &rpos, &rremain, + plaintext, plaintext_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&rpos, &rremain, plaintext_length); + ok = psasim_serialise_size_t( + &rpos, &rremain, + plaintext_length); if (!ok) { goto fail; } @@ -290,17 +318,23 @@ int psa_aead_decrypt_setup_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); if (!ok) { goto fail; } @@ -332,12 +366,16 @@ int psa_aead_decrypt_setup_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -381,37 +419,51 @@ int psa_aead_encrypt_wrapper( goto fail; } - ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &nonce, &nonce_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &additional_data, &additional_data_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &additional_data, &additional_data_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &plaintext, &plaintext_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &plaintext, &plaintext_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &ciphertext, &ciphertext_size); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &ciphertext, &ciphertext_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &ciphertext_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &ciphertext_length); if (!ok) { goto fail; } @@ -448,17 +500,23 @@ int psa_aead_encrypt_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&rpos, &rremain, ciphertext, ciphertext_size); + ok = psasim_serialise_buffer( + &rpos, &rremain, + ciphertext, ciphertext_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&rpos, &rremain, ciphertext_length); + ok = psasim_serialise_size_t( + &rpos, &rremain, + ciphertext_length); if (!ok) { goto fail; } @@ -504,17 +562,23 @@ int psa_aead_encrypt_setup_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); if (!ok) { goto fail; } @@ -546,12 +610,16 @@ int psa_aead_encrypt_setup_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -591,27 +659,37 @@ int psa_aead_finish_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &ciphertext, &ciphertext_size); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &ciphertext, &ciphertext_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &ciphertext_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &ciphertext_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &tag, &tag_size); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &tag, &tag_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &tag_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &tag_length); if (!ok) { goto fail; } @@ -649,32 +727,44 @@ int psa_aead_finish_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&rpos, &rremain, ciphertext, ciphertext_size); + ok = psasim_serialise_buffer( + &rpos, &rremain, + ciphertext, ciphertext_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&rpos, &rremain, ciphertext_length); + ok = psasim_serialise_size_t( + &rpos, &rremain, + ciphertext_length); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&rpos, &rremain, tag, tag_size); + ok = psasim_serialise_buffer( + &rpos, &rremain, + tag, tag_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&rpos, &rremain, tag_length); + ok = psasim_serialise_size_t( + &rpos, &rremain, + tag_length); if (!ok) { goto fail; } @@ -717,17 +807,23 @@ int psa_aead_generate_nonce_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_size); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &nonce, &nonce_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &nonce_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &nonce_length); if (!ok) { goto fail; } @@ -761,22 +857,30 @@ int psa_aead_generate_nonce_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&rpos, &rremain, nonce, nonce_size); + ok = psasim_serialise_buffer( + &rpos, &rremain, + nonce, nonce_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&rpos, &rremain, nonce_length); + ok = psasim_serialise_size_t( + &rpos, &rremain, + nonce_length); if (!ok) { goto fail; } @@ -816,17 +920,23 @@ int psa_aead_set_lengths_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &ad_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &ad_length); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &plaintext_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &plaintext_length); if (!ok) { goto fail; } @@ -858,12 +968,16 @@ int psa_aead_set_lengths_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -899,12 +1013,16 @@ int psa_aead_set_nonce_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &nonce, &nonce_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &nonce, &nonce_length); if (!ok) { goto fail; } @@ -935,12 +1053,16 @@ int psa_aead_set_nonce_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -983,22 +1105,30 @@ int psa_aead_update_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &output, &output_size); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &output_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); if (!ok) { goto fail; } @@ -1033,22 +1163,30 @@ int psa_aead_update_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&rpos, &rremain, output, output_size); + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&rpos, &rremain, output_length); + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); if (!ok) { goto fail; } @@ -1090,12 +1228,16 @@ int psa_aead_update_ad_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); if (!ok) { goto fail; } @@ -1126,12 +1268,16 @@ int psa_aead_update_ad_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -1174,22 +1320,30 @@ int psa_aead_verify_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_aead_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_aead_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &plaintext, &plaintext_size); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &plaintext, &plaintext_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &plaintext_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &plaintext_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &tag, &tag_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &tag, &tag_length); if (!ok) { goto fail; } @@ -1224,22 +1378,30 @@ int psa_aead_verify_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_aead_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_aead_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&rpos, &rremain, plaintext, plaintext_size); + ok = psasim_serialise_buffer( + &rpos, &rremain, + plaintext, plaintext_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&rpos, &rremain, plaintext_length); + ok = psasim_serialise_size_t( + &rpos, &rremain, + plaintext_length); if (!ok) { goto fail; } @@ -1261,6 +1423,1335 @@ fail: 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_cipher_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_decrypt_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_decrypt( + key, + alg, + input, input_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_decrypt_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_decrypt_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_encrypt_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_encrypt( + key, + alg, + input, input_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_encrypt_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_encrypt_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_finish_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_finish( + operation, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(output); + + return 1; // success + +fail: + free(result); + + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_generate_iv_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + uint8_t *iv = NULL; + size_t iv_size; + size_t iv_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &iv, &iv_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &iv_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_generate_iv( + operation, + iv, iv_size, + &iv_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation) + + psasim_serialise_buffer_needs(iv, iv_size) + + psasim_serialise_size_t_needs(iv_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + iv, iv_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + iv_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(iv); + + return 1; // success + +fail: + free(result); + + free(iv); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_set_iv_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + uint8_t *iv = NULL; + size_t iv_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &iv, &iv_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_set_iv( + operation, + iv, iv_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(iv); + + return 1; // success + +fail: + free(result); + + free(iv); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_cipher_update_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t *operation; + uint8_t *input = NULL; + size_t input_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_cipher_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_cipher_update( + operation, + input, input_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_cipher_operation_t_needs(operation) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_cipher_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_copy_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t source_key; + psa_key_attributes_t attributes; + mbedtls_svc_key_id_t target_key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &source_key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &target_key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_copy_key( + source_key, + &attributes, + &target_key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_mbedtls_svc_key_id_t_needs(target_key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + target_key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + // Returns 1 for success, 0 for failure int psa_destroy_key_wrapper( uint8_t *in_params, size_t in_params_len, @@ -1279,7 +2770,9 @@ int psa_destroy_key_wrapper( goto fail; } - ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); if (!ok) { goto fail; } @@ -1308,7 +2801,9 @@ int psa_destroy_key_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } @@ -1324,6 +2819,480 @@ fail: 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_generate_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_key( + &attributes, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_key_ext_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + psa_key_production_parameters_t *params = NULL; + size_t params_data_length; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_production_parameters_t( + &pos, &remaining, + ¶ms, ¶ms_data_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_key_ext( + &attributes, + params, params_data_length, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(params); + + return 1; // success + +fail: + free(result); + + free(params); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_random_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t *output = NULL; + size_t output_size; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_random( + output, output_size + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(output); + + return 1; // success + +fail: + free(result); + + free(output); + + return 0; // This shouldn't happen! +} + // Returns 1 for success, 0 for failure int psa_get_key_attributes_wrapper( uint8_t *in_params, size_t in_params_len, @@ -1343,12 +3312,16 @@ int psa_get_key_attributes_wrapper( goto fail; } - ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_key_attributes_t(&pos, &remaining, &attributes); + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); if (!ok) { goto fail; } @@ -1379,12 +3352,16 @@ int psa_get_key_attributes_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_serialise_psa_key_attributes_t(&rpos, &rremain, attributes); + ok = psasim_serialise_psa_key_attributes_t( + &rpos, &rremain, + attributes); if (!ok) { goto fail; } @@ -1418,7 +3395,9 @@ int psa_hash_abort_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } @@ -1448,12 +3427,16 @@ int psa_hash_abort_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -1488,12 +3471,16 @@ int psa_hash_clone_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &source_operation); + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &source_operation); if (!ok) { goto fail; } - ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &target_operation); + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &target_operation); if (!ok) { goto fail; } @@ -1524,12 +3511,16 @@ int psa_hash_clone_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, target_operation); + ok = psasim_server_serialise_psa_hash_operation_t( + &rpos, &rremain, + target_operation); if (!ok) { goto fail; } @@ -1567,17 +3558,23 @@ int psa_hash_compare_wrapper( goto fail; } - ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); if (!ok) { goto fail; } @@ -1608,7 +3605,9 @@ int psa_hash_compare_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } @@ -1653,22 +3652,30 @@ int psa_hash_compute_wrapper( goto fail; } - ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_size); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &hash_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &hash_length); if (!ok) { goto fail; } @@ -1702,17 +3709,23 @@ int psa_hash_compute_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&rpos, &rremain, hash, hash_size); + ok = psasim_serialise_buffer( + &rpos, &rremain, + hash, hash_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&rpos, &rremain, hash_length); + ok = psasim_serialise_size_t( + &rpos, &rremain, + hash_length); if (!ok) { goto fail; } @@ -1755,17 +3768,23 @@ int psa_hash_finish_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_size); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_size); if (!ok) { goto fail; } - ok = psasim_deserialise_size_t(&pos, &remaining, &hash_length); + ok = psasim_deserialise_size_t( + &pos, &remaining, + &hash_length); if (!ok) { goto fail; } @@ -1799,22 +3818,30 @@ int psa_hash_finish_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } - ok = psasim_serialise_buffer(&rpos, &rremain, hash, hash_size); + ok = psasim_serialise_buffer( + &rpos, &rremain, + hash, hash_size); if (!ok) { goto fail; } - ok = psasim_serialise_size_t(&rpos, &rremain, hash_length); + ok = psasim_serialise_size_t( + &rpos, &rremain, + hash_length); if (!ok) { goto fail; } @@ -1853,12 +3880,16 @@ int psa_hash_setup_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); if (!ok) { goto fail; } @@ -1889,12 +3920,16 @@ int psa_hash_setup_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -1930,12 +3965,16 @@ int psa_hash_update_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); if (!ok) { goto fail; } @@ -1966,12 +4005,16 @@ int psa_hash_update_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -2011,12 +4054,16 @@ int psa_hash_verify_wrapper( goto fail; } - ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation); + ok = psasim_server_deserialise_psa_hash_operation_t( + &pos, &remaining, + &operation); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); if (!ok) { goto fail; } @@ -2047,12 +4094,16 @@ int psa_hash_verify_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation); + ok = psasim_server_serialise_psa_hash_operation_t( + &rpos, &rremain, + operation); if (!ok) { goto fail; } @@ -2093,17 +4144,23 @@ int psa_import_key_wrapper( goto fail; } - ok = psasim_deserialise_psa_key_attributes_t(&pos, &remaining, &attributes); + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); if (!ok) { goto fail; } - ok = psasim_deserialise_buffer(&pos, &remaining, &data, &data_length); + ok = psasim_deserialise_buffer( + &pos, &remaining, + &data, &data_length); if (!ok) { goto fail; } - ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); if (!ok) { goto fail; } @@ -2135,12 +4192,16 @@ int psa_import_key_wrapper( goto fail; } - ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); if (!ok) { goto fail; } - ok = psasim_serialise_mbedtls_svc_key_id_t(&rpos, &rremain, key); + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); if (!ok) { goto fail; } @@ -2160,6 +4221,3345 @@ fail: return 0; // This shouldn't happen! } +// Returns 1 for success, 0 for failure +int psa_interruptible_get_max_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t value = 0; + + uint8_t *result = NULL; + int ok; + + // Now we call the actual target function + + value = psa_interruptible_get_max_ops( + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(value); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_uint32_t( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_interruptible_set_max_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t max_ops; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint32_t( + &pos, &remaining, + &max_ops); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + psa_interruptible_set_max_ops( + max_ops + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs(); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_get_capacity_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + size_t capacity; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &capacity); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_get_capacity( + operation, + &capacity + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_size_t_needs(capacity); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + capacity); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_input_bytes_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_key_derivation_step_t step; + uint8_t *data = NULL; + size_t data_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_step_t( + &pos, &remaining, + &step); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &data, &data_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_input_bytes( + operation, + step, + data, data_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(data); + + return 1; // success + +fail: + free(result); + + free(data); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_input_integer_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_key_derivation_step_t step; + uint64_t value; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_step_t( + &pos, &remaining, + &step); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_uint64_t( + &pos, &remaining, + &value); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_input_integer( + operation, + step, + value + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_input_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_key_derivation_step_t step; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_step_t( + &pos, &remaining, + &step); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_input_key( + operation, + step, + key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_key_agreement_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_key_derivation_step_t step; + mbedtls_svc_key_id_t private_key; + uint8_t *peer_key = NULL; + size_t peer_key_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_derivation_step_t( + &pos, &remaining, + &step); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &private_key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &peer_key, &peer_key_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_key_agreement( + operation, + step, + private_key, + peer_key, peer_key_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(peer_key); + + return 1; // success + +fail: + free(result); + + free(peer_key); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_output_bytes_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + uint8_t *output = NULL; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_output_bytes( + operation, + output, output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation) + + psasim_serialise_buffer_needs(output, output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(output); + + return 1; // success + +fail: + free(result); + + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_output_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + psa_key_derivation_operation_t *operation; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_output_key( + &attributes, + operation, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_output_key_ext_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + psa_key_derivation_operation_t *operation; + psa_key_production_parameters_t *params = NULL; + size_t params_data_length; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_production_parameters_t( + &pos, &remaining, + ¶ms, ¶ms_data_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_output_key_ext( + &attributes, + operation, + params, params_data_length, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t( + &rpos, &rremain, + key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(params); + + return 1; // success + +fail: + free(result); + + free(params); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_set_capacity_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + size_t capacity; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &capacity); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_set_capacity( + operation, + capacity + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_key_derivation_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t *operation; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_key_derivation_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_key_derivation_setup( + operation, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_key_derivation_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_key_derivation_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_compute_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *mac = NULL; + size_t mac_size; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &mac, &mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_compute( + key, + alg, + input, input_length, + mac, mac_size, + &mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(mac_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + mac_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(mac); + + return 1; // success + +fail: + free(result); + + free(input); + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_sign_finish_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + uint8_t *mac = NULL; + size_t mac_size; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &mac, &mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_sign_finish( + operation, + mac, mac_size, + &mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation) + + psasim_serialise_buffer_needs(mac, mac_size) + + psasim_serialise_size_t_needs(mac_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + mac, mac_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + mac_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(mac); + + return 1; // success + +fail: + free(result); + + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_sign_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_sign_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_update_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + uint8_t *input = NULL; + size_t input_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_update( + operation, + input, input_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + + return 1; // success + +fail: + free(result); + + free(input); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_verify_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *mac = NULL; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &mac, &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_verify( + key, + alg, + input, input_length, + mac, mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(mac); + + return 1; // success + +fail: + free(result); + + free(input); + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_verify_finish_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + uint8_t *mac = NULL; + size_t mac_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &mac, &mac_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_verify_finish( + operation, + mac, mac_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(mac); + + return 1; // success + +fail: + free(result); + + free(mac); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_mac_verify_setup_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_mac_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_mac_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_mac_verify_setup( + operation, + key, + alg + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_mac_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_mac_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_purge_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_purge_key( + key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_raw_key_agreement_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t alg; + mbedtls_svc_key_id_t private_key; + uint8_t *peer_key = NULL; + size_t peer_key_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &private_key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &peer_key, &peer_key_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_raw_key_agreement( + alg, + private_key, + peer_key, peer_key_length, + output, output_size, + &output_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(peer_key); + free(output); + + return 1; // success + +fail: + free(result); + + free(peer_key); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_reset_key_attributes_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_key_attributes_t attributes; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t( + &pos, &remaining, + &attributes); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + psa_reset_key_attributes( + &attributes + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(attributes); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_key_attributes_t( + &rpos, &rremain, + attributes); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *hash = NULL; + size_t hash_length; + uint8_t *signature = NULL; + size_t signature_size; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_hash( + key, + alg, + hash, hash_length, + signature, signature_size, + &signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(signature_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + free(signature); + + return 1; // success + +fail: + free(result); + + free(hash); + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_sign_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_hash_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_complete_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_sign_hash_interruptible_operation_t *operation; + uint8_t *signature = NULL; + size_t signature_size; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_hash_complete( + operation, + signature, signature_size, + &signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(signature_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(signature); + + return 1; // success + +fail: + free(result); + + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_get_num_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t value = 0; + psa_sign_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + value = psa_sign_hash_get_num_ops( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(value); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_uint32_t( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_hash_start_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_sign_hash_interruptible_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *hash = NULL; + size_t hash_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_hash_start( + operation, + key, + alg, + hash, hash_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + + return 1; // success + +fail: + free(result); + + free(hash); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_sign_message_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *signature = NULL; + size_t signature_size; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t( + &pos, &remaining, + &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_sign_message( + key, + alg, + input, input_length, + signature, signature_size, + &signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_buffer_needs(signature, signature_size) + + psasim_serialise_size_t_needs(signature_length); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_buffer( + &rpos, &rremain, + signature, signature_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t( + &rpos, &rremain, + signature_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(signature); + + return 1; // success + +fail: + free(result); + + free(input); + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *hash = NULL; + size_t hash_length; + uint8_t *signature = NULL; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_hash( + key, + alg, + hash, hash_length, + signature, signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + free(signature); + + return 1; // success + +fail: + free(result); + + free(hash); + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_abort_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_verify_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_hash_abort( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_complete_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_verify_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_hash_complete( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_get_num_ops_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + uint32_t value = 0; + psa_verify_hash_interruptible_operation_t *operation; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + value = psa_verify_hash_get_num_ops( + operation + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_uint32_t_needs(value); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_uint32_t( + &rpos, &rremain, + value); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_hash_start_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_verify_hash_interruptible_operation_t *operation; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *hash = NULL; + size_t hash_length; + uint8_t *signature = NULL; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t( + &pos, &remaining, + &operation); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &hash, &hash_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_hash_start( + operation, + key, + alg, + hash, hash_length, + signature, signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t( + &rpos, &rremain, + operation); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(hash); + free(signature); + + return 1; // success + +fail: + free(result); + + free(hash); + free(signature); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_verify_message_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *signature = NULL; + size_t signature_length; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t( + &pos, &remaining, + &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t( + &pos, &remaining, + &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer( + &pos, &remaining, + &signature, &signature_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_verify_message( + key, + alg, + input, input_length, + signature, signature_length + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t( + &rpos, &rremain, + status); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(signature); + + return 1; // success + +fail: + free(result); + + free(input); + free(signature); + + return 0; // This shouldn't happen! +} + psa_status_t psa_crypto_call(psa_msg_t msg) { int ok = 0; @@ -2248,10 +7648,78 @@ psa_status_t psa_crypto_call(psa_msg_t msg) ok = psa_aead_verify_wrapper(in_params, in_params_len, &out_params, &out_params_len); break; + case PSA_ASYMMETRIC_DECRYPT: + ok = psa_asymmetric_decrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_ASYMMETRIC_ENCRYPT: + ok = psa_asymmetric_encrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_ABORT: + ok = psa_cipher_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_DECRYPT: + ok = psa_cipher_decrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_DECRYPT_SETUP: + ok = psa_cipher_decrypt_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_ENCRYPT: + ok = psa_cipher_encrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_ENCRYPT_SETUP: + ok = psa_cipher_encrypt_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_FINISH: + ok = psa_cipher_finish_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_GENERATE_IV: + ok = psa_cipher_generate_iv_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_SET_IV: + ok = psa_cipher_set_iv_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_CIPHER_UPDATE: + ok = psa_cipher_update_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_COPY_KEY: + ok = psa_copy_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; case PSA_DESTROY_KEY: ok = psa_destroy_key_wrapper(in_params, in_params_len, &out_params, &out_params_len); break; + case PSA_EXPORT_KEY: + ok = psa_export_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_EXPORT_PUBLIC_KEY: + ok = psa_export_public_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_KEY: + ok = psa_generate_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_KEY_EXT: + ok = psa_generate_key_ext_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_RANDOM: + ok = psa_generate_random_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; case PSA_GET_KEY_ATTRIBUTES: ok = psa_get_key_attributes_wrapper(in_params, in_params_len, &out_params, &out_params_len); @@ -2292,6 +7760,150 @@ psa_status_t psa_crypto_call(psa_msg_t msg) ok = psa_import_key_wrapper(in_params, in_params_len, &out_params, &out_params_len); break; + case PSA_INTERRUPTIBLE_GET_MAX_OPS: + ok = psa_interruptible_get_max_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_INTERRUPTIBLE_SET_MAX_OPS: + ok = psa_interruptible_set_max_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_ABORT: + ok = psa_key_derivation_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_GET_CAPACITY: + ok = psa_key_derivation_get_capacity_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_INPUT_BYTES: + ok = psa_key_derivation_input_bytes_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_INPUT_INTEGER: + ok = psa_key_derivation_input_integer_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_INPUT_KEY: + ok = psa_key_derivation_input_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_KEY_AGREEMENT: + ok = psa_key_derivation_key_agreement_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_OUTPUT_BYTES: + ok = psa_key_derivation_output_bytes_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_OUTPUT_KEY: + ok = psa_key_derivation_output_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_OUTPUT_KEY_EXT: + ok = psa_key_derivation_output_key_ext_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_SET_CAPACITY: + ok = psa_key_derivation_set_capacity_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_KEY_DERIVATION_SETUP: + ok = psa_key_derivation_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_ABORT: + ok = psa_mac_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_COMPUTE: + ok = psa_mac_compute_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_SIGN_FINISH: + ok = psa_mac_sign_finish_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_SIGN_SETUP: + ok = psa_mac_sign_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_UPDATE: + ok = psa_mac_update_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_VERIFY: + ok = psa_mac_verify_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_VERIFY_FINISH: + ok = psa_mac_verify_finish_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_MAC_VERIFY_SETUP: + ok = psa_mac_verify_setup_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_PURGE_KEY: + ok = psa_purge_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_RAW_KEY_AGREEMENT: + ok = psa_raw_key_agreement_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_RESET_KEY_ATTRIBUTES: + ok = psa_reset_key_attributes_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH: + ok = psa_sign_hash_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH_ABORT: + ok = psa_sign_hash_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH_COMPLETE: + ok = psa_sign_hash_complete_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH_GET_NUM_OPS: + ok = psa_sign_hash_get_num_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_HASH_START: + ok = psa_sign_hash_start_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_SIGN_MESSAGE: + ok = psa_sign_message_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH: + ok = psa_verify_hash_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH_ABORT: + ok = psa_verify_hash_abort_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH_COMPLETE: + ok = psa_verify_hash_complete_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH_GET_NUM_OPS: + ok = psa_verify_hash_get_num_ops_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_HASH_START: + ok = psa_verify_hash_start_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_VERIFY_MESSAGE: + ok = psa_verify_message_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; } free(in_params); diff --git a/tests/psa-client-server/psasim/src/psa_sim_generate.pl b/tests/psa-client-server/psasim/src/psa_sim_generate.pl index 43de1db5e0..ac238070c3 100755 --- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl +++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl @@ -18,6 +18,16 @@ my $debug = 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 = qw( + psa_key_derivation_verify_bytes + psa_key_derivation_verify_key +); + +# Remove @skip_functions from @functions +my %skip_functions = map { $_ => 1 } @skip_functions; +@functions = grep(!exists($skip_functions{$_}), @functions); + # get_functions(), called above, returns a data structure for each function # that we need to create client and server stubs for. In this example Perl script, # the function declarations we want are in the data section (after __END__ at @@ -519,6 +529,9 @@ int ${name}_wrapper( uint8_t *in_params, size_t in_params_len, uint8_t **out_params, size_t *out_params_len) { +EOF + + print $fh <{is_output}, @$args); - my $sep1 = ($ret_type eq "void") ? ";" : " +"; + my $sep1 = (($ret_type eq "void") and ($#outputs < 0)) ? ";" : " +"; print $fh <{args}; @@ -764,19 +818,35 @@ EOF $argtype =~ s/^const //; print $fh <{return}->{type}; my $ret_name = $f->{return}->{name}; my $args = $f->{args}; - print $fh "\n $ret_name = $name(\n"; + if ($ret_type eq "void") { + print $fh "\n $name(\n"; + } else { + print $fh "\n $ret_name = $name(\n"; + } print $fh " );\n" if $#$args < 0; # If no arguments, empty arg list @@ -921,6 +1010,9 @@ sub output_call if ($argtype =~ /^(const )?buffer$/) { my ($n1, $n2) = split(/,\s*/, $argname); print $fh " $n1, $n2"; + } elsif ($argtype =~ /^(const )?psa_key_production_parameters_t$/) { + my ($n1, $n2) = split(/,\s*/, $argname); + print $fh " $n1, $n2"; } else { $argname =~ s/^\*/\&/; # Replace leading * with & if ($is_server && $argtype =~ /^psa_\w+_operation_t/) { @@ -944,7 +1036,7 @@ sub output_signature print $fh "\n$ret_type $name(\n"; - print $fh " void\n)\n" if $#$args < 0; # No arguments + print $fh " void\n )\n" if $#$args < 0; # No arguments for my $i (0 .. $#$args) { my $arg = $args->[$i]; @@ -956,6 +1048,10 @@ sub output_signature my $const = length($1) ? "const " : ""; my ($n1, $n2) = split(/,/, $argname); print $fh " ${const}uint8_t *$n1, size_t $n2"; + } elsif ($argtype =~ /^(const )?psa_key_production_parameters_t$/) { + my $const = length($1) ? "const " : ""; + my ($n1, $n2) = split(/,/, $argname); + print $fh " ${const}psa_key_production_parameters_t *$n1, size_t $n2"; } else { print $fh " $ctypename$argname"; } @@ -984,7 +1080,7 @@ sub get_functions my %funcs = (); for (my $i = 0; $i <= $#src; $i++) { my $line = $src[$i]; - if ($line =~ /^psa_status_t (psa_\w*)\(/) { # begin function definition + if ($line =~ /^(psa_status_t|uint32_t|void) (psa_\w*)\(/) { # begin function definition #print "have one $line\n"; while ($line !~ /;/) { $line .= $src[$i + 1]; @@ -1003,9 +1099,13 @@ sub get_functions my $ret_name = ""; $ret_name = "status" if $ret_type eq "psa_status_t"; + $ret_name = "value" if $ret_type eq "uint32_t"; + $ret_name = "(void)" if $ret_type eq "void"; die("ret_name for $ret_type?") unless length($ret_name); my $ret_default = ""; $ret_default = "PSA_ERROR_CORRUPTION_DETECTED" if $ret_type eq "psa_status_t"; + $ret_default = "0" if $ret_type eq "uint32_t"; + $ret_default = "(void)" if $ret_type eq "void"; die("ret_default for $ret_type?") unless length($ret_default); #print "FUNC $func RET_NAME $ret_name RET_TYPE $ret_type ARGS (", join("; ", @args), ")\n"; @@ -1037,10 +1137,28 @@ sub get_functions #print("$arg: $name: might be a buffer?\n"); die("$arg: not a buffer 1!\n") if $i == $#args; my $next = $args[$i + 1]; + if ($func eq "psa_key_derivation_verify_bytes" && + $arg eq "const uint8_t *expected_output" && + $next eq "size_t output_length") { + $next = "size_t expected_output_length"; # doesn't follow naming convention, so override + } die("$arg: not a buffer 2!\n") if $next !~ /^size_t\s+(${name}_\w+)$/; $i++; # We're using the next param here my $nname = $1; $name .= ", " . $nname; + } elsif ($arg =~ /^((const)\s+)?psa_key_production_parameters_t\s*\*\s*(\w+)$/) { + $type = "psa_key_production_parameters_t"; + $is_output = (length($1) == 0) ? 1 : 0; + $type = "const psa_key_production_parameters_t" if !$is_output; + $ctype = ""; + $name = $3; + #print("$arg: $name: might be a psa_key_production_parameters_t?\n"); + die("$arg: not a psa_key_production_parameters_t 1!\n") if $i == $#args; + my $next = $args[$i + 1]; + die("$arg: $func: $name: $next: not a psa_key_production_parameters_t 2!\n") if $next !~ /^size_t\s+(${name}_\w+)$/; + $i++; # We're using the next param here + my $nname = $1; + $name .= ", " . $nname; } elsif ($arg =~ /^((const)\s+)?(\w+)\s*\*(\w+)$/) { ($type, $name) = ($3, "*" . $4); $ctype = $1 . $type . " "; @@ -2371,3 +2489,3068 @@ psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, * results in this error code. */ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key); + +/** + * \brief Generate random bytes. + * + * \warning This function **can** fail! Callers MUST check the return status + * and MUST NOT use the content of the output buffer if the return + * status is not #PSA_SUCCESS. + * + * \note To generate a key, use psa_generate_key() instead. + * + * \param[out] output Output buffer for the generated data. + * \param output_size Number of bytes to generate and output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size); + +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param key Identifier of the key to use for the operation. It + * must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \param key Identifier of the key to use for the operation. It + * must allow the usage PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + size_t mac_length); + +/** The type of the state data structure for multipart MAC operations. + * + * Before calling any function on a MAC operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_mac_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_mac_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, + * for example: + * \code + * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_mac_operation_init() + * to the structure, for example: + * \code + * psa_mac_operation_t operation; + * operation = psa_mac_operation_init(); + * \endcode + * + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_mac_operation_s psa_mac_operation_t; + +/** \def PSA_MAC_OPERATION_INIT + * + * This macro returns a suitable initializer for a MAC operation object of type + * #psa_mac_operation_t. + */ + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + +/** Set up a multipart MAC calculation operation. + * + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. + * + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. It + * must remain valid until the operation terminates. + * It must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Set up a multipart MAC verification operation. + * + * This function sets up the verification of the MAC + * (message authentication code) of a byte string against an expected value. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. It + * must remain valid until the operation terminates. + * It must allow the usage + * PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_LENGTH(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of the key and \c alg is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p mac buffer is too small. You can determine a + * sufficient buffer size by calling PSA_MAC_LENGTH(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation), or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac verify + * operation), or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length); + +/** Abort a MAC operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_mac_sign_setup() or psa_mac_verify_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_mac_operation_t. + * + * In particular, calling psa_mac_abort() after the operation has been + * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or + * psa_mac_verify_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_abort(psa_mac_operation_t *operation); + +/** Encrypt a message using a symmetric cipher. + * + * This function encrypts a message with a random IV (initialization + * vector). Use the multipart operation interface with a + * #psa_cipher_operation_t object to provide other forms of IV. + * + * \param key Identifier of the key to use for the operation. + * It must allow the usage #PSA_KEY_USAGE_ENCRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * The output contains the IV followed by + * the ciphertext proper. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Decrypt a message using a symmetric cipher. + * + * This function decrypts a message encrypted with a symmetric cipher. + * + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to decrypt. + * This consists of the IV followed by the + * ciphertext proper. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the plaintext is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** The type of the state data structure for multipart cipher operations. + * + * Before calling any function on a cipher operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_cipher_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_cipher_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, + * for example: + * \code + * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_cipher_operation_init() + * to the structure, for example: + * \code + * psa_cipher_operation_t operation; + * operation = psa_cipher_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_cipher_operation_s psa_cipher_operation_t; + +/** \def PSA_CIPHER_OPERATION_INIT + * + * This macro returns a suitable initializer for a cipher operation object of + * type #psa_cipher_operation_t. + */ + +/** Return an initial value for a cipher operation object. + */ +static psa_cipher_operation_t psa_cipher_operation_init(void); + +/** Set the key for a multipart symmetric encryption operation. + * + * The sequence of operations to encrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. + * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to + * generate or set the IV (initialization vector). You should use + * psa_cipher_generate_iv() unless the protocol you are implementing + * requires a specific IV value. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Set the key for a multipart symmetric decryption operation. + * + * The sequence of operations to decrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. + * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the + * decryption. If the IV is prepended to the ciphertext, you can call + * psa_cipher_update() on a buffer containing the IV followed by the + * beginning of the message. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Generate an IV for a symmetric encryption operation. + * + * This function generates a random IV (initialization vector), nonce + * or initial counter value for the encryption operation as appropriate + * for the chosen algorithm, key type and key size. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] iv Buffer where the generated IV is to be written. + * \param iv_size Size of the \p iv buffer in bytes. + * \param[out] iv_length On success, the number of bytes of the + * generated IV. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p iv buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no IV set), + * or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \note When encrypting, applications should use psa_cipher_generate_iv() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active cipher operation. + * \param[in] iv Buffer containing the IV to use. + * \param iv_length Size of the IV in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active cipher + * encrypt operation, with no IV set), or the library has not been + * previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * Before calling this function, you must: + * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() + * (recommended when encrypting) or psa_cipher_set_iv(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm), or the library has not been + * previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting or decrypting a message in a cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. + * + * This function finishes the encryption or decryption of the message + * formed by concatenating the inputs passed to preceding calls to + * psa_cipher_update(). + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm), or the library has not been + * previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Abort a cipher operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_cipher_operation_t. + * + * In particular, calling psa_cipher_abort() after the operation has been + * terminated by a call to psa_cipher_abort() or psa_cipher_finish() + * is safe and has no effect. + * + * \param[in,out] operation Initialized cipher operation. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); + +/** \defgroup key_derivation Key derivation and pseudorandom generation + * @{ + */ + +/** The type of the state data structure for key derivation operations. + * + * Before calling any function on a key derivation operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_derivation_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_derivation_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, + * for example: + * \code + * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_key_derivation_operation_init() + * to the structure, for example: + * \code + * psa_key_derivation_operation_t operation; + * operation = psa_key_derivation_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. + */ +typedef struct psa_key_derivation_s psa_key_derivation_operation_t; + +/** \def PSA_KEY_DERIVATION_OPERATION_INIT + * + * This macro returns a suitable initializer for a key derivation operation + * object of type #psa_key_derivation_operation_t. + */ + +/** Return an initial value for a key derivation operation object. + */ +static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); + +/** Set up a key derivation operation. + * + * A key derivation algorithm takes some inputs and uses them to generate + * a byte stream in a deterministic way. + * This byte stream can be used to produce keys and other + * cryptographic material. + * + * To derive a key: + * -# Start with an initialized object of type #psa_key_derivation_operation_t. + * -# Call psa_key_derivation_setup() to select the algorithm. + * -# Provide the inputs for the key derivation by calling + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() + * as appropriate. Which inputs are needed, in what order, and whether + * they may be keys and if so of what type depends on the algorithm. + * -# Optionally set the operation's maximum capacity with + * psa_key_derivation_set_capacity(). You may do this before, in the middle + * of or after providing inputs. For some algorithms, this step is mandatory + * because the output depends on the maximum capacity. + * -# To derive a key, call psa_key_derivation_output_key() or + * psa_key_derivation_output_key_ext(). + * To derive a byte string for a different purpose, call + * psa_key_derivation_output_bytes(). + * Successive calls to these functions use successive output bytes + * calculated by the key derivation algorithm. + * -# Clean up the key derivation operation object with + * psa_key_derivation_abort(). + * + * If this function returns an error, the key derivation operation object is + * not changed. + * + * If an error occurs at any step after a call to psa_key_derivation_setup(), + * the operation will need to be reset by a call to psa_key_derivation_abort(). + * + * Implementations must reject an attempt to derive a key of size 0. + * + * \param[in,out] operation The key derivation operation object + * to set up. It must + * have been initialized but not set up yet. + * \param alg The key derivation algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c alg is not a key derivation algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg); + +/** Retrieve the current capacity of a key derivation operation. + * + * The capacity of a key derivation is the maximum number of bytes that it can + * return. When you get *N* bytes of output from a key derivation operation, + * this reduces its capacity by *N*. + * + * \param[in] operation The operation to query. + * \param[out] capacity On success, the capacity of the operation. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity); + +/** Set the maximum capacity of a key derivation operation. + * + * The capacity of a key derivation operation is the maximum number of bytes + * that the key derivation operation can return from this point onwards. + * + * \param[in,out] operation The key derivation operation object to modify. + * \param capacity The new capacity of the operation. + * It must be less or equal to the operation's + * current capacity. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p capacity is larger than the operation's current capacity. + * In this case, the operation object remains valid and its capacity + * remains unchanged. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or the + * library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity); + +/** Use the maximum possible capacity for a key derivation operation. + * + * Use this value as the capacity argument when setting up a key derivation + * to indicate that the operation should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the key derivation + * algorithm. + */ +#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t) (-1)) + +/** Provide an input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function passes direct inputs, which is usually correct for + * non-secret inputs. To pass a secret input, which should be in a key + * object, call psa_key_derivation_input_key() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] data Input data to use. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm, or + * \c step does not allow direct inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length); + +/** Provide a numeric input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * However, when an algorithm requires a particular order, numeric inputs + * usually come first as they tend to be configuration parameters. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function is used for inputs which are fixed-size non-negative + * integers. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] value The value of the numeric input. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm, or + * \c step does not allow numeric inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_integer( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value); + +/** Provide an input for key derivation in the form of a key. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function obtains input from a key object, which is usually correct for + * secret inputs or for non-secret personalization strings kept in the key + * store. To pass a non-secret parameter which is not in the key store, + * call psa_key_derivation_input_bytes() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param key Identifier of the key. It must have an + * appropriate type for step and must allow the + * usage #PSA_KEY_USAGE_DERIVE or + * #PSA_KEY_USAGE_VERIFY_DERIVATION (see note) + * and the algorithm used by the operation. + * + * \note Once all inputs steps are completed, the operations will allow: + * - psa_key_derivation_output_bytes() if each input was either a direct input + * or a key with #PSA_KEY_USAGE_DERIVE set; + * - psa_key_derivation_output_key() or psa_key_derivation_output_key_ext() + * if the input for step + * #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD + * was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was + * either a direct input or a key with #PSA_KEY_USAGE_DERIVE set; + * - psa_key_derivation_verify_bytes() if each input was either a direct input + * or a key with #PSA_KEY_USAGE_VERIFY_DERIVATION set; + * - psa_key_derivation_verify_key() under the same conditions as + * psa_key_derivation_verify_bytes(). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key allows neither #PSA_KEY_USAGE_DERIVE nor + * #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this + * algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm, or + * \c step does not allow key inputs of the given type + * or does not allow key inputs at all. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t key); + +/** Perform a key agreement and use the shared secret as input to a key + * derivation. + * + * A key agreement algorithm takes two inputs: a private key \p private_key + * a public key \p peer_key. + * The result of this function is passed as input to a key derivation. + * The output of this key derivation can be extracted by reading from the + * resulting operation to produce keys and other cryptographic material. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() with a + * key agreement and derivation algorithm + * \c alg (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true + * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) + * is false). + * The operation must be ready for an + * input of the type given by \p step. + * \param step Which step the input data is for. + * \param private_key Identifier of the private key to use. It must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * \param[in] peer_key Public key of the peer. The peer key must be in the + * same format that psa_import_key() accepts for the + * public key type corresponding to the type of + * private_key. That is, this function performs the + * equivalent of + * #psa_import_key(..., + * `peer_key`, `peer_key_length`) where + * with key attributes indicating the public key + * type corresponding to the type of `private_key`. + * For example, for EC keys, this means that peer_key + * is interpreted as a point on the curve that the + * private key is on. The standard formats for public + * keys are documented in the documentation of + * psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c private_key is not compatible with \c alg, + * or \p peer_key is not valid for \c alg or not compatible with + * \c private_key, or \c step does not allow an input resulting + * from a key agreement. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this key agreement \p step, + * or the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length); + +/** Read some data from a key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm and + * return those bytes. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the requested number of bytes from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] output Buffer where the output will be written. + * \param output_length Number of bytes to output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * One of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * no output is written to the output buffer. + * The operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length); + +/** Derive a key from an ongoing key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm + * and uses those bytes to generate a key deterministically. + * The key's location, usage policy, type and size are taken from + * \p attributes. + * + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads as many bytes as required from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * How much output is produced and consumed from the operation, and how + * the key is derived, depends on the key type and on the key size + * (denoted \c bits below): + * + * - For key types for which the key is an arbitrary sequence of bytes + * of a given size, this function is functionally equivalent to + * calling #psa_key_derivation_output_bytes + * and passing the resulting output to #psa_import_key. + * However, this function has a security benefit: + * if the implementation provides an isolation boundary then + * the key material is not exposed outside the isolation boundary. + * As a consequence, for these key types, this function always consumes + * exactly (\c bits / 8) bytes from the operation. + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_AES; + * - #PSA_KEY_TYPE_ARIA; + * - #PSA_KEY_TYPE_CAMELLIA; + * - #PSA_KEY_TYPE_DERIVE; + * - #PSA_KEY_TYPE_HMAC; + * - #PSA_KEY_TYPE_PASSWORD_HASH. + * + * - For ECC keys on a Montgomery elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Montgomery curve), this function always draws a byte string whose + * length is determined by the curve, and sets the mandatory bits + * accordingly. That is: + * + * - Curve25519 (#PSA_ECC_FAMILY_MONTGOMERY, 255 bits): draw a 32-byte + * string and process it as specified in RFC 7748 §5. + * - Curve448 (#PSA_ECC_FAMILY_MONTGOMERY, 448 bits): draw a 56-byte + * string and process it as specified in RFC 7748 §5. + * + * - For key types for which the key is represented by a single sequence of + * \c bits bits with constraints as to which bit sequences are acceptable, + * this function draws a byte string of length (\c bits / 8) bytes rounded + * up to the nearest whole number of bytes. If the resulting byte string + * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. + * This process is repeated until an acceptable byte string is drawn. + * The byte string drawn from the operation is interpreted as specified + * for the output produced by psa_export_key(). + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_DES. + * Force-set the parity bits, but discard forbidden weak keys. + * For 2-key and 3-key triple-DES, the three keys are generated + * successively (for example, for 3-key triple-DES, + * if the first 8 bytes specify a weak key and the next 8 bytes do not, + * discard the first 8 bytes, use the next 8 bytes as the first key, + * and continue reading output from the operation to derive the other + * two keys). + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) + * where \c group designates any Diffie-Hellman group) and + * ECC keys on a Weierstrass elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Weierstrass curve). + * For these key types, interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * This method allows compliance to NIST standards, specifically + * the methods titled "key-pair generation by testing candidates" + * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, + * in FIPS 186-4 §B.1.2 for DSA, and + * in NIST SP 800-56A §5.6.1.2.2 or + * FIPS 186-4 §B.4.2 for elliptic curve keys. + * + * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, + * the way in which the operation output is consumed is + * implementation-defined. + * + * In all cases, the data that is read is discarded from the operation. + * The operation's capacity is decreased by the number of bytes read. + * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * + * \note This function is equivalent to calling + * psa_key_derivation_output_key_ext() + * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * and `params_data_length == 0` (i.e. `params->data` is empty). + * + * \param[in] attributes The attributes for the new key. + * If the key type to be created is + * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in + * the policy must be the same as in the current + * operation. + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET or + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a + * key; or one of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + mbedtls_svc_key_id_t *key); + +/** Derive a key from an ongoing key derivation operation with custom + * production parameters. + * + * See the description of psa_key_derivation_out_key() for the operation of + * this function with the default production parameters. + * Mbed TLS currently does not currently support any non-default production + * parameters. + * + * \note This function is experimental and may change in future minor + * versions of Mbed TLS. + * + * \param[in] attributes The attributes for the new key. + * If the key type to be created is + * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in + * the policy must be the same as in the current + * operation. + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] params Customization parameters for the key derivation. + * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * with \p params_data_length = 0, + * this function is equivalent to + * psa_key_derivation_output_key(). + * Mbed TLS currently only supports the default + * production parameters, i.e. + * #PSA_KEY_PRODUCTION_PARAMETERS_INIT, + * for all key types. + * \param params_data_length + * Length of `params->data` in bytes. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET or + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a + * key; or one of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_key_ext( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + const psa_key_production_parameters_t *params, + size_t params_data_length, + mbedtls_svc_key_id_t *key); + +/** Compare output data from a key derivation operation to an expected value. + * + * This function calculates output bytes from a key derivation algorithm and + * compares those bytes to an expected value in constant time. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the expected number of bytes from the + * stream before comparing them. + * The operation's capacity decreases by the number of bytes read. + * + * This is functionally equivalent to the following code: + * \code + * psa_key_derivation_output_bytes(operation, tmp, output_length); + * if (memcmp(output, tmp, output_length) != 0) + * return PSA_ERROR_INVALID_SIGNATURE; + * \endcode + * except (1) it works even if the key's policy does not allow outputting the + * bytes, and (2) the comparison will be done in constant time. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, + * the operation enters an error state and must be aborted by calling + * psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] expected_output Buffer containing the expected derivation output. + * \param output_length Length of the expected output; this is also the + * number of bytes that will be read. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The output was read successfully, but it differs from the expected + * output. + * \retval #PSA_ERROR_NOT_PERMITTED + * One of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_VERIFY_DERIVATION. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * the operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller expected output. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_verify_bytes( + psa_key_derivation_operation_t *operation, + const uint8_t *expected_output, + size_t output_length); + +/** Compare output data from a key derivation operation to an expected value + * stored in a key object. + * + * This function calculates output bytes from a key derivation algorithm and + * compares those bytes to an expected value, provided as key of type + * #PSA_KEY_TYPE_PASSWORD_HASH. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the number of bytes corresponding to the + * length of the expected value from the stream before comparing them. + * The operation's capacity decreases by the number of bytes read. + * + * This is functionally equivalent to exporting the key and calling + * psa_key_derivation_verify_bytes() on the result, except that it + * works even if the key cannot be exported. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, + * the operation enters an error state and must be aborted by calling + * psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] expected A key of type #PSA_KEY_TYPE_PASSWORD_HASH + * containing the expected output. Its policy must + * include the #PSA_KEY_USAGE_VERIFY_DERIVATION flag + * and the permitted algorithm must match the + * operation. The value of this key was likely + * computed by a previous call to + * psa_key_derivation_output_key() or + * psa_key_derivation_output_key_ext(). + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The output was read successfully, but if differs from the expected + * output. + * \retval #PSA_ERROR_INVALID_HANDLE + * The key passed as the expected value does not exist. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key passed as the expected value has an invalid type. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key passed as the expected value does not allow this usage or + * this algorithm; or one of the inputs was a key whose policy didn't + * allow #PSA_KEY_USAGE_VERIFY_DERIVATION. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * the length of the expected value. In this case, + * the operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller expected output. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_verify_key( + psa_key_derivation_operation_t *operation, + psa_key_id_t expected); + +/** Abort a key derivation operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_key_derivation_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_key_derivation_operation_t. + * + * In particular, it is valid to call psa_key_derivation_abort() twice, or to + * call psa_key_derivation_abort() on an operation that has not been set up. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation); + +/** Perform a key agreement and return the raw shared secret. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It should instead be passed as + * input to a key derivation algorithm. To chain a key agreement with + * a key derivation, use psa_key_derivation_key_agreement() and other + * functions from the key derivation interface. + * + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) + * is true). + * \param private_key Identifier of the private key to use. It must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * \param[in] peer_key Public key of the peer. It must be + * in the same format that psa_import_key() + * accepts. The standard formats for public + * keys are documented in the documentation + * of psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm, or + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p output_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Generate a key or key pair. + * + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \note This function is equivalent to calling psa_generate_key_ext() + * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * and `params_data_length == 0` (i.e. `params->data` is empty). + * + * \param[in] attributes The attributes for the new key. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key); + +/** + * \brief Generate a key or key pair using custom production parameters. + * + * See the description of psa_generate_key() for the operation of this + * function with the default production parameters. In addition, this function + * supports the following production customizations, described in more detail + * in the documentation of ::psa_key_production_parameters_t: + * + * - RSA keys: generation with a custom public exponent. + * + * \note This function is experimental and may change in future minor + * versions of Mbed TLS. + * + * \param[in] attributes The attributes for the new key. + * \param[in] params Customization parameters for the key generation. + * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * with \p params_data_length = 0, + * this function is equivalent to + * psa_generate_key(). + * \param params_data_length + * Length of `params->data` in bytes. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, + size_t params_data_length, + mbedtls_svc_key_id_t *key); + +/** + * \brief Sign a message with a private key. For hash-and-sign algorithms, + * this includes the hashing step. + * + * \note To perform a multi-part hash-and-sign signature algorithm, first use + * a multi-part hash operation and then pass the resulting hash to + * psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the + * hash algorithm to use. + * + * \param[in] key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. The key must + * allow the usage #PSA_KEY_USAGE_SIGN_MESSAGE. + * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) + * is true), that is compatible with the type of + * \p key. + * \param[in] input The input message to sign. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param[in] signature_size Size of the \p signature buffer in bytes. This + * must be appropriate for the selected + * algorithm and key: + * - The required signature size is + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of key. + * - #PSA_SIGNATURE_MAX_SIZE evaluates to the + * maximum signature size of any supported + * signature algorithm. + * \param[out] signature_length On success, the number of bytes that make up + * the returned signature value. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, + * or it does not permit the requested algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** \brief Verify the signature of a message with a public key, using + * a hash-and-sign verification algorithm. + * + * \note To perform a multi-part hash-and-sign signature verification + * algorithm, first use a multi-part hash operation to hash the message + * and then pass the resulting hash to psa_verify_hash(). + * PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm + * to use. + * + * \param[in] key Identifier of the key to use for the operation. + * It must be a public key or an asymmetric key + * pair. The key must allow the usage + * #PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) + * is true), that is compatible with the type of + * \p key. + * \param[in] input The message whose signature is to be verified. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param[in] signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, + * or it does not permit the requested algorithm. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed signature + * is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_message(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Sign a hash or short message with a private key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). + * Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. The key must + * allow the usage #PSA_KEY_USAGE_SIGN_HASH. + * \param alg A signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * \brief Verify the signature of a hash or short message using a public key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). + * Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param key Identifier of the key to use for the operation. It + * must be a public key or an asymmetric key pair. The + * key must allow the usage + * #PSA_KEY_USAGE_VERIFY_HASH. + * \param alg A signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Encrypt a short message with a public key. + * + * \param key Identifier of the key to use for the operation. + * It must be a public key or an asymmetric key + * pair. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p key. + * \param[in] input The message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. It must + * allow the usage #PSA_KEY_USAGE_DECRYPT. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p key. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_INVALID_PADDING \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Remove non-essential copies of key material from memory. + * + * If the key identifier designates a volatile key, this functions does not do + * anything and returns successfully. + * + * If the key identifier designates a persistent key, then this function will + * free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and the key can still be used. + * + * \param key Identifier of the key to purge. + * + * \retval #PSA_SUCCESS + * The key material will have been removed from memory if it is not + * currently required. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not a valid key identifier. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_purge_key(mbedtls_svc_key_id_t key); + +/** + * \brief Export a key in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If the implementation of psa_import_key() supports other formats + * beyond the format specified here, the output from psa_export_key() + * must use the representation specified here, not the original + * representation. + * + * For standard key types, the output format is as follows: + * + * - For symmetric keys (including MAC keys), the format is the + * raw bytes of the key. + * - For DES, the key data consists of 8 bytes. The parity bits must be + * correct. + * - For Triple-DES, the format is the concatenation of the + * two or three DES keys. + * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format + * is the non-encrypted DER encoding of the representation defined by + * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. + * ``` + * RSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * ``` + * - For elliptic curve key pairs (key types for which + * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is + * a representation of the private value as a `ceiling(m/8)`-byte string + * where `m` is the bit size associated with the curve, i.e. the bit size + * of the order of the curve's coordinate field. This byte string is + * in little-endian order for Montgomery curves (curve types + * `PSA_ECC_FAMILY_CURVEXXX`), and in big-endian order for Weierstrass + * curves (curve types `PSA_ECC_FAMILY_SECTXXX`, `PSA_ECC_FAMILY_SECPXXX` + * and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`). + * For Weierstrass curves, this is the content of the `privateKey` field of + * the `ECPrivateKey` format defined by RFC 5915. For Montgomery curves, + * the format is defined by RFC 7748, and output is masked according to §5. + * For twisted Edwards curves, the private key is as defined by RFC 8032 + * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). + * - For Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the + * format is the representation of the private key `x` as a big-endian byte + * string. The length of the byte string is the private key size in bytes + * (leading zeroes are not stripped). + * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is + * true), the format is the same as for psa_export_public_key(). + * + * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. + * + * \param key Identifier of the key to export. It must allow the + * usage #PSA_KEY_USAGE_EXPORT, unless it is a public + * key. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_EXPORT flag. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_EXPORT_KEY_OUTPUT_SIZE(\c type, \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_key(mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Export a public key or the public part of a key pair in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an object that is equivalent to the public key. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * For standard key types, the output format is as follows: + * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of + * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. + * ``` + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * ``` + * - For elliptic curve keys on a twisted Edwards curve (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_ECC_GET_FAMILY + * returns #PSA_ECC_FAMILY_TWISTED_EDWARDS), the public key is as defined + * by RFC 8032 + * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). + * - For other elliptic curve public keys (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed + * representation defined by SEC1 §2.3.3 as the content of an ECPoint. + * Let `m` be the bit size associated with the curve, i.e. the bit size of + * `q` for a curve over `F_q`. The representation consists of: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * - For Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), + * the format is the representation of the public key `y = g^x mod p` as a + * big-endian byte string. The length of the byte string is the length of the + * base prime `p` in bytes. + * + * Exporting a public key object or the public part of a key pair is + * always permitted, regardless of the key's usage flags. + * + * \param key Identifier of the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is neither a public key nor a key pair. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_EXPORT_KEY_OUTPUT_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Set the maximum number of ops allowed to be + * executed by an interruptible function in a + * single call. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note The time taken to execute a single op is + * implementation specific and depends on + * software, hardware, the algorithm, key type and + * curve chosen. Even within a single operation, + * successive ops can take differing amounts of + * time. The only guarantee is that lower values + * for \p max_ops means functions will block for a + * lesser maximum amount of time. The functions + * \c psa_sign_interruptible_get_num_ops() and + * \c psa_verify_interruptible_get_num_ops() are + * provided to help with tuning this value. + * + * \note This value defaults to + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, which + * means the whole operation will be done in one + * go, regardless of the number of ops required. + * + * \note If more ops are needed to complete a + * computation, #PSA_OPERATION_INCOMPLETE will be + * returned by the function performing the + * computation. It is then the caller's + * responsibility to either call again with the + * same operation context until it returns 0 or an + * error code; or to call the relevant abort + * function if the answer is no longer required. + * + * \note The interpretation of \p max_ops is also + * implementation defined. On a hard real time + * system, this can indicate a hard deadline, as a + * real-time system needs a guarantee of not + * spending more than X time, however care must be + * taken in such an implementation to avoid the + * situation whereby calls just return, not being + * able to do any actual work within the allotted + * time. On a non-real-time system, the + * implementation can be more relaxed, but again + * whether this number should be interpreted as as + * hard or soft limit or even whether a less than + * or equals as regards to ops executed in a + * single call is implementation defined. + * + * \note For keys in local storage when no accelerator + * driver applies, please see also the + * documentation for \c mbedtls_ecp_set_max_ops(), + * which is the internal implementation in these + * cases. + * + * \warning With implementations that interpret this number + * as a hard limit, setting this number too small + * may result in an infinite loop, whereby each + * call results in immediate return with no ops + * done (as there is not enough time to execute + * any), and thus no result will ever be achieved. + * + * \note This only applies to functions whose + * documentation mentions they may return + * #PSA_OPERATION_INCOMPLETE. + * + * \param max_ops The maximum number of ops to be executed in a + * single call. This can be a number from 0 to + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0 + * is the least amount of work done per call. + */ +void psa_interruptible_set_max_ops(uint32_t max_ops); + +/** + * \brief Get the maximum number of ops allowed to be + * executed by an interruptible function in a + * single call. This will return the last + * value set by + * \c psa_interruptible_set_max_ops() or + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED if + * that function has never been called. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \return Maximum number of ops allowed to be + * executed by an interruptible function in a + * single call. + */ +uint32_t psa_interruptible_get_max_ops(void); + +/** + * \brief Get the number of ops that a hash signing + * operation has taken so far. If the operation + * has completed, then this will represent the + * number of ops required for the entire + * operation. After initialization or calling + * \c psa_sign_hash_interruptible_abort() on + * the operation, a value of 0 will be returned. + * + * \note This interface is guaranteed re-entrant and + * thus may be called from driver code. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * This is a helper provided to help you tune the + * value passed to \c + * psa_interruptible_set_max_ops(). + * + * \param operation The \c psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \return Number of ops that the operation has taken so + * far. + */ +uint32_t psa_sign_hash_get_num_ops( + const psa_sign_hash_interruptible_operation_t *operation); + +/** + * \brief Get the number of ops that a hash verification + * operation has taken so far. If the operation + * has completed, then this will represent the + * number of ops required for the entire + * operation. After initialization or calling \c + * psa_verify_hash_interruptible_abort() on the + * operation, a value of 0 will be returned. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * This is a helper provided to help you tune the + * value passed to \c + * psa_interruptible_set_max_ops(). + * + * \param operation The \c + * psa_verify_hash_interruptible_operation_t to + * use. This must be initialized first. + * + * \return Number of ops that the operation has taken so + * far. + */ +uint32_t psa_verify_hash_get_num_ops( + const psa_verify_hash_interruptible_operation_t *operation); + +/** + * \brief Start signing a hash or short message with a + * private key, in an interruptible manner. + * + * \see \c psa_sign_hash_complete() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_sign_hash_complete() is equivalent to + * \c psa_sign_hash() but + * \c psa_sign_hash_complete() can return early and + * resume according to the limit set with \c + * psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function call. + * + * \note Users should call \c psa_sign_hash_complete() + * repeatedly on the same context after a + * successful call to this function until \c + * psa_sign_hash_complete() either returns 0 or an + * error. \c psa_sign_hash_complete() will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_sign_hash_abort() at any point if they no + * longer want the result. + * + * \note If this function returns an error status, the + * operation enters an error state and must be + * aborted by calling \c psa_sign_hash_abort(). + * + * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. The key must + * allow the usage #PSA_KEY_USAGE_SIGN_HASH. + * \param alg A signature algorithm (\c PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The operation started successfully - call \c psa_sign_hash_complete() + * with the same context to complete the operation + * + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_SIGN_HASH flag, or it does + * not permit the requested algorithm. + * \retval #PSA_ERROR_BAD_STATE + * An operation has previously been started on this context, and is + * still in progress. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash_start( + psa_sign_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length); + +/** + * \brief Continue and eventually complete the action of + * signing a hash or short message with a private + * key, in an interruptible manner. + * + * \see \c psa_sign_hash_start() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_sign_hash_start() is equivalent to + * \c psa_sign_hash() but this function can return + * early and resume according to the limit set with + * \c psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function call. + * + * \note Users should call this function on the same + * operation object repeatedly until it either + * returns 0 or an error. This function will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_sign_hash_abort() at any point if they no + * longer want the result. + * + * \note When this function returns successfully, the + * operation becomes inactive. If this function + * returns an error status, the operation enters an + * error state and must be aborted by calling + * \c psa_sign_hash_abort(). + * + * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first, and have + * had \c psa_sign_hash_start() called with it + * first. + * + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. This + * must be appropriate for the selected + * algorithm and key: + * - The required signature size is + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c + * key_bits, \c alg) where \c key_type and \c + * key_bits are the type and bit-size + * respectively of key. + * - #PSA_SIGNATURE_MAX_SIZE evaluates to the + * maximum signature size of any supported + * signature algorithm. + * \param[out] signature_length On success, the number of bytes that make up + * the returned signature value. + * + * \retval #PSA_SUCCESS + * Operation completed successfully + * + * \retval #PSA_OPERATION_INCOMPLETE + * Operation was interrupted due to the setting of \c + * psa_interruptible_set_max_ops(). There is still work to be done. + * Call this function again with the same operation object. + * + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \c key. + * + * \retval #PSA_ERROR_BAD_STATE + * An operation was not previously started on this context via + * \c psa_sign_hash_start(). + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has either not been previously initialized by + * psa_crypto_init() or you did not previously call + * psa_sign_hash_start() with this operation object. It is + * implementation-dependent whether a failure to initialize results in + * this error code. + */ +psa_status_t psa_sign_hash_complete( + psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length); + +/** + * \brief Abort a sign hash operation. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function is the only function that clears + * the number of ops completed as part of the + * operation. Please ensure you copy this value via + * \c psa_sign_hash_get_num_ops() if required + * before calling. + * + * \note Aborting an operation frees all associated + * resources except for the \p operation structure + * itself. Once aborted, the operation object can + * be reused for another operation by calling \c + * psa_sign_hash_start() again. + * + * \note You may call this function any time after the + * operation object has been initialized. In + * particular, calling \c psa_sign_hash_abort() + * after the operation has already been terminated + * by a call to \c psa_sign_hash_abort() or + * psa_sign_hash_complete() is safe. + * + * \param[in,out] operation Initialized sign hash operation. + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash_abort( + psa_sign_hash_interruptible_operation_t *operation); + +/** + * \brief Start reading and verifying a hash or short + * message, in an interruptible manner. + * + * \see \c psa_verify_hash_complete() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_verify_hash_complete() is equivalent to + * \c psa_verify_hash() but \c + * psa_verify_hash_complete() can return early and + * resume according to the limit set with \c + * psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function. + * + * \note Users should call \c psa_verify_hash_complete() + * repeatedly on the same operation object after a + * successful call to this function until \c + * psa_verify_hash_complete() either returns 0 or + * an error. \c psa_verify_hash_complete() will + * return #PSA_OPERATION_INCOMPLETE if there is + * more work to do. Alternatively users can call + * \c psa_verify_hash_abort() at any point if they + * no longer want the result. + * + * \note If this function returns an error status, the + * operation enters an error state and must be + * aborted by calling \c psa_verify_hash_abort(). + * + * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \param key Identifier of the key to use for the operation. + * The key must allow the usage + * #PSA_KEY_USAGE_VERIFY_HASH. + * \param alg A signature algorithm (\c PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash whose signature is to be verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The operation started successfully - please call \c + * psa_verify_hash_complete() with the same context to complete the + * operation. + * + * \retval #PSA_ERROR_BAD_STATE + * Another operation has already been started on this context, and is + * still in progress. + * + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_VERIFY_HASH flag, or it does + * not permit the requested algorithm. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash_start( + psa_verify_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length); + +/** + * \brief Continue and eventually complete the action of + * reading and verifying a hash or short message + * signed with a private key, in an interruptible + * manner. + * + * \see \c psa_verify_hash_start() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_verify_hash_start() is equivalent to + * \c psa_verify_hash() but this function can + * return early and resume according to the limit + * set with \c psa_interruptible_set_max_ops() to + * reduce the maximum time spent in a function + * call. + * + * \note Users should call this function on the same + * operation object repeatedly until it either + * returns 0 or an error. This function will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_verify_hash_abort() at any point if they + * no longer want the result. + * + * \note When this function returns successfully, the + * operation becomes inactive. If this function + * returns an error status, the operation enters an + * error state and must be aborted by calling + * \c psa_verify_hash_abort(). + * + * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t + * to use. This must be initialized first, and have + * had \c psa_verify_hash_start() called with it + * first. + * + * \retval #PSA_SUCCESS + * Operation completed successfully, and the passed signature is valid. + * + * \retval #PSA_OPERATION_INCOMPLETE + * Operation was interrupted due to the setting of \c + * psa_interruptible_set_max_ops(). There is still work to be done. + * Call this function again with the same operation object. + * + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_BAD_STATE + * An operation was not previously started on this context via + * \c psa_verify_hash_start(). + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has either not been previously initialized by + * psa_crypto_init() or you did not previously call + * psa_verify_hash_start() on this object. It is + * implementation-dependent whether a failure to initialize results in + * this error code. + */ +psa_status_t psa_verify_hash_complete( + psa_verify_hash_interruptible_operation_t *operation); + +/** + * \brief Abort a verify hash operation. + * + * \warning This is a beta API, and thus subject to change at + * any point. It is not bound by the usual interface + * stability promises. + * + * \note This function is the only function that clears the + * number of ops completed as part of the operation. + * Please ensure you copy this value via + * \c psa_verify_hash_get_num_ops() if required + * before calling. + * + * \note Aborting an operation frees all associated + * resources except for the operation structure + * itself. Once aborted, the operation object can be + * reused for another operation by calling \c + * psa_verify_hash_start() again. + * + * \note You may call this function any time after the + * operation object has been initialized. + * In particular, calling \c psa_verify_hash_abort() + * after the operation has already been terminated by + * a call to \c psa_verify_hash_abort() or + * psa_verify_hash_complete() is safe. + * + * \param[in,out] operation Initialized verify hash operation. + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash_abort( + psa_verify_hash_interruptible_operation_t *operation); + +/** Make a copy of a key. + * + * Copy key material from one location to another. + * + * This function is primarily useful to copy a key from one location + * to another, since it populates a key using the material from + * another key which may have a different lifetime. + * + * This function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * + * The policy on the source key must have the usage flag + * #PSA_KEY_USAGE_COPY set. + * This flag is sufficient to permit the copy if the key has the lifetime + * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. + * Some secure elements do not provide a way to copy a key without + * making it extractable from the secure element. If a key is located + * in such a secure element, then the key must have both usage flags + * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make + * a copy of the key outside the secure element. + * + * The resulting key may only be used in a way that conforms to + * both the policy of the original key and the policy specified in + * the \p attributes parameter: + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy and the usage flags in \p attributes. + * - If both allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If either of the policies allows an algorithm and the other policy + * allows a wildcard-based algorithm policy that includes this algorithm, + * the resulting key allows the same algorithm. + * - If the policies do not allow any algorithm in common, this function + * fails with the status #PSA_ERROR_INVALID_ARGUMENT. + * + * The effect of this function on implementation-defined attributes is + * implementation-defined. + * + * \param source_key The key to copy. It must allow the usage + * #PSA_KEY_USAGE_COPY. If a private or secret key is + * being copied outside of a secure element it must + * also allow #PSA_KEY_USAGE_EXPORT. + * \param[in] attributes The attributes for the new key. + * They are used as follows: + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - The key location (the lifetime and, for + * persistent keys, the key identifier) is + * used directly. + * - The policy constraints (usage flags and + * algorithm policy) are combined from + * the source key and \p attributes so that + * both sets of restrictions apply, as + * described in the documentation of this function. + * \param[out] target_key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE + * \p source_key is invalid. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The lifetime or identifier in \p attributes are invalid, or + * the policy constraints on the source and specified in + * \p attributes are incompatible, or + * \p attributes specifies a key type or key size + * which does not match the attributes of the source key. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key does not have the #PSA_KEY_USAGE_COPY usage flag, or + * the source key is not exportable and its lifetime does not + * allow copying it to the target's lifetime. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *target_key); + +/** Reset a key attribute structure to a freshly initialized state. + * + * You must initialize the attribute structure as described in the + * documentation of the type #psa_key_attributes_t before calling this + * function. Once the structure has been initialized, you may call this + * function at any time. + * + * This function frees any auxiliary resources that the structure + * may contain. + * + * \param[in,out] attributes The attribute structure to reset. + */ +void psa_reset_key_attributes(psa_key_attributes_t *attributes); diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.c b/tests/psa-client-server/psasim/src/psa_sim_serialise.c index 651e0468e2..e655e078f3 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c @@ -63,8 +63,10 @@ typedef struct psasim_operation_s { #define MAX_LIVE_HANDLES_PER_CLASS 100 /* this many slots */ -static psa_hash_operation_t hash_operations[MAX_LIVE_HANDLES_PER_CLASS]; -static psasim_client_handle_t hash_operation_handles[MAX_LIVE_HANDLES_PER_CLASS]; +static psa_hash_operation_t hash_operations[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t hash_operation_handles[ + MAX_LIVE_HANDLES_PER_CLASS]; static psasim_client_handle_t next_hash_operation_handle = 1; /* Get a free slot */ @@ -101,8 +103,10 @@ static ssize_t find_hash_slot_by_handle(psasim_client_handle_t 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 psa_aead_operation_t aead_operations[ + MAX_LIVE_HANDLES_PER_CLASS]; +static psasim_client_handle_t aead_operation_handles[ + MAX_LIVE_HANDLES_PER_CLASS]; static psasim_client_handle_t next_aead_operation_handle = 1; /* Get a free slot */ @@ -139,6 +143,206 @@ static ssize_t find_aead_slot_by_handle(psasim_client_handle_t 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 @@ -213,7 +417,8 @@ int psasim_deserialise_begin(uint8_t **pos, size_t *remaining) return 1; } -size_t psasim_serialise_unsigned_int_needs(unsigned int value) +size_t psasim_serialise_unsigned_int_needs( + unsigned int value) { return sizeof(value); } @@ -248,7 +453,8 @@ int psasim_deserialise_unsigned_int(uint8_t **pos, return 1; } -size_t psasim_serialise_int_needs(int value) +size_t psasim_serialise_int_needs( + int value) { return sizeof(value); } @@ -283,7 +489,8 @@ int psasim_deserialise_int(uint8_t **pos, return 1; } -size_t psasim_serialise_size_t_needs(size_t value) +size_t psasim_serialise_size_t_needs( + size_t value) { return sizeof(value); } @@ -318,6 +525,114 @@ int psasim_deserialise_size_t(uint8_t **pos, return 1; } +size_t psasim_serialise_uint16_t_needs( + uint16_t value) +{ + return sizeof(value); +} + +int psasim_serialise_uint16_t(uint8_t **pos, + size_t *remaining, + uint16_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_uint16_t(uint8_t **pos, + size_t *remaining, + uint16_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_serialise_uint32_t_needs( + uint32_t value) +{ + return sizeof(value); +} + +int psasim_serialise_uint32_t(uint8_t **pos, + size_t *remaining, + uint32_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_uint32_t(uint8_t **pos, + size_t *remaining, + uint32_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_serialise_uint64_t_needs( + uint64_t value) +{ + return sizeof(value); +} + +int psasim_serialise_uint64_t(uint8_t **pos, + size_t *remaining, + uint64_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_uint64_t(uint8_t **pos, + size_t *remaining, + uint64_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size) { (void) buffer; @@ -420,7 +735,102 @@ int psasim_deserialise_return_buffer(uint8_t **pos, return 1; } -size_t psasim_serialise_psa_status_t_needs(psa_status_t value) +#define SER_TAG_SIZE 4 + +size_t psasim_serialise_psa_key_production_parameters_t_needs( + const psa_key_production_parameters_t *params, + size_t data_length) +{ + /* We will serialise with 4-byte tag = "PKPP" + 4-byte overall length at the beginning, + * followed by size_t data_length, then the actual data from the structure. + */ + return SER_TAG_SIZE + sizeof(uint32_t) + sizeof(data_length) + sizeof(*params) + data_length; +} + +int psasim_serialise_psa_key_production_parameters_t(uint8_t **pos, + size_t *remaining, + const psa_key_production_parameters_t *params, + size_t data_length) +{ + if (data_length > UINT32_MAX / 2) { /* arbitrary limit */ + return 0; /* too big to serialise */ + } + + /* We use 32-bit lengths, which should be enough for any reasonable usage :) */ + /* (the UINT32_MAX / 2 above is an even more conservative check to avoid overflow here) */ + uint32_t len = (uint32_t) (sizeof(data_length) + sizeof(*params) + data_length); + if (*remaining < SER_TAG_SIZE + sizeof(uint32_t) + len) { + return 0; + } + + char tag[SER_TAG_SIZE] = "PKPP"; + + memcpy(*pos, tag, sizeof(tag)); + memcpy(*pos + sizeof(tag), &len, sizeof(len)); + *pos += sizeof(tag) + sizeof(len); + *remaining -= sizeof(tag) + sizeof(len); + + memcpy(*pos, &data_length, sizeof(data_length)); + memcpy(*pos + sizeof(data_length), params, sizeof(*params) + data_length); + *pos += sizeof(data_length) + sizeof(*params) + data_length; + *remaining -= sizeof(data_length) + sizeof(*params) + data_length; + + return 1; +} + +int psasim_deserialise_psa_key_production_parameters_t(uint8_t **pos, + size_t *remaining, + psa_key_production_parameters_t **params, + size_t *data_length) +{ + if (*remaining < SER_TAG_SIZE + sizeof(uint32_t)) { + return 0; /* can't even be an empty serialisation */ + } + + char tag[SER_TAG_SIZE] = "PKPP"; /* expected */ + uint32_t len; + + memcpy(&len, *pos + sizeof(tag), sizeof(len)); + + if (memcmp(*pos, tag, sizeof(tag)) != 0) { + return 0; /* wrong tag */ + } + + *pos += sizeof(tag) + sizeof(len); + *remaining -= sizeof(tag) + sizeof(len); + + if (*remaining < sizeof(*data_length)) { + return 0; /* missing data_length */ + } + memcpy(data_length, *pos, sizeof(*data_length)); + + if ((size_t) len != (sizeof(data_length) + sizeof(**params) + *data_length)) { + return 0; /* wrong length */ + } + + if (*remaining < sizeof(*data_length) + sizeof(**params) + *data_length) { + return 0; /* not enough data provided */ + } + + *pos += sizeof(data_length); + *remaining -= sizeof(data_length); + + psa_key_production_parameters_t *out = malloc(sizeof(**params) + *data_length); + if (out == NULL) { + return 0; /* allocation failure */ + } + + memcpy(out, *pos, sizeof(*out) + *data_length); + *pos += sizeof(*out) + *data_length; + *remaining -= sizeof(*out) + *data_length; + + *params = out; + + return 1; +} + +size_t psasim_serialise_psa_status_t_needs( + psa_status_t value) { return psasim_serialise_int_needs(value); } @@ -439,7 +849,8 @@ int psasim_deserialise_psa_status_t(uint8_t **pos, return psasim_deserialise_int(pos, remaining, value); } -size_t psasim_serialise_psa_algorithm_t_needs(psa_algorithm_t value) +size_t psasim_serialise_psa_algorithm_t_needs( + psa_algorithm_t value) { return psasim_serialise_unsigned_int_needs(value); } @@ -458,7 +869,28 @@ int psasim_deserialise_psa_algorithm_t(uint8_t **pos, return psasim_deserialise_unsigned_int(pos, remaining, value); } -size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t value) +size_t psasim_serialise_psa_key_derivation_step_t_needs( + psa_key_derivation_step_t value) +{ + return psasim_serialise_uint16_t_needs(value); +} + +int psasim_serialise_psa_key_derivation_step_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_step_t value) +{ + return psasim_serialise_uint16_t(pos, remaining, value); +} + +int psasim_deserialise_psa_key_derivation_step_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_step_t *value) +{ + return psasim_deserialise_uint16_t(pos, remaining, value); +} + +size_t psasim_serialise_psa_hash_operation_t_needs( + psa_hash_operation_t value) { return sizeof(value); } @@ -493,7 +925,8 @@ int psasim_deserialise_psa_hash_operation_t(uint8_t **pos, return 1; } -size_t psasim_server_serialise_psa_hash_operation_t_needs(psa_hash_operation_t *operation) +size_t psasim_server_serialise_psa_hash_operation_t_needs( + psa_hash_operation_t *operation) { (void) operation; @@ -551,7 +984,8 @@ int psasim_server_deserialise_psa_hash_operation_t(uint8_t **pos, return 1; } -size_t psasim_serialise_psa_aead_operation_t_needs(psa_aead_operation_t value) +size_t psasim_serialise_psa_aead_operation_t_needs( + psa_aead_operation_t value) { return sizeof(value); } @@ -586,7 +1020,8 @@ int psasim_deserialise_psa_aead_operation_t(uint8_t **pos, return 1; } -size_t psasim_server_serialise_psa_aead_operation_t_needs(psa_aead_operation_t *operation) +size_t psasim_server_serialise_psa_aead_operation_t_needs( + psa_aead_operation_t *operation) { (void) operation; @@ -644,7 +1079,8 @@ int psasim_server_deserialise_psa_aead_operation_t(uint8_t **pos, return 1; } -size_t psasim_serialise_psa_key_attributes_t_needs(psa_key_attributes_t value) +size_t psasim_serialise_psa_key_attributes_t_needs( + psa_key_attributes_t value) { return sizeof(value); } @@ -679,7 +1115,483 @@ int psasim_deserialise_psa_key_attributes_t(uint8_t **pos, return 1; } -size_t psasim_serialise_mbedtls_svc_key_id_t_needs(mbedtls_svc_key_id_t value) +size_t psasim_serialise_psa_mac_operation_t_needs( + psa_mac_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_mac_operation_t_needs( + psa_mac_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - mac_operations; + + client_operation.handle = mac_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_mac_operation_slot(); + } else { + slot = find_mac_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &mac_operations[slot]; + + return 1; +} + +size_t psasim_serialise_psa_cipher_operation_t_needs( + psa_cipher_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_cipher_operation_t_needs( + psa_cipher_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t *operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - cipher_operations; + + client_operation.handle = cipher_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_cipher_operation_slot(); + } else { + slot = find_cipher_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &cipher_operations[slot]; + + return 1; +} + +size_t psasim_serialise_psa_key_derivation_operation_t_needs( + psa_key_derivation_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_key_derivation_operation_t_needs( + psa_key_derivation_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t *operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - key_derivation_operations; + + client_operation.handle = key_derivation_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_key_derivation_operation_slot(); + } else { + slot = find_key_derivation_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &key_derivation_operations[slot]; + + return 1; +} + +size_t psasim_serialise_psa_sign_hash_interruptible_operation_t_needs( + psa_sign_hash_interruptible_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs( + psa_sign_hash_interruptible_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t *operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - sign_hash_interruptible_operations; + + client_operation.handle = sign_hash_interruptible_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_sign_hash_interruptible_operation_slot(); + } else { + slot = find_sign_hash_interruptible_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &sign_hash_interruptible_operations[slot]; + + return 1; +} + +size_t psasim_serialise_psa_verify_hash_interruptible_operation_t_needs( + psa_verify_hash_interruptible_operation_t value) +{ + return sizeof(value); +} + +int psasim_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t value) +{ + if (*remaining < sizeof(value)) { + return 0; + } + + memcpy(*pos, &value, sizeof(value)); + *pos += sizeof(value); + + return 1; +} + +int psasim_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t *value) +{ + if (*remaining < sizeof(*value)) { + return 0; + } + + memcpy(value, *pos, sizeof(*value)); + + *pos += sizeof(*value); + *remaining -= sizeof(*value); + + return 1; +} + +size_t psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs( + psa_verify_hash_interruptible_operation_t *operation) +{ + (void) operation; + + /* We will actually return a handle */ + return sizeof(psasim_operation_t); +} + +int psasim_server_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t *operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(client_operation)) { + return 0; + } + + ssize_t slot = operation - verify_hash_interruptible_operations; + + client_operation.handle = verify_hash_interruptible_operation_handles[slot]; + + memcpy(*pos, &client_operation, sizeof(client_operation)); + *pos += sizeof(client_operation); + + return 1; +} + +int psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t **operation) +{ + psasim_operation_t client_operation; + + if (*remaining < sizeof(psasim_operation_t)) { + return 0; + } + + memcpy(&client_operation, *pos, sizeof(psasim_operation_t)); + *pos += sizeof(psasim_operation_t); + *remaining -= sizeof(psasim_operation_t); + + ssize_t slot; + if (client_operation.handle == 0) { /* We need a new handle */ + slot = allocate_verify_hash_interruptible_operation_slot(); + } else { + slot = find_verify_hash_interruptible_slot_by_handle(client_operation.handle); + } + + if (slot < 0) { + return 0; + } + + *operation = &verify_hash_interruptible_operations[slot]; + + return 1; +} + +size_t psasim_serialise_mbedtls_svc_key_id_t_needs( + mbedtls_svc_key_id_t value) { return sizeof(value); } @@ -716,8 +1628,32 @@ int psasim_deserialise_mbedtls_svc_key_id_t(uint8_t **pos, void psa_sim_serialize_reset(void) { - memset(hash_operation_handles, 0, sizeof(hash_operation_handles)); - memset(hash_operations, 0, sizeof(hash_operations)); - memset(aead_operation_handles, 0, sizeof(aead_operation_handles)); - memset(aead_operations, 0, sizeof(aead_operations)); + memset(hash_operation_handles, 0, + sizeof(hash_operation_handles)); + memset(hash_operations, 0, + sizeof(hash_operations)); + memset(aead_operation_handles, 0, + sizeof(aead_operation_handles)); + memset(aead_operations, 0, + sizeof(aead_operations)); + memset(mac_operation_handles, 0, + sizeof(mac_operation_handles)); + memset(mac_operations, 0, + sizeof(mac_operations)); + memset(cipher_operation_handles, 0, + sizeof(cipher_operation_handles)); + memset(cipher_operations, 0, + sizeof(cipher_operations)); + memset(key_derivation_operation_handles, 0, + sizeof(key_derivation_operation_handles)); + memset(key_derivation_operations, 0, + sizeof(key_derivation_operations)); + memset(sign_hash_interruptible_operation_handles, 0, + sizeof(sign_hash_interruptible_operation_handles)); + memset(sign_hash_interruptible_operations, 0, + sizeof(sign_hash_interruptible_operations)); + memset(verify_hash_interruptible_operation_handles, 0, + sizeof(verify_hash_interruptible_operation_handles)); + memset(verify_hash_interruptible_operations, 0, + sizeof(verify_hash_interruptible_operations)); } diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.h b/tests/psa-client-server/psasim/src/psa_sim_serialise.h index 537730c1f8..f85faad606 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h @@ -107,7 +107,8 @@ int psasim_deserialise_begin(uint8_t **pos, size_t *remaining); * \c psasim_serialise_unsigned_int() to serialise * the given value. */ -size_t psasim_serialise_unsigned_int_needs(unsigned int value); +size_t psasim_serialise_unsigned_int_needs( + unsigned int value); /** Serialise an `unsigned int` into a buffer. * @@ -149,7 +150,8 @@ int psasim_deserialise_unsigned_int(uint8_t **pos, * \c psasim_serialise_int() to serialise * the given value. */ -size_t psasim_serialise_int_needs(int value); +size_t psasim_serialise_int_needs( + int value); /** Serialise an `int` into a buffer. * @@ -191,7 +193,8 @@ int psasim_deserialise_int(uint8_t **pos, * \c psasim_serialise_size_t() to serialise * the given value. */ -size_t psasim_serialise_size_t_needs(size_t value); +size_t psasim_serialise_size_t_needs( + size_t value); /** Serialise a `size_t` into a buffer. * @@ -222,6 +225,135 @@ 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. * @@ -289,6 +421,56 @@ int psasim_deserialise_buffer(uint8_t **pos, size_t *remaining, int psasim_deserialise_return_buffer(uint8_t **pos, size_t *remaining, uint8_t *buffer, size_t buffer_length); +/** Return how much space is needed by \c psasim_serialise_psa_key_production_parameters_t() + * to serialise a psa_key_production_parameters_t (a structure with a flexible array member). + * + * \param params Pointer to the struct to be serialised + * (needed in case some serialisations are value- + * dependent). + * \param data_length Number of bytes in the data[] of the struct to be serialised. + * + * \return The number of bytes needed in the serialisation buffer by + * \c psasim_serialise_psa_key_production_parameters_t() to serialise + * the specified structure. + */ +size_t psasim_serialise_psa_key_production_parameters_t_needs( + const psa_key_production_parameters_t *params, + size_t buffer_size); + +/** Serialise a psa_key_production_parameters_t. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param params Pointer to the structure to be serialised. + * \param data_length Number of bytes in the data[] of the struct to be serialised. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_key_production_parameters_t(uint8_t **pos, + size_t *remaining, + const psa_key_production_parameters_t *params, + size_t data_length); + +/** Deserialise a psa_key_production_parameters_t. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the serialisation buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the serialisation buffer. + * \param params Pointer to a `psa_key_production_parameters_t *` to + * receive the address of a newly-allocated structure, + * which the caller must `free()`. + * \param data_length Pointer to a `size_t` to receive the number of + * bytes in the data[] member of the structure deserialised. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_key_production_parameters_t(uint8_t **pos, size_t *remaining, + psa_key_production_parameters_t **params, + size_t *buffer_length); + /** Return how much buffer space is needed by \c psasim_serialise_psa_status_t() * to serialise a `psa_status_t`. * @@ -300,7 +482,8 @@ int psasim_deserialise_return_buffer(uint8_t **pos, size_t *remaining, * \c psasim_serialise_psa_status_t() to serialise * the given value. */ -size_t psasim_serialise_psa_status_t_needs(psa_status_t value); +size_t psasim_serialise_psa_status_t_needs( + psa_status_t value); /** Serialise a `psa_status_t` into a buffer. * @@ -342,7 +525,8 @@ int psasim_deserialise_psa_status_t(uint8_t **pos, * \c psasim_serialise_psa_algorithm_t() to serialise * the given value. */ -size_t psasim_serialise_psa_algorithm_t_needs(psa_algorithm_t value); +size_t psasim_serialise_psa_algorithm_t_needs( + psa_algorithm_t value); /** Serialise a `psa_algorithm_t` into a buffer. * @@ -373,6 +557,49 @@ 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`. * @@ -384,7 +611,8 @@ int psasim_deserialise_psa_algorithm_t(uint8_t **pos, * \c psasim_serialise_psa_hash_operation_t() to serialise * the given value. */ -size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t value); +size_t psasim_serialise_psa_hash_operation_t_needs( + psa_hash_operation_t value); /** Serialise a `psa_hash_operation_t` into a buffer. * @@ -426,7 +654,8 @@ int psasim_deserialise_psa_hash_operation_t(uint8_t **pos, * \c psasim_serialise_psa_hash_operation_t() to serialise * the given value. */ -size_t psasim_server_serialise_psa_hash_operation_t_needs(psa_hash_operation_t *value); +size_t psasim_server_serialise_psa_hash_operation_t_needs( + psa_hash_operation_t *value); /** Serialise a `psa_hash_operation_t` into a buffer on the server side. * @@ -468,7 +697,8 @@ int psasim_server_deserialise_psa_hash_operation_t(uint8_t **pos, * \c psasim_serialise_psa_aead_operation_t() to serialise * the given value. */ -size_t psasim_serialise_psa_aead_operation_t_needs(psa_aead_operation_t value); +size_t psasim_serialise_psa_aead_operation_t_needs( + psa_aead_operation_t value); /** Serialise a `psa_aead_operation_t` into a buffer. * @@ -510,7 +740,8 @@ int psasim_deserialise_psa_aead_operation_t(uint8_t **pos, * \c psasim_serialise_psa_aead_operation_t() to serialise * the given value. */ -size_t psasim_server_serialise_psa_aead_operation_t_needs(psa_aead_operation_t *value); +size_t psasim_server_serialise_psa_aead_operation_t_needs( + psa_aead_operation_t *value); /** Serialise a `psa_aead_operation_t` into a buffer on the server side. * @@ -552,7 +783,8 @@ int psasim_server_deserialise_psa_aead_operation_t(uint8_t **pos, * \c psasim_serialise_psa_key_attributes_t() to serialise * the given value. */ -size_t psasim_serialise_psa_key_attributes_t_needs(psa_key_attributes_t value); +size_t psasim_serialise_psa_key_attributes_t_needs( + psa_key_attributes_t value); /** Serialise a `psa_key_attributes_t` into a buffer. * @@ -583,6 +815,436 @@ 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. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t *value); + +/** Deserialise a `psa_mac_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_mac_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_mac_operation_t(uint8_t **pos, + size_t *remaining, + psa_mac_operation_t **value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_cipher_operation_t() + * to serialise a `psa_cipher_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_cipher_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_cipher_operation_t_needs( + psa_cipher_operation_t value); + +/** Serialise a `psa_cipher_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t value); + +/** Deserialise a `psa_cipher_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_cipher_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_cipher_operation_t() + * to serialise a `psa_cipher_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_cipher_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_cipher_operation_t_needs( + psa_cipher_operation_t *value); + +/** Serialise a `psa_cipher_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t *value); + +/** Deserialise a `psa_cipher_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_cipher_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_cipher_operation_t(uint8_t **pos, + size_t *remaining, + psa_cipher_operation_t **value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_key_derivation_operation_t() + * to serialise a `psa_key_derivation_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_key_derivation_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_key_derivation_operation_t_needs( + psa_key_derivation_operation_t value); + +/** Serialise a `psa_key_derivation_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t value); + +/** Deserialise a `psa_key_derivation_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_key_derivation_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_key_derivation_operation_t() + * to serialise a `psa_key_derivation_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_key_derivation_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_key_derivation_operation_t_needs( + psa_key_derivation_operation_t *value); + +/** Serialise a `psa_key_derivation_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t *value); + +/** Deserialise a `psa_key_derivation_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_key_derivation_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_key_derivation_operation_t(uint8_t **pos, + size_t *remaining, + psa_key_derivation_operation_t **value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_sign_hash_interruptible_operation_t() + * to serialise a `psa_sign_hash_interruptible_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_sign_hash_interruptible_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_sign_hash_interruptible_operation_t_needs( + psa_sign_hash_interruptible_operation_t value); + +/** Serialise a `psa_sign_hash_interruptible_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t value); + +/** Deserialise a `psa_sign_hash_interruptible_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_sign_hash_interruptible_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_sign_hash_interruptible_operation_t() + * to serialise a `psa_sign_hash_interruptible_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_sign_hash_interruptible_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs( + psa_sign_hash_interruptible_operation_t *value); + +/** Serialise a `psa_sign_hash_interruptible_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t *value); + +/** Deserialise a `psa_sign_hash_interruptible_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_sign_hash_interruptible_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_sign_hash_interruptible_operation_t **value); + +/** Return how much buffer space is needed by \c psasim_serialise_psa_verify_hash_interruptible_operation_t() + * to serialise a `psa_verify_hash_interruptible_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_verify_hash_interruptible_operation_t() to serialise + * the given value. + */ +size_t psasim_serialise_psa_verify_hash_interruptible_operation_t_needs( + psa_verify_hash_interruptible_operation_t value); + +/** Serialise a `psa_verify_hash_interruptible_operation_t` into a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t value); + +/** Deserialise a `psa_verify_hash_interruptible_operation_t` from a buffer. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_verify_hash_interruptible_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t *value); + +/** Return how much buffer space is needed by \c psasim_server_serialise_psa_verify_hash_interruptible_operation_t() + * to serialise a `psa_verify_hash_interruptible_operation_t`. + * + * \param value The value that will be serialised into the buffer + * (needed in case some serialisations are value- + * dependent). + * + * \return The number of bytes needed in the buffer by + * \c psasim_serialise_psa_verify_hash_interruptible_operation_t() to serialise + * the given value. + */ +size_t psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs( + psa_verify_hash_interruptible_operation_t *value); + +/** Serialise a `psa_verify_hash_interruptible_operation_t` into a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value The value to serialise into the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_serialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t *value); + +/** Deserialise a `psa_verify_hash_interruptible_operation_t` from a buffer on the server side. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param value Pointer to a `psa_verify_hash_interruptible_operation_t` to receive the value + * deserialised from the buffer. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(uint8_t **pos, + size_t *remaining, + psa_verify_hash_interruptible_operation_t **value); + /** Return how much buffer space is needed by \c psasim_serialise_mbedtls_svc_key_id_t() * to serialise a `mbedtls_svc_key_id_t`. * @@ -594,7 +1256,8 @@ int psasim_deserialise_psa_key_attributes_t(uint8_t **pos, * \c psasim_serialise_mbedtls_svc_key_id_t() to serialise * the given value. */ -size_t psasim_serialise_mbedtls_svc_key_id_t_needs(mbedtls_svc_key_id_t value); +size_t psasim_serialise_mbedtls_svc_key_id_t_needs( + mbedtls_svc_key_id_t value); /** Serialise a `mbedtls_svc_key_id_t` into a buffer. * diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl index e89fafe0be..81808caffc 100755 --- a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl +++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl @@ -36,11 +36,18 @@ die($usage) unless $which eq "c" || $which eq "h"; # are). # my @types = qw(unsigned-int int size_t + uint16_t uint32_t uint64_t buffer - psa_status_t psa_algorithm_t + psa_key_production_parameters_t + psa_status_t psa_algorithm_t psa_key_derivation_step_t psa_hash_operation_t psa_aead_operation_t psa_key_attributes_t + psa_mac_operation_t + psa_cipher_operation_t + psa_key_derivation_operation_t + psa_sign_hash_interruptible_operation_t + psa_verify_hash_interruptible_operation_t mbedtls_svc_key_id_t); grep(s/-/ /g, @types); @@ -49,6 +56,7 @@ grep(s/-/ /g, @types); my %isa = ( "psa_status_t" => "int", "psa_algorithm_t" => "unsigned int", + "psa_key_derivation_step_t" => "uint16_t", ); if ($which eq "h") { @@ -58,6 +66,8 @@ if ($which eq "h") { for my $type (@types) { if ($type eq "buffer") { print declare_buffer_functions(); + } elsif ($type eq "psa_key_production_parameters_t") { + print declare_psa_key_production_parameters_t_functions(); } else { print declare_needs($type, ""); print declare_serialise($type, ""); @@ -88,6 +98,8 @@ if ($which eq "h") { for my $type (@types) { if ($type eq "buffer") { print define_buffer_functions(); + } elsif ($type eq "psa_key_production_parameters_t") { + print define_psa_key_production_parameters_t_functions(); } elsif (exists($isa{$type})) { print define_needs_isa($type, $isa{$type}); print define_serialise_isa($type, $isa{$type}); @@ -133,7 +145,8 @@ sub declare_needs * \\c psasim_serialise_$type_d() to serialise * the given value. */ -size_t psasim_${server}serialise_${type_d}_needs($type ${ptr}value); +size_t psasim_${server}serialise_${type_d}_needs( + $type ${ptr}value); EOF } @@ -271,6 +284,62 @@ int psasim_deserialise_return_buffer(uint8_t **pos, size_t *remaining, EOF } +sub declare_psa_key_production_parameters_t_functions +{ + return <<'EOF'; + +/** Return how much space is needed by \c psasim_serialise_psa_key_production_parameters_t() + * to serialise a psa_key_production_parameters_t (a structure with a flexible array member). + * + * \param params Pointer to the struct to be serialised + * (needed in case some serialisations are value- + * dependent). + * \param data_length Number of bytes in the data[] of the struct to be serialised. + * + * \return The number of bytes needed in the serialisation buffer by + * \c psasim_serialise_psa_key_production_parameters_t() to serialise + * the specified structure. + */ +size_t psasim_serialise_psa_key_production_parameters_t_needs( + const psa_key_production_parameters_t *params, + size_t buffer_size); + +/** Serialise a psa_key_production_parameters_t. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the buffer. + * \param params Pointer to the structure to be serialised. + * \param data_length Number of bytes in the data[] of the struct to be serialised. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_serialise_psa_key_production_parameters_t(uint8_t **pos, + size_t *remaining, + const psa_key_production_parameters_t *params, + size_t data_length); + +/** Deserialise a psa_key_production_parameters_t. + * + * \param pos[in,out] Pointer to a `uint8_t *` holding current position + * in the serialisation buffer. + * \param remaining[in,out] Pointer to a `size_t` holding number of bytes + * remaining in the serialisation buffer. + * \param params Pointer to a `psa_key_production_parameters_t *` to + * receive the address of a newly-allocated structure, + * which the caller must `free()`. + * \param data_length Pointer to a `size_t` to receive the number of + * bytes in the data[] member of the structure deserialised. + * + * \return \c 1 on success ("okay"), \c 0 on error. + */ +int psasim_deserialise_psa_key_production_parameters_t(uint8_t **pos, size_t *remaining, + psa_key_production_parameters_t **params, + size_t *buffer_length); +EOF +} + sub h_header { return <<'EOF'; @@ -383,7 +452,8 @@ sub define_needs return < UINT32_MAX / 2) { /* arbitrary limit */ + return 0; /* too big to serialise */ + } + + /* We use 32-bit lengths, which should be enough for any reasonable usage :) */ + /* (the UINT32_MAX / 2 above is an even more conservative check to avoid overflow here) */ + uint32_t len = (uint32_t) (sizeof(data_length) + sizeof(*params) + data_length); + if (*remaining < SER_TAG_SIZE + sizeof(uint32_t) + len) { + return 0; + } + + char tag[SER_TAG_SIZE] = "PKPP"; + + memcpy(*pos, tag, sizeof(tag)); + memcpy(*pos + sizeof(tag), &len, sizeof(len)); + *pos += sizeof(tag) + sizeof(len); + *remaining -= sizeof(tag) + sizeof(len); + + memcpy(*pos, &data_length, sizeof(data_length)); + memcpy(*pos + sizeof(data_length), params, sizeof(*params) + data_length); + *pos += sizeof(data_length) + sizeof(*params) + data_length; + *remaining -= sizeof(data_length) + sizeof(*params) + data_length; + + return 1; +} + +int psasim_deserialise_psa_key_production_parameters_t(uint8_t **pos, + size_t *remaining, + psa_key_production_parameters_t **params, + size_t *data_length) +{ + if (*remaining < SER_TAG_SIZE + sizeof(uint32_t)) { + return 0; /* can't even be an empty serialisation */ + } + + char tag[SER_TAG_SIZE] = "PKPP"; /* expected */ + uint32_t len; + + memcpy(&len, *pos + sizeof(tag), sizeof(len)); + + if (memcmp(*pos, tag, sizeof(tag)) != 0) { + return 0; /* wrong tag */ + } + + *pos += sizeof(tag) + sizeof(len); + *remaining -= sizeof(tag) + sizeof(len); + + if (*remaining < sizeof(*data_length)) { + return 0; /* missing data_length */ + } + memcpy(data_length, *pos, sizeof(*data_length)); + + if ((size_t) len != (sizeof(data_length) + sizeof(**params) + *data_length)) { + return 0; /* wrong length */ + } + + if (*remaining < sizeof(*data_length) + sizeof(**params) + *data_length) { + return 0; /* not enough data provided */ + } + + *pos += sizeof(data_length); + *remaining -= sizeof(data_length); + + psa_key_production_parameters_t *out = malloc(sizeof(**params) + *data_length); + if (out == NULL) { + return 0; /* allocation failure */ + } + + memcpy(out, *pos, sizeof(*out) + *data_length); + *pos += sizeof(*out) + *data_length; + *remaining -= sizeof(*out) + *data_length; + + *params = out; + + return 1; +} +EOF +} + sub c_header { return <<'EOF'; @@ -800,8 +972,10 @@ sub define_operation_type_data_and_functions return <