/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */

/* server implementations */

/*
 *  Copyright The Mbed TLS Contributors
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 */

#include <stdio.h>
#include <stdlib.h>

#include <psa/crypto.h>

#include "psa_functions_codes.h"
#include "psa_sim_serialise.h"

#include "service.h"

#if !defined(MBEDTLS_PSA_CRYPTO_C)
#error "Error: MBEDTLS_PSA_CRYPTO_C must be enabled on server build"
#endif

#if defined(MBEDTLS_TEST_HOOKS)
void (*mbedtls_test_hook_error_add)(int, int, const char *, int);
#endif

// Returns 1 for success, 0 for failure
int psa_crypto_init_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;

    uint8_t *result = NULL;
    int ok;

    // Now we call the actual target function

    status = psa_crypto_init(
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_abort(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_decrypt_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *nonce = NULL;
    size_t nonce_length;
    uint8_t *additional_data = NULL;
    size_t additional_data_length;
    uint8_t *ciphertext = NULL;
    size_t ciphertext_length;
    uint8_t *plaintext = NULL;
    size_t plaintext_size;
    size_t plaintext_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &nonce, &nonce_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &additional_data, &additional_data_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &ciphertext, &ciphertext_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &plaintext, &plaintext_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &plaintext_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_decrypt(
        key,
        alg,
        nonce, nonce_length,
        additional_data, additional_data_length,
        ciphertext, ciphertext_length,
        plaintext, plaintext_size,
        &plaintext_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(plaintext, plaintext_size) +
        psasim_serialise_size_t_needs(plaintext_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        plaintext, plaintext_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        plaintext_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(nonce);
    free(additional_data);
    free(ciphertext);
    free(plaintext);

    return 1;   // success

fail:
    free(result);

    free(nonce);
    free(additional_data);
    free(ciphertext);
    free(plaintext);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_decrypt_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_decrypt_setup(
        operation,
        key,
        alg
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_encrypt_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *nonce = NULL;
    size_t nonce_length;
    uint8_t *additional_data = NULL;
    size_t additional_data_length;
    uint8_t *plaintext = NULL;
    size_t plaintext_length;
    uint8_t *ciphertext = NULL;
    size_t ciphertext_size;
    size_t ciphertext_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &nonce, &nonce_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &additional_data, &additional_data_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &plaintext, &plaintext_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &ciphertext, &ciphertext_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &ciphertext_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_encrypt(
        key,
        alg,
        nonce, nonce_length,
        additional_data, additional_data_length,
        plaintext, plaintext_length,
        ciphertext, ciphertext_size,
        &ciphertext_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(ciphertext, ciphertext_size) +
        psasim_serialise_size_t_needs(ciphertext_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        ciphertext, ciphertext_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        ciphertext_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(nonce);
    free(additional_data);
    free(plaintext);
    free(ciphertext);

    return 1;   // success

fail:
    free(result);

    free(nonce);
    free(additional_data);
    free(plaintext);
    free(ciphertext);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_encrypt_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_encrypt_setup(
        operation,
        key,
        alg
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_finish_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;
    uint8_t *ciphertext = NULL;
    size_t ciphertext_size;
    size_t ciphertext_length;
    uint8_t *tag = NULL;
    size_t tag_size;
    size_t tag_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &ciphertext, &ciphertext_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &ciphertext_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &tag, &tag_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &tag_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_finish(
        operation,
        ciphertext, ciphertext_size,
        &ciphertext_length,
        tag, tag_size,
        &tag_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(ciphertext, ciphertext_size) +
        psasim_serialise_size_t_needs(ciphertext_length) +
        psasim_serialise_buffer_needs(tag, tag_size) +
        psasim_serialise_size_t_needs(tag_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        ciphertext, ciphertext_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        ciphertext_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        tag, tag_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        tag_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(ciphertext);
    free(tag);

    return 1;   // success

fail:
    free(result);

    free(ciphertext);
    free(tag);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_generate_nonce_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;
    uint8_t *nonce = NULL;
    size_t nonce_size;
    size_t nonce_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &nonce, &nonce_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &nonce_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_generate_nonce(
        operation,
        nonce, nonce_size,
        &nonce_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(nonce, nonce_size) +
        psasim_serialise_size_t_needs(nonce_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        nonce, nonce_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        nonce_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(nonce);

    return 1;   // success

fail:
    free(result);

    free(nonce);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_set_lengths_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;
    size_t ad_length;
    size_t plaintext_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &ad_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &plaintext_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_set_lengths(
        operation,
        ad_length,
        plaintext_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_set_nonce_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;
    uint8_t *nonce = NULL;
    size_t nonce_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &nonce, &nonce_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_set_nonce(
        operation,
        nonce, nonce_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(nonce);

    return 1;   // success

fail:
    free(result);

    free(nonce);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_update_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *output = NULL;
    size_t output_size;
    size_t output_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &output_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_update(
        operation,
        input, input_length,
        output, output_size,
        &output_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(output, output_size) +
        psasim_serialise_size_t_needs(output_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        output_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(output);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_update_ad_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;
    uint8_t *input = NULL;
    size_t input_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_update_ad(
        operation,
        input, input_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);

    return 1;   // success

fail:
    free(result);

    free(input);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_aead_verify_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_aead_operation_t *operation;
    uint8_t *plaintext = NULL;
    size_t plaintext_size;
    size_t plaintext_length;
    uint8_t *tag = NULL;
    size_t tag_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_aead_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &plaintext, &plaintext_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &plaintext_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &tag, &tag_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_aead_verify(
        operation,
        plaintext, plaintext_size,
        &plaintext_length,
        tag, tag_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_aead_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(plaintext, plaintext_size) +
        psasim_serialise_size_t_needs(plaintext_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_aead_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        plaintext, plaintext_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        plaintext_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(plaintext);
    free(tag);

    return 1;   // success

fail:
    free(result);

    free(plaintext);
    free(tag);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_asymmetric_decrypt_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *salt = NULL;
    size_t salt_length;
    uint8_t *output = NULL;
    size_t output_size;
    size_t output_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &salt, &salt_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &output_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_asymmetric_decrypt(
        key,
        alg,
        input, input_length,
        salt, salt_length,
        output, output_size,
        &output_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(output, output_size) +
        psasim_serialise_size_t_needs(output_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        output_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(salt);
    free(output);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(salt);
    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_asymmetric_encrypt_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *salt = NULL;
    size_t salt_length;
    uint8_t *output = NULL;
    size_t output_size;
    size_t output_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &salt, &salt_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &output_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_asymmetric_encrypt(
        key,
        alg,
        input, input_length,
        salt, salt_length,
        output, output_size,
        &output_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(output, output_size) +
        psasim_serialise_size_t_needs(output_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        output_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(salt);
    free(output);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(salt);
    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_can_do_hash_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    int value = 0;
    psa_algorithm_t hash_alg;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &hash_alg);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    value = psa_can_do_hash(
        hash_alg
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_int_needs(value);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_int(
        &rpos, &rremain,
        value);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_cipher_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_cipher_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_cipher_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_cipher_abort(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_cipher_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_cipher_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_cipher_decrypt_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *output = NULL;
    size_t output_size;
    size_t output_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &output_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_cipher_decrypt(
        key,
        alg,
        input, input_length,
        output, output_size,
        &output_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(output, output_size) +
        psasim_serialise_size_t_needs(output_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        output_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(output);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_cipher_decrypt_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_cipher_operation_t *operation;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_cipher_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_cipher_decrypt_setup(
        operation,
        key,
        alg
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_cipher_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_cipher_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_cipher_encrypt_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *output = NULL;
    size_t output_size;
    size_t output_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &output_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_cipher_encrypt(
        key,
        alg,
        input, input_length,
        output, output_size,
        &output_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(output, output_size) +
        psasim_serialise_size_t_needs(output_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        output_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(output);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_cipher_encrypt_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_cipher_operation_t *operation;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_cipher_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_cipher_encrypt_setup(
        operation,
        key,
        alg
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_cipher_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_cipher_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_cipher_finish_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_cipher_operation_t *operation;
    uint8_t *output = NULL;
    size_t output_size;
    size_t output_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_cipher_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &output_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_cipher_finish(
        operation,
        output, output_size,
        &output_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_cipher_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(output, output_size) +
        psasim_serialise_size_t_needs(output_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_cipher_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        output_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(output);

    return 1;   // success

fail:
    free(result);

    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_cipher_generate_iv_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_cipher_operation_t *operation;
    uint8_t *iv = NULL;
    size_t iv_size;
    size_t iv_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_cipher_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &iv, &iv_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &iv_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_cipher_generate_iv(
        operation,
        iv, iv_size,
        &iv_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_cipher_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(iv, iv_size) +
        psasim_serialise_size_t_needs(iv_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_cipher_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        iv, iv_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        iv_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(iv);

    return 1;   // success

fail:
    free(result);

    free(iv);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_cipher_set_iv_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_cipher_operation_t *operation;
    uint8_t *iv = NULL;
    size_t iv_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_cipher_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &iv, &iv_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_cipher_set_iv(
        operation,
        iv, iv_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_cipher_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_cipher_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(iv);

    return 1;   // success

fail:
    free(result);

    free(iv);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_cipher_update_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_cipher_operation_t *operation;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *output = NULL;
    size_t output_size;
    size_t output_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_cipher_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &output_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_cipher_update(
        operation,
        input, input_length,
        output, output_size,
        &output_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_cipher_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(output, output_size) +
        psasim_serialise_size_t_needs(output_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_cipher_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        output_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(output);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_copy_key_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t source_key;
    psa_key_attributes_t attributes;
    mbedtls_svc_key_id_t target_key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &source_key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &target_key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_copy_key(
        source_key,
        &attributes,
        &target_key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_mbedtls_svc_key_id_t_needs(target_key);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_mbedtls_svc_key_id_t(
        &rpos, &rremain,
        target_key);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_destroy_key_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_destroy_key(
        key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_export_key_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    uint8_t *data = NULL;
    size_t data_size;
    size_t data_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &data, &data_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &data_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_export_key(
        key,
        data, data_size,
        &data_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(data, data_size) +
        psasim_serialise_size_t_needs(data_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        data, data_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        data_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(data);

    return 1;   // success

fail:
    free(result);

    free(data);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_export_public_key_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    uint8_t *data = NULL;
    size_t data_size;
    size_t data_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &data, &data_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &data_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_export_public_key(
        key,
        data, data_size,
        &data_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(data, data_size) +
        psasim_serialise_size_t_needs(data_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        data, data_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        data_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(data);

    return 1;   // success

fail:
    free(result);

    free(data);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_export_public_key_iop_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_export_public_key_iop_t operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_export_public_key_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_export_public_key_iop_abort(
        &operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_export_public_key_iop_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_export_public_key_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_export_public_key_iop_complete_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_export_public_key_iop_t operation;
    uint8_t *data = NULL;
    size_t data_size;
    size_t data_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_export_public_key_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &data, &data_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &data_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_export_public_key_iop_complete(
        &operation,
        data, data_size,
        &data_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_export_public_key_iop_t_needs(operation) +
        psasim_serialise_buffer_needs(data, data_size) +
        psasim_serialise_size_t_needs(data_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_export_public_key_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        data, data_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        data_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(data);

    return 1;   // success

fail:
    free(result);

    free(data);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_export_public_key_iop_get_num_ops_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    uint32_t value = 0;
    psa_export_public_key_iop_t operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_export_public_key_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    value = psa_export_public_key_iop_get_num_ops(
        &operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_uint32_t_needs(value) +
        psasim_serialise_psa_export_public_key_iop_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_uint32_t(
        &rpos, &rremain,
        value);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_export_public_key_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_export_public_key_iop_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_export_public_key_iop_t operation;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_export_public_key_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_export_public_key_iop_setup(
        &operation,
        key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_export_public_key_iop_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_export_public_key_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_generate_key_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_attributes_t attributes;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_generate_key(
        &attributes,
        &key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_mbedtls_svc_key_id_t_needs(key);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_mbedtls_svc_key_id_t(
        &rpos, &rremain,
        key);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_generate_key_custom_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_attributes_t attributes;
    psa_custom_key_parameters_t custom;
    uint8_t *custom_data = NULL;
    size_t custom_data_length;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_custom_key_parameters_t(
        &pos, &remaining,
        &custom);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &custom_data, &custom_data_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_generate_key_custom(
        &attributes,
        &custom,
        custom_data, custom_data_length,
        &key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_mbedtls_svc_key_id_t_needs(key);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_mbedtls_svc_key_id_t(
        &rpos, &rremain,
        key);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(custom_data);

    return 1;   // success

fail:
    free(result);

    free(custom_data);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_generate_key_iop_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_generate_key_iop_t operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_generate_key_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_generate_key_iop_abort(
        &operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_generate_key_iop_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_generate_key_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_generate_key_iop_complete_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_generate_key_iop_t operation;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_generate_key_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_generate_key_iop_complete(
        &operation,
        &key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_generate_key_iop_t_needs(operation) +
        psasim_serialise_mbedtls_svc_key_id_t_needs(key);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_generate_key_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_mbedtls_svc_key_id_t(
        &rpos, &rremain,
        key);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_generate_key_iop_get_num_ops_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    uint32_t value = 0;
    psa_generate_key_iop_t operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_generate_key_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    value = psa_generate_key_iop_get_num_ops(
        &operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_uint32_t_needs(value) +
        psasim_serialise_psa_generate_key_iop_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_uint32_t(
        &rpos, &rremain,
        value);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_generate_key_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_generate_key_iop_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_generate_key_iop_t operation;
    psa_key_attributes_t attributes;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_generate_key_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_generate_key_iop_setup(
        &operation,
        &attributes
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_generate_key_iop_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_generate_key_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_generate_random_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    uint8_t *output = NULL;
    size_t output_size;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_size);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_generate_random(
        output, output_size
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(output, output_size);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_size);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(output);

    return 1;   // success

fail:
    free(result);

    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_get_key_attributes_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_key_attributes_t attributes;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_get_key_attributes(
        key,
        &attributes
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_key_attributes_t_needs(attributes);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_key_attributes_t(
        &rpos, &rremain,
        attributes);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_hash_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_hash_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_hash_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_hash_abort(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_hash_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_hash_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_hash_clone_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_hash_operation_t *source_operation;
    psa_hash_operation_t *target_operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_hash_operation_t(
        &pos, &remaining,
        &source_operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_hash_operation_t(
        &pos, &remaining,
        &target_operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_hash_clone(
        source_operation,
        target_operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_hash_operation_t_needs(target_operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_hash_operation_t(
        &rpos, &rremain,
        target_operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_hash_compare_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *hash = NULL;
    size_t hash_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &hash, &hash_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_hash_compare(
        alg,
        input, input_length,
        hash, hash_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(hash);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(hash);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_hash_compute_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *hash = NULL;
    size_t hash_size;
    size_t hash_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &hash, &hash_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &hash_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_hash_compute(
        alg,
        input, input_length,
        hash, hash_size,
        &hash_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(hash, hash_size) +
        psasim_serialise_size_t_needs(hash_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        hash, hash_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        hash_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(hash);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(hash);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_hash_finish_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_hash_operation_t *operation;
    uint8_t *hash = NULL;
    size_t hash_size;
    size_t hash_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_hash_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &hash, &hash_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &hash_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_hash_finish(
        operation,
        hash, hash_size,
        &hash_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_hash_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(hash, hash_size) +
        psasim_serialise_size_t_needs(hash_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_hash_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        hash, hash_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        hash_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(hash);

    return 1;   // success

fail:
    free(result);

    free(hash);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_hash_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_hash_operation_t *operation;
    psa_algorithm_t alg;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_hash_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_hash_setup(
        operation,
        alg
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_hash_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_hash_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_hash_update_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_hash_operation_t *operation;
    uint8_t *input = NULL;
    size_t input_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_hash_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_hash_update(
        operation,
        input, input_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_hash_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_hash_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);

    return 1;   // success

fail:
    free(result);

    free(input);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_hash_verify_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_hash_operation_t *operation;
    uint8_t *hash = NULL;
    size_t hash_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_hash_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &hash, &hash_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_hash_verify(
        operation,
        hash, hash_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_hash_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_hash_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(hash);

    return 1;   // success

fail:
    free(result);

    free(hash);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_import_key_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_attributes_t attributes;
    uint8_t *data = NULL;
    size_t data_length;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &data, &data_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_import_key(
        &attributes,
        data, data_length,
        &key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_mbedtls_svc_key_id_t_needs(key);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_mbedtls_svc_key_id_t(
        &rpos, &rremain,
        key);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(data);

    return 1;   // success

fail:
    free(result);

    free(data);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_interruptible_get_max_ops_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    uint32_t value = 0;

    uint8_t *result = NULL;
    int ok;

    // Now we call the actual target function

    value = psa_interruptible_get_max_ops(
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_uint32_t_needs(value);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_uint32_t(
        &rpos, &rremain,
        value);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_interruptible_set_max_ops_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    uint32_t max_ops;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_uint32_t(
        &pos, &remaining,
        &max_ops);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    psa_interruptible_set_max_ops(
        max_ops
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs();

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_agreement_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t private_key;
    uint8_t *peer_key = NULL;
    size_t peer_key_length;
    psa_algorithm_t alg;
    psa_key_attributes_t attributes;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &private_key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &peer_key, &peer_key_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_agreement(
        private_key,
        peer_key, peer_key_length,
        alg,
        &attributes,
        &key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_mbedtls_svc_key_id_t_needs(key);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_mbedtls_svc_key_id_t(
        &rpos, &rremain,
        key);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(peer_key);

    return 1;   // success

fail:
    free(result);

    free(peer_key);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_agreement_iop_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_agreement_iop_t operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_agreement_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_agreement_iop_abort(
        &operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_key_agreement_iop_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_key_agreement_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_agreement_iop_complete_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_agreement_iop_t operation;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_agreement_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_agreement_iop_complete(
        &operation,
        &key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_key_agreement_iop_t_needs(operation) +
        psasim_serialise_mbedtls_svc_key_id_t_needs(key);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_key_agreement_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_mbedtls_svc_key_id_t(
        &rpos, &rremain,
        key);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_agreement_iop_get_num_ops_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    uint32_t value = 0;
    psa_key_agreement_iop_t operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_agreement_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    value = psa_key_agreement_iop_get_num_ops(
        &operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_uint32_t_needs(value) +
        psasim_serialise_psa_key_agreement_iop_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_uint32_t(
        &rpos, &rremain,
        value);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_key_agreement_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_agreement_iop_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_agreement_iop_t operation;
    mbedtls_svc_key_id_t private_key;
    uint8_t *peer_key = NULL;
    size_t peer_key_length;
    psa_algorithm_t alg;
    psa_key_attributes_t attributes;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_agreement_iop_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &private_key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &peer_key, &peer_key_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_agreement_iop_setup(
        &operation,
        private_key,
        peer_key, peer_key_length,
        alg,
        &attributes
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_psa_key_agreement_iop_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_key_agreement_iop_t(
        &rpos, &rremain,
        operation);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(peer_key);

    return 1;   // success

fail:
    free(result);

    free(peer_key);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_derivation_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_abort(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_get_capacity_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_derivation_operation_t *operation;
    size_t capacity;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &capacity);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_get_capacity(
        operation,
        &capacity
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_size_t_needs(capacity);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        capacity);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_input_bytes_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_derivation_operation_t *operation;
    psa_key_derivation_step_t step;
    uint8_t *data = NULL;
    size_t data_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_derivation_step_t(
        &pos, &remaining,
        &step);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &data, &data_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_input_bytes(
        operation,
        step,
        data, data_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(data);

    return 1;   // success

fail:
    free(result);

    free(data);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_input_integer_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_derivation_operation_t *operation;
    psa_key_derivation_step_t step;
    uint64_t value;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_derivation_step_t(
        &pos, &remaining,
        &step);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_uint64_t(
        &pos, &remaining,
        &value);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_input_integer(
        operation,
        step,
        value
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_input_key_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_derivation_operation_t *operation;
    psa_key_derivation_step_t step;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_derivation_step_t(
        &pos, &remaining,
        &step);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_input_key(
        operation,
        step,
        key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_key_agreement_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_derivation_operation_t *operation;
    psa_key_derivation_step_t step;
    mbedtls_svc_key_id_t private_key;
    uint8_t *peer_key = NULL;
    size_t peer_key_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_derivation_step_t(
        &pos, &remaining,
        &step);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &private_key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &peer_key, &peer_key_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_key_agreement(
        operation,
        step,
        private_key,
        peer_key, peer_key_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(peer_key);

    return 1;   // success

fail:
    free(result);

    free(peer_key);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_output_bytes_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_derivation_operation_t *operation;
    uint8_t *output = NULL;
    size_t output_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_output_bytes(
        operation,
        output, output_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(output, output_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(output);

    return 1;   // success

fail:
    free(result);

    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_output_key_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_attributes_t attributes;
    psa_key_derivation_operation_t *operation;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_output_key(
        &attributes,
        operation,
        &key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation) +
        psasim_serialise_mbedtls_svc_key_id_t_needs(key);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_mbedtls_svc_key_id_t(
        &rpos, &rremain,
        key);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_output_key_custom_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_attributes_t attributes;
    psa_key_derivation_operation_t *operation;
    psa_custom_key_parameters_t custom;
    uint8_t *custom_data = NULL;
    size_t custom_data_length;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_custom_key_parameters_t(
        &pos, &remaining,
        &custom);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &custom_data, &custom_data_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_output_key_custom(
        &attributes,
        operation,
        &custom,
        custom_data, custom_data_length,
        &key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation) +
        psasim_serialise_mbedtls_svc_key_id_t_needs(key);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_mbedtls_svc_key_id_t(
        &rpos, &rremain,
        key);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(custom_data);

    return 1;   // success

fail:
    free(result);

    free(custom_data);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_set_capacity_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_derivation_operation_t *operation;
    size_t capacity;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &capacity);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_set_capacity(
        operation,
        capacity
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_key_derivation_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_key_derivation_operation_t *operation;
    psa_algorithm_t alg;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_key_derivation_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_key_derivation_setup(
        operation,
        alg
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_key_derivation_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_key_derivation_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_mac_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_mac_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_mac_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_mac_abort(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_mac_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_mac_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_mac_compute_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *mac = NULL;
    size_t mac_size;
    size_t mac_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &mac, &mac_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &mac_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_mac_compute(
        key,
        alg,
        input, input_length,
        mac, mac_size,
        &mac_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(mac, mac_size) +
        psasim_serialise_size_t_needs(mac_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        mac, mac_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        mac_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(mac);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(mac);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_mac_sign_finish_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_mac_operation_t *operation;
    uint8_t *mac = NULL;
    size_t mac_size;
    size_t mac_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_mac_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &mac, &mac_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &mac_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_mac_sign_finish(
        operation,
        mac, mac_size,
        &mac_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_mac_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(mac, mac_size) +
        psasim_serialise_size_t_needs(mac_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_mac_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        mac, mac_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        mac_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(mac);

    return 1;   // success

fail:
    free(result);

    free(mac);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_mac_sign_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_mac_operation_t *operation;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_mac_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_mac_sign_setup(
        operation,
        key,
        alg
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_mac_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_mac_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_mac_update_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_mac_operation_t *operation;
    uint8_t *input = NULL;
    size_t input_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_mac_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_mac_update(
        operation,
        input, input_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_mac_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_mac_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);

    return 1;   // success

fail:
    free(result);

    free(input);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_mac_verify_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *mac = NULL;
    size_t mac_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &mac, &mac_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_mac_verify(
        key,
        alg,
        input, input_length,
        mac, mac_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(mac);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(mac);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_mac_verify_finish_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_mac_operation_t *operation;
    uint8_t *mac = NULL;
    size_t mac_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_mac_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &mac, &mac_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_mac_verify_finish(
        operation,
        mac, mac_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_mac_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_mac_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(mac);

    return 1;   // success

fail:
    free(result);

    free(mac);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_mac_verify_setup_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_mac_operation_t *operation;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_mac_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_mac_verify_setup(
        operation,
        key,
        alg
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_mac_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_mac_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_purge_key_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_purge_key(
        key
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_raw_key_agreement_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_algorithm_t alg;
    mbedtls_svc_key_id_t private_key;
    uint8_t *peer_key = NULL;
    size_t peer_key_length;
    uint8_t *output = NULL;
    size_t output_size;
    size_t output_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &private_key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &peer_key, &peer_key_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &output, &output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &output_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_raw_key_agreement(
        alg,
        private_key,
        peer_key, peer_key_length,
        output, output_size,
        &output_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(output, output_size) +
        psasim_serialise_size_t_needs(output_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        output, output_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        output_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(peer_key);
    free(output);

    return 1;   // success

fail:
    free(result);

    free(peer_key);
    free(output);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_reset_key_attributes_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_key_attributes_t attributes;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_key_attributes_t(
        &pos, &remaining,
        &attributes);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    psa_reset_key_attributes(
        &attributes
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_key_attributes_t_needs(attributes);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_key_attributes_t(
        &rpos, &rremain,
        attributes);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_sign_hash_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *hash = NULL;
    size_t hash_length;
    uint8_t *signature = NULL;
    size_t signature_size;
    size_t signature_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &hash, &hash_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &signature, &signature_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &signature_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_sign_hash(
        key,
        alg,
        hash, hash_length,
        signature, signature_size,
        &signature_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(signature, signature_size) +
        psasim_serialise_size_t_needs(signature_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        signature, signature_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        signature_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(hash);
    free(signature);

    return 1;   // success

fail:
    free(result);

    free(hash);
    free(signature);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_sign_hash_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_sign_hash_interruptible_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_sign_hash_abort(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_sign_hash_complete_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_sign_hash_interruptible_operation_t *operation;
    uint8_t *signature = NULL;
    size_t signature_size;
    size_t signature_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &signature, &signature_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &signature_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_sign_hash_complete(
        operation,
        signature, signature_size,
        &signature_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation) +
        psasim_serialise_buffer_needs(signature, signature_size) +
        psasim_serialise_size_t_needs(signature_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        signature, signature_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        signature_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(signature);

    return 1;   // success

fail:
    free(result);

    free(signature);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_sign_hash_get_num_ops_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    uint32_t value = 0;
    psa_sign_hash_interruptible_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    value = psa_sign_hash_get_num_ops(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_uint32_t_needs(value);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_uint32_t(
        &rpos, &rremain,
        value);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_sign_hash_start_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_sign_hash_interruptible_operation_t *operation;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *hash = NULL;
    size_t hash_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_sign_hash_interruptible_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &hash, &hash_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_sign_hash_start(
        operation,
        key,
        alg,
        hash, hash_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_sign_hash_interruptible_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_sign_hash_interruptible_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(hash);

    return 1;   // success

fail:
    free(result);

    free(hash);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_sign_message_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *signature = NULL;
    size_t signature_size;
    size_t signature_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &signature, &signature_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_size_t(
        &pos, &remaining,
        &signature_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_sign_message(
        key,
        alg,
        input, input_length,
        signature, signature_size,
        &signature_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_serialise_buffer_needs(signature, signature_size) +
        psasim_serialise_size_t_needs(signature_length);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_buffer(
        &rpos, &rremain,
        signature, signature_size);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_size_t(
        &rpos, &rremain,
        signature_length);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(signature);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(signature);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_verify_hash_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *hash = NULL;
    size_t hash_length;
    uint8_t *signature = NULL;
    size_t signature_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &hash, &hash_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &signature, &signature_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_verify_hash(
        key,
        alg,
        hash, hash_length,
        signature, signature_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(hash);
    free(signature);

    return 1;   // success

fail:
    free(result);

    free(hash);
    free(signature);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_verify_hash_abort_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_verify_hash_interruptible_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_verify_hash_abort(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t(
        &rpos, &rremain,
        operation, 1);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_verify_hash_complete_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_verify_hash_interruptible_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_verify_hash_complete(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_verify_hash_get_num_ops_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    uint32_t value = 0;
    psa_verify_hash_interruptible_operation_t *operation;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    value = psa_verify_hash_get_num_ops(
        operation
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_uint32_t_needs(value);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_uint32_t(
        &rpos, &rremain,
        value);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    return 1;   // success

fail:
    free(result);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_verify_hash_start_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    psa_verify_hash_interruptible_operation_t *operation;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *hash = NULL;
    size_t hash_length;
    uint8_t *signature = NULL;
    size_t signature_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_deserialise_psa_verify_hash_interruptible_operation_t(
        &pos, &remaining,
        &operation);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &hash, &hash_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &signature, &signature_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_verify_hash_start(
        operation,
        key,
        alg,
        hash, hash_length,
        signature, signature_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status) +
        psasim_server_serialise_psa_verify_hash_interruptible_operation_t_needs(operation);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    ok = psasim_server_serialise_psa_verify_hash_interruptible_operation_t(
        &rpos, &rremain,
        operation, 0);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(hash);
    free(signature);

    return 1;   // success

fail:
    free(result);

    free(hash);
    free(signature);

    return 0;       // This shouldn't happen!
}

// Returns 1 for success, 0 for failure
int psa_verify_message_wrapper(
    uint8_t *in_params, size_t in_params_len,
    uint8_t **out_params, size_t *out_params_len)
{
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_svc_key_id_t key;
    psa_algorithm_t alg;
    uint8_t *input = NULL;
    size_t input_length;
    uint8_t *signature = NULL;
    size_t signature_length;

    uint8_t *pos = in_params;
    size_t remaining = in_params_len;
    uint8_t *result = NULL;
    int ok;

    ok = psasim_deserialise_begin(&pos, &remaining);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_mbedtls_svc_key_id_t(
        &pos, &remaining,
        &key);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_psa_algorithm_t(
        &pos, &remaining,
        &alg);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &input, &input_length);
    if (!ok) {
        goto fail;
    }

    ok = psasim_deserialise_buffer(
        &pos, &remaining,
        &signature, &signature_length);
    if (!ok) {
        goto fail;
    }

    // Now we call the actual target function

    status = psa_verify_message(
        key,
        alg,
        input, input_length,
        signature, signature_length
        );

    // NOTE: Should really check there is no overflow as we go along.
    size_t result_size =
        psasim_serialise_begin_needs() +
        psasim_serialise_psa_status_t_needs(status);

    result = malloc(result_size);
    if (result == NULL) {
        goto fail;
    }

    uint8_t *rpos = result;
    size_t rremain = result_size;

    ok = psasim_serialise_begin(&rpos, &rremain);
    if (!ok) {
        goto fail;
    }

    ok = psasim_serialise_psa_status_t(
        &rpos, &rremain,
        status);
    if (!ok) {
        goto fail;
    }

    *out_params = result;
    *out_params_len = result_size;

    free(input);
    free(signature);

    return 1;   // success

fail:
    free(result);

    free(input);
    free(signature);

    return 0;       // This shouldn't happen!
}

psa_status_t psa_crypto_call(psa_msg_t msg)
{
    int ok = 0;

    int func = msg.type;

    /* We only expect a single input buffer, with everything serialised in it */
    if (msg.in_size[1] != 0 || msg.in_size[2] != 0 || msg.in_size[3] != 0) {
        return PSA_ERROR_INVALID_ARGUMENT;
    }

    /* We expect exactly 2 output buffers, one for size, the other for data */
    if (msg.out_size[0] != sizeof(size_t) || msg.out_size[1] == 0 ||
        msg.out_size[2] != 0 || msg.out_size[3] != 0) {
        return PSA_ERROR_INVALID_ARGUMENT;
    }

    uint8_t *in_params = NULL;
    size_t in_params_len = 0;
    uint8_t *out_params = NULL;
    size_t out_params_len = 0;

    in_params_len = msg.in_size[0];
    in_params = malloc(in_params_len);
    if (in_params == NULL) {
        return PSA_ERROR_INSUFFICIENT_MEMORY;
    }

    /* Read the bytes from the client */
    size_t actual = psa_read(msg.handle, 0, in_params, in_params_len);
    if (actual != in_params_len) {
        free(in_params);
        return PSA_ERROR_CORRUPTION_DETECTED;
    }

    switch (func) {
        case PSA_CRYPTO_INIT:
            ok = psa_crypto_init_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_AEAD_ABORT:
            ok = psa_aead_abort_wrapper(in_params, in_params_len,
                                        &out_params, &out_params_len);
            break;
        case PSA_AEAD_DECRYPT:
            ok = psa_aead_decrypt_wrapper(in_params, in_params_len,
                                          &out_params, &out_params_len);
            break;
        case PSA_AEAD_DECRYPT_SETUP:
            ok = psa_aead_decrypt_setup_wrapper(in_params, in_params_len,
                                                &out_params, &out_params_len);
            break;
        case PSA_AEAD_ENCRYPT:
            ok = psa_aead_encrypt_wrapper(in_params, in_params_len,
                                          &out_params, &out_params_len);
            break;
        case PSA_AEAD_ENCRYPT_SETUP:
            ok = psa_aead_encrypt_setup_wrapper(in_params, in_params_len,
                                                &out_params, &out_params_len);
            break;
        case PSA_AEAD_FINISH:
            ok = psa_aead_finish_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_AEAD_GENERATE_NONCE:
            ok = psa_aead_generate_nonce_wrapper(in_params, in_params_len,
                                                 &out_params, &out_params_len);
            break;
        case PSA_AEAD_SET_LENGTHS:
            ok = psa_aead_set_lengths_wrapper(in_params, in_params_len,
                                              &out_params, &out_params_len);
            break;
        case PSA_AEAD_SET_NONCE:
            ok = psa_aead_set_nonce_wrapper(in_params, in_params_len,
                                            &out_params, &out_params_len);
            break;
        case PSA_AEAD_UPDATE:
            ok = psa_aead_update_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_AEAD_UPDATE_AD:
            ok = psa_aead_update_ad_wrapper(in_params, in_params_len,
                                            &out_params, &out_params_len);
            break;
        case PSA_AEAD_VERIFY:
            ok = psa_aead_verify_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_ASYMMETRIC_DECRYPT:
            ok = psa_asymmetric_decrypt_wrapper(in_params, in_params_len,
                                                &out_params, &out_params_len);
            break;
        case PSA_ASYMMETRIC_ENCRYPT:
            ok = psa_asymmetric_encrypt_wrapper(in_params, in_params_len,
                                                &out_params, &out_params_len);
            break;
        case PSA_CAN_DO_HASH:
            ok = psa_can_do_hash_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_CIPHER_ABORT:
            ok = psa_cipher_abort_wrapper(in_params, in_params_len,
                                          &out_params, &out_params_len);
            break;
        case PSA_CIPHER_DECRYPT:
            ok = psa_cipher_decrypt_wrapper(in_params, in_params_len,
                                            &out_params, &out_params_len);
            break;
        case PSA_CIPHER_DECRYPT_SETUP:
            ok = psa_cipher_decrypt_setup_wrapper(in_params, in_params_len,
                                                  &out_params, &out_params_len);
            break;
        case PSA_CIPHER_ENCRYPT:
            ok = psa_cipher_encrypt_wrapper(in_params, in_params_len,
                                            &out_params, &out_params_len);
            break;
        case PSA_CIPHER_ENCRYPT_SETUP:
            ok = psa_cipher_encrypt_setup_wrapper(in_params, in_params_len,
                                                  &out_params, &out_params_len);
            break;
        case PSA_CIPHER_FINISH:
            ok = psa_cipher_finish_wrapper(in_params, in_params_len,
                                           &out_params, &out_params_len);
            break;
        case PSA_CIPHER_GENERATE_IV:
            ok = psa_cipher_generate_iv_wrapper(in_params, in_params_len,
                                                &out_params, &out_params_len);
            break;
        case PSA_CIPHER_SET_IV:
            ok = psa_cipher_set_iv_wrapper(in_params, in_params_len,
                                           &out_params, &out_params_len);
            break;
        case PSA_CIPHER_UPDATE:
            ok = psa_cipher_update_wrapper(in_params, in_params_len,
                                           &out_params, &out_params_len);
            break;
        case PSA_COPY_KEY:
            ok = psa_copy_key_wrapper(in_params, in_params_len,
                                      &out_params, &out_params_len);
            break;
        case PSA_DESTROY_KEY:
            ok = psa_destroy_key_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_EXPORT_KEY:
            ok = psa_export_key_wrapper(in_params, in_params_len,
                                        &out_params, &out_params_len);
            break;
        case PSA_EXPORT_PUBLIC_KEY:
            ok = psa_export_public_key_wrapper(in_params, in_params_len,
                                               &out_params, &out_params_len);
            break;
        case PSA_EXPORT_PUBLIC_KEY_IOP_ABORT:
            ok = psa_export_public_key_iop_abort_wrapper(in_params, in_params_len,
                                                         &out_params, &out_params_len);
            break;
        case PSA_EXPORT_PUBLIC_KEY_IOP_COMPLETE:
            ok = psa_export_public_key_iop_complete_wrapper(in_params, in_params_len,
                                                            &out_params, &out_params_len);
            break;
        case PSA_EXPORT_PUBLIC_KEY_IOP_GET_NUM_OPS:
            ok = psa_export_public_key_iop_get_num_ops_wrapper(in_params, in_params_len,
                                                               &out_params, &out_params_len);
            break;
        case PSA_EXPORT_PUBLIC_KEY_IOP_SETUP:
            ok = psa_export_public_key_iop_setup_wrapper(in_params, in_params_len,
                                                         &out_params, &out_params_len);
            break;
        case PSA_GENERATE_KEY:
            ok = psa_generate_key_wrapper(in_params, in_params_len,
                                          &out_params, &out_params_len);
            break;
        case PSA_GENERATE_KEY_CUSTOM:
            ok = psa_generate_key_custom_wrapper(in_params, in_params_len,
                                                 &out_params, &out_params_len);
            break;
        case PSA_GENERATE_KEY_IOP_ABORT:
            ok = psa_generate_key_iop_abort_wrapper(in_params, in_params_len,
                                                    &out_params, &out_params_len);
            break;
        case PSA_GENERATE_KEY_IOP_COMPLETE:
            ok = psa_generate_key_iop_complete_wrapper(in_params, in_params_len,
                                                       &out_params, &out_params_len);
            break;
        case PSA_GENERATE_KEY_IOP_GET_NUM_OPS:
            ok = psa_generate_key_iop_get_num_ops_wrapper(in_params, in_params_len,
                                                          &out_params, &out_params_len);
            break;
        case PSA_GENERATE_KEY_IOP_SETUP:
            ok = psa_generate_key_iop_setup_wrapper(in_params, in_params_len,
                                                    &out_params, &out_params_len);
            break;
        case PSA_GENERATE_RANDOM:
            ok = psa_generate_random_wrapper(in_params, in_params_len,
                                             &out_params, &out_params_len);
            break;
        case PSA_GET_KEY_ATTRIBUTES:
            ok = psa_get_key_attributes_wrapper(in_params, in_params_len,
                                                &out_params, &out_params_len);
            break;
        case PSA_HASH_ABORT:
            ok = psa_hash_abort_wrapper(in_params, in_params_len,
                                        &out_params, &out_params_len);
            break;
        case PSA_HASH_CLONE:
            ok = psa_hash_clone_wrapper(in_params, in_params_len,
                                        &out_params, &out_params_len);
            break;
        case PSA_HASH_COMPARE:
            ok = psa_hash_compare_wrapper(in_params, in_params_len,
                                          &out_params, &out_params_len);
            break;
        case PSA_HASH_COMPUTE:
            ok = psa_hash_compute_wrapper(in_params, in_params_len,
                                          &out_params, &out_params_len);
            break;
        case PSA_HASH_FINISH:
            ok = psa_hash_finish_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_HASH_SETUP:
            ok = psa_hash_setup_wrapper(in_params, in_params_len,
                                        &out_params, &out_params_len);
            break;
        case PSA_HASH_UPDATE:
            ok = psa_hash_update_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_HASH_VERIFY:
            ok = psa_hash_verify_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_IMPORT_KEY:
            ok = psa_import_key_wrapper(in_params, in_params_len,
                                        &out_params, &out_params_len);
            break;
        case PSA_INTERRUPTIBLE_GET_MAX_OPS:
            ok = psa_interruptible_get_max_ops_wrapper(in_params, in_params_len,
                                                       &out_params, &out_params_len);
            break;
        case PSA_INTERRUPTIBLE_SET_MAX_OPS:
            ok = psa_interruptible_set_max_ops_wrapper(in_params, in_params_len,
                                                       &out_params, &out_params_len);
            break;
        case PSA_KEY_AGREEMENT:
            ok = psa_key_agreement_wrapper(in_params, in_params_len,
                                           &out_params, &out_params_len);
            break;
        case PSA_KEY_AGREEMENT_IOP_ABORT:
            ok = psa_key_agreement_iop_abort_wrapper(in_params, in_params_len,
                                                     &out_params, &out_params_len);
            break;
        case PSA_KEY_AGREEMENT_IOP_COMPLETE:
            ok = psa_key_agreement_iop_complete_wrapper(in_params, in_params_len,
                                                        &out_params, &out_params_len);
            break;
        case PSA_KEY_AGREEMENT_IOP_GET_NUM_OPS:
            ok = psa_key_agreement_iop_get_num_ops_wrapper(in_params, in_params_len,
                                                           &out_params, &out_params_len);
            break;
        case PSA_KEY_AGREEMENT_IOP_SETUP:
            ok = psa_key_agreement_iop_setup_wrapper(in_params, in_params_len,
                                                     &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_ABORT:
            ok = psa_key_derivation_abort_wrapper(in_params, in_params_len,
                                                  &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_GET_CAPACITY:
            ok = psa_key_derivation_get_capacity_wrapper(in_params, in_params_len,
                                                         &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_INPUT_BYTES:
            ok = psa_key_derivation_input_bytes_wrapper(in_params, in_params_len,
                                                        &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_INPUT_INTEGER:
            ok = psa_key_derivation_input_integer_wrapper(in_params, in_params_len,
                                                          &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_INPUT_KEY:
            ok = psa_key_derivation_input_key_wrapper(in_params, in_params_len,
                                                      &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_KEY_AGREEMENT:
            ok = psa_key_derivation_key_agreement_wrapper(in_params, in_params_len,
                                                          &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_OUTPUT_BYTES:
            ok = psa_key_derivation_output_bytes_wrapper(in_params, in_params_len,
                                                         &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_OUTPUT_KEY:
            ok = psa_key_derivation_output_key_wrapper(in_params, in_params_len,
                                                       &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_OUTPUT_KEY_CUSTOM:
            ok = psa_key_derivation_output_key_custom_wrapper(in_params, in_params_len,
                                                              &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_SET_CAPACITY:
            ok = psa_key_derivation_set_capacity_wrapper(in_params, in_params_len,
                                                         &out_params, &out_params_len);
            break;
        case PSA_KEY_DERIVATION_SETUP:
            ok = psa_key_derivation_setup_wrapper(in_params, in_params_len,
                                                  &out_params, &out_params_len);
            break;
        case PSA_MAC_ABORT:
            ok = psa_mac_abort_wrapper(in_params, in_params_len,
                                       &out_params, &out_params_len);
            break;
        case PSA_MAC_COMPUTE:
            ok = psa_mac_compute_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_MAC_SIGN_FINISH:
            ok = psa_mac_sign_finish_wrapper(in_params, in_params_len,
                                             &out_params, &out_params_len);
            break;
        case PSA_MAC_SIGN_SETUP:
            ok = psa_mac_sign_setup_wrapper(in_params, in_params_len,
                                            &out_params, &out_params_len);
            break;
        case PSA_MAC_UPDATE:
            ok = psa_mac_update_wrapper(in_params, in_params_len,
                                        &out_params, &out_params_len);
            break;
        case PSA_MAC_VERIFY:
            ok = psa_mac_verify_wrapper(in_params, in_params_len,
                                        &out_params, &out_params_len);
            break;
        case PSA_MAC_VERIFY_FINISH:
            ok = psa_mac_verify_finish_wrapper(in_params, in_params_len,
                                               &out_params, &out_params_len);
            break;
        case PSA_MAC_VERIFY_SETUP:
            ok = psa_mac_verify_setup_wrapper(in_params, in_params_len,
                                              &out_params, &out_params_len);
            break;
        case PSA_PURGE_KEY:
            ok = psa_purge_key_wrapper(in_params, in_params_len,
                                       &out_params, &out_params_len);
            break;
        case PSA_RAW_KEY_AGREEMENT:
            ok = psa_raw_key_agreement_wrapper(in_params, in_params_len,
                                               &out_params, &out_params_len);
            break;
        case PSA_RESET_KEY_ATTRIBUTES:
            ok = psa_reset_key_attributes_wrapper(in_params, in_params_len,
                                                  &out_params, &out_params_len);
            break;
        case PSA_SIGN_HASH:
            ok = psa_sign_hash_wrapper(in_params, in_params_len,
                                       &out_params, &out_params_len);
            break;
        case PSA_SIGN_HASH_ABORT:
            ok = psa_sign_hash_abort_wrapper(in_params, in_params_len,
                                             &out_params, &out_params_len);
            break;
        case PSA_SIGN_HASH_COMPLETE:
            ok = psa_sign_hash_complete_wrapper(in_params, in_params_len,
                                                &out_params, &out_params_len);
            break;
        case PSA_SIGN_HASH_GET_NUM_OPS:
            ok = psa_sign_hash_get_num_ops_wrapper(in_params, in_params_len,
                                                   &out_params, &out_params_len);
            break;
        case PSA_SIGN_HASH_START:
            ok = psa_sign_hash_start_wrapper(in_params, in_params_len,
                                             &out_params, &out_params_len);
            break;
        case PSA_SIGN_MESSAGE:
            ok = psa_sign_message_wrapper(in_params, in_params_len,
                                          &out_params, &out_params_len);
            break;
        case PSA_VERIFY_HASH:
            ok = psa_verify_hash_wrapper(in_params, in_params_len,
                                         &out_params, &out_params_len);
            break;
        case PSA_VERIFY_HASH_ABORT:
            ok = psa_verify_hash_abort_wrapper(in_params, in_params_len,
                                               &out_params, &out_params_len);
            break;
        case PSA_VERIFY_HASH_COMPLETE:
            ok = psa_verify_hash_complete_wrapper(in_params, in_params_len,
                                                  &out_params, &out_params_len);
            break;
        case PSA_VERIFY_HASH_GET_NUM_OPS:
            ok = psa_verify_hash_get_num_ops_wrapper(in_params, in_params_len,
                                                     &out_params, &out_params_len);
            break;
        case PSA_VERIFY_HASH_START:
            ok = psa_verify_hash_start_wrapper(in_params, in_params_len,
                                               &out_params, &out_params_len);
            break;
        case PSA_VERIFY_MESSAGE:
            ok = psa_verify_message_wrapper(in_params, in_params_len,
                                            &out_params, &out_params_len);
            break;
    }

    free(in_params);

    if (out_params_len > msg.out_size[1]) {
        fprintf(stderr, "unable to write %zu bytes into buffer of %zu bytes\n",
                out_params_len, msg.out_size[1]);
        exit(1);
    }

    /* Write the exact amount of data we're returning */
    psa_write(msg.handle, 0, &out_params_len, sizeof(out_params_len));

    /* And write the data itself */
    if (out_params_len) {
        psa_write(msg.handle, 1, out_params, out_params_len);
    }

    free(out_params);

    return ok ? PSA_SUCCESS : PSA_ERROR_GENERIC_ERROR;
}

void psa_crypto_close(void)
{
    psa_sim_serialize_reset();
}
