mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-02-21 06:40:50 +00:00
Merge pull request #9198 from tom-cosgrove-arm/psa-sim-hashing
Test psa_hash_xxx() APIs in the PSA crypto simulator
This commit is contained in:
commit
30a9b6f2fc
@ -1,3 +1,5 @@
|
||||
MAIN ?= src/client.c
|
||||
|
||||
CFLAGS += -Wall -Werror -std=c99 -D_XOPEN_SOURCE=1 -D_POSIX_C_SOURCE=200809L
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
@ -18,12 +20,16 @@ GENERATED_H_FILES = include/psa_manifest/manifest.h \
|
||||
include/psa_manifest/sid.h
|
||||
|
||||
PSA_CLIENT_SRC = src/psa_ff_client.c \
|
||||
src/client.c
|
||||
$(MAIN) \
|
||||
src/psa_sim_crypto_client.c \
|
||||
src/psa_sim_serialise.c
|
||||
|
||||
PARTITION_SERVER_BOOTSTRAP = src/psa_ff_bootstrap_TEST_PARTITION.c
|
||||
|
||||
PSA_SERVER_SRC = $(PARTITION_SERVER_BOOTSTRAP) \
|
||||
src/psa_ff_server.c
|
||||
src/psa_ff_server.c \
|
||||
src/psa_sim_crypto_server.c \
|
||||
src/psa_sim_serialise.c
|
||||
|
||||
.PHONY: all clean libpsaclient libpsaserver
|
||||
|
||||
|
112
tests/psa-client-server/psasim/src/aut_psa_hash_compute.c
Normal file
112
tests/psa-client-server/psasim/src/aut_psa_hash_compute.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* API(s) under test: psa_hash_compute()
|
||||
*
|
||||
* Taken from programs/psa/psa_hash.c, and calls to all hash APIs
|
||||
* but psa_hash_compute() removed.
|
||||
*
|
||||
* Example computing a SHA-256 hash using the PSA Crypto API
|
||||
*
|
||||
* The example computes the SHA-256 hash of a test string using the
|
||||
* one-shot API call psa_hash_compute().
|
||||
*
|
||||
*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mbedtls/build_info.h"
|
||||
#include "mbedtls/platform.h"
|
||||
|
||||
/* Information about hashing with the PSA API can be
|
||||
* found here:
|
||||
* https://arm-software.github.io/psa-api/crypto/1.1/api/ops/hashes.html
|
||||
*
|
||||
* The algorithm used by this demo is SHA 256.
|
||||
* Please see include/psa/crypto_values.h to see the other
|
||||
* algorithms that are supported by Mbed TLS.
|
||||
* If you switch to a different algorithm you will need to update
|
||||
* the hash data in the EXAMPLE_HASH_VALUE macro below. */
|
||||
|
||||
#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256)
|
||||
int main(void)
|
||||
{
|
||||
mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256"
|
||||
"not defined.\r\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#else
|
||||
|
||||
#define HASH_ALG PSA_ALG_SHA_256
|
||||
|
||||
const uint8_t sample_message[] = "Hello World!";
|
||||
/* sample_message is terminated with a null byte which is not part of
|
||||
* the message itself so we make sure to subtract it in order to get
|
||||
* the message length. */
|
||||
const size_t sample_message_length = sizeof(sample_message) - 1;
|
||||
|
||||
#define EXPECTED_HASH_VALUE { \
|
||||
0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \
|
||||
0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, \
|
||||
0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \
|
||||
}
|
||||
|
||||
const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
|
||||
const size_t expected_hash_len = sizeof(expected_hash);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
psa_status_t status;
|
||||
uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)];
|
||||
size_t hash_length;
|
||||
|
||||
mbedtls_printf("PSA Crypto API: SHA-256 example\n\n");
|
||||
|
||||
status = psa_crypto_init();
|
||||
if (status != PSA_SUCCESS) {
|
||||
mbedtls_printf("psa_crypto_init failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Clear local variables prior to one-shot hash demo */
|
||||
memset(hash, 0, sizeof(hash));
|
||||
hash_length = 0;
|
||||
|
||||
/* Compute hash using one-shot function call */
|
||||
status = psa_hash_compute(HASH_ALG,
|
||||
sample_message, sample_message_length,
|
||||
hash, sizeof(hash),
|
||||
&hash_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
mbedtls_printf("psa_hash_compute failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (hash_length != expected_hash_len ||
|
||||
(memcmp(hash, expected_hash, expected_hash_len) != 0)) {
|
||||
mbedtls_printf("One-shot hash operation gave the wrong result!\n\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
mbedtls_printf("One-shot hash operation successful!\n\n");
|
||||
|
||||
/* Print out result */
|
||||
mbedtls_printf("The SHA-256( '%s' ) is: ", sample_message);
|
||||
|
||||
for (size_t j = 0; j < expected_hash_len; j++) {
|
||||
mbedtls_printf("%02x", hash[j]);
|
||||
}
|
||||
|
||||
mbedtls_printf("\n");
|
||||
|
||||
mbedtls_psa_crypto_free();
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#endif /* !MBEDTLS_PSA_CRYPTO_C || !PSA_WANT_ALG_SHA_256 */
|
@ -5,50 +5,17 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Includes from psasim */
|
||||
#include <client.h>
|
||||
#include <util.h>
|
||||
#include "psa_manifest/sid.h"
|
||||
#include "psa_functions_codes.h"
|
||||
|
||||
/* Includes from mbedtls */
|
||||
#include "mbedtls/version.h"
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#define CLIENT_PRINT(fmt, ...) \
|
||||
PRINT("Client: " fmt, ##__VA_ARGS__)
|
||||
|
||||
int main()
|
||||
{
|
||||
char mbedtls_version[18];
|
||||
// psa_invec invecs[1];
|
||||
// psa_outvec outvecs[1];
|
||||
psa_status_t status;
|
||||
|
||||
mbedtls_version_get_string_full(mbedtls_version);
|
||||
CLIENT_PRINT("%s", mbedtls_version);
|
||||
|
||||
CLIENT_PRINT("My PID: %d", getpid());
|
||||
|
||||
CLIENT_PRINT("PSA version: %u", psa_version(PSA_SID_CRYPTO_SID));
|
||||
psa_handle_t h = psa_connect(PSA_SID_CRYPTO_SID, 1);
|
||||
|
||||
if (h < 0) {
|
||||
CLIENT_PRINT("Couldn't connect %d", h);
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = psa_call(h, PSA_CRYPTO_INIT, NULL, 0, NULL, 0);
|
||||
CLIENT_PRINT("PSA_CRYPTO_INIT returned: %d", status);
|
||||
|
||||
CLIENT_PRINT("Closing handle");
|
||||
psa_close(h);
|
||||
|
||||
/* psa_crypto_init() connects to the server */
|
||||
psa_status_t status = psa_crypto_init();
|
||||
if (status != PSA_SUCCESS) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
mbedtls_psa_crypto_free();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,9 +1,25 @@
|
||||
/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */
|
||||
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef _PSA_FUNCTIONS_CODES_H_
|
||||
#define _PSA_FUNCTIONS_CODES_H_
|
||||
|
||||
enum {
|
||||
PSA_CRYPTO_INIT = 0x00,
|
||||
/* Add other PSA functions here */
|
||||
/* Start here to avoid overlap with PSA_IPC_CONNECT, PSA_IPC_DISCONNECT
|
||||
* and VERSION_REQUEST */
|
||||
PSA_CRYPTO_INIT = 100,
|
||||
PSA_HASH_ABORT,
|
||||
PSA_HASH_CLONE,
|
||||
PSA_HASH_COMPARE,
|
||||
PSA_HASH_COMPUTE,
|
||||
PSA_HASH_FINISH,
|
||||
PSA_HASH_SETUP,
|
||||
PSA_HASH_UPDATE,
|
||||
PSA_HASH_VERIFY,
|
||||
};
|
||||
|
||||
#endif /* _PSA_FUNCTIONS_CODES_H_ */
|
||||
|
701
tests/psa-client-server/psasim/src/psa_sim_crypto_client.c
Normal file
701
tests/psa-client-server/psasim/src/psa_sim_crypto_client.c
Normal file
@ -0,0 +1,701 @@
|
||||
/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */
|
||||
|
||||
/* client calls */
|
||||
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Includes from psasim */
|
||||
#include <client.h>
|
||||
#include <util.h>
|
||||
#include "psa_manifest/sid.h"
|
||||
#include "psa_functions_codes.h"
|
||||
#include "psa_sim_serialise.h"
|
||||
|
||||
/* Includes from mbedtls */
|
||||
#include "mbedtls/version.h"
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#define CLIENT_PRINT(fmt, ...) \
|
||||
PRINT("Client: " fmt, ##__VA_ARGS__)
|
||||
|
||||
static psa_handle_t handle = -1;
|
||||
|
||||
int psa_crypto_call(int function,
|
||||
uint8_t *in_params, size_t in_params_len,
|
||||
uint8_t **out_params, size_t *out_params_len)
|
||||
{
|
||||
// psa_outvec outvecs[1];
|
||||
if (handle < 0) {
|
||||
fprintf(stderr, "NOT CONNECTED\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
psa_invec invec;
|
||||
invec.base = in_params;
|
||||
invec.len = in_params_len;
|
||||
|
||||
size_t max_receive = 8192;
|
||||
uint8_t *receive = malloc(max_receive);
|
||||
if (receive == NULL) {
|
||||
fprintf(stderr, "FAILED to allocate %u bytes\n", (unsigned) max_receive);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t actual_received = 0;
|
||||
|
||||
psa_outvec outvecs[2];
|
||||
outvecs[0].base = &actual_received;
|
||||
outvecs[0].len = sizeof(actual_received);
|
||||
outvecs[1].base = receive;
|
||||
outvecs[1].len = max_receive;
|
||||
|
||||
psa_status_t status = psa_call(handle, function, &invec, 1, outvecs, 2);
|
||||
if (status != PSA_SUCCESS) {
|
||||
free(receive);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_params = receive;
|
||||
*out_params_len = actual_received;
|
||||
|
||||
return 1; // success
|
||||
}
|
||||
|
||||
psa_status_t psa_crypto_init(void)
|
||||
{
|
||||
char mbedtls_version[18];
|
||||
uint8_t *result = NULL;
|
||||
size_t result_length;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
mbedtls_version_get_string_full(mbedtls_version);
|
||||
CLIENT_PRINT("%s", mbedtls_version);
|
||||
|
||||
CLIENT_PRINT("My PID: %d", getpid());
|
||||
|
||||
CLIENT_PRINT("PSA version: %u", psa_version(PSA_SID_CRYPTO_SID));
|
||||
handle = psa_connect(PSA_SID_CRYPTO_SID, 1);
|
||||
|
||||
if (handle < 0) {
|
||||
CLIENT_PRINT("Couldn't connect %d", handle);
|
||||
return PSA_ERROR_COMMUNICATION_FAILURE;
|
||||
}
|
||||
|
||||
int ok = psa_crypto_call(PSA_CRYPTO_INIT, NULL, 0, &result, &result_length);
|
||||
CLIENT_PRINT("PSA_CRYPTO_INIT returned: %d", ok);
|
||||
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *rpos = result;
|
||||
size_t rremain = result_length;
|
||||
|
||||
ok = psasim_deserialise_begin(&rpos, &rremain);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(result);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void mbedtls_psa_crypto_free(void)
|
||||
{
|
||||
CLIENT_PRINT("Closing handle");
|
||||
psa_close(handle);
|
||||
handle = -1;
|
||||
}
|
||||
|
||||
|
||||
psa_status_t psa_hash_abort(
|
||||
psa_hash_operation_t *operation
|
||||
)
|
||||
{
|
||||
uint8_t *params = NULL;
|
||||
uint8_t *result = NULL;
|
||||
size_t result_length;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t needed = psasim_serialise_begin_needs() +
|
||||
psasim_serialise_psa_hash_operation_t_needs(*operation);
|
||||
|
||||
params = malloc(needed);
|
||||
if (params == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *pos = params;
|
||||
size_t remaining = needed;
|
||||
int ok;
|
||||
ok = psasim_serialise_begin(&pos, &remaining);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psa_crypto_call(PSA_HASH_ABORT,
|
||||
params, (size_t) (pos - params), &result, &result_length);
|
||||
if (!ok) {
|
||||
printf("XXX server call failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *rpos = result;
|
||||
size_t rremain = result_length;
|
||||
|
||||
ok = psasim_deserialise_begin(&rpos, &rremain);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(params);
|
||||
free(result);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
psa_status_t psa_hash_clone(
|
||||
const psa_hash_operation_t *source_operation,
|
||||
psa_hash_operation_t *target_operation
|
||||
)
|
||||
{
|
||||
uint8_t *params = NULL;
|
||||
uint8_t *result = NULL;
|
||||
size_t result_length;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t needed = psasim_serialise_begin_needs() +
|
||||
psasim_serialise_psa_hash_operation_t_needs(*source_operation) +
|
||||
psasim_serialise_psa_hash_operation_t_needs(*target_operation);
|
||||
|
||||
params = malloc(needed);
|
||||
if (params == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *pos = params;
|
||||
size_t remaining = needed;
|
||||
int ok;
|
||||
ok = psasim_serialise_begin(&pos, &remaining);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *source_operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *target_operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psa_crypto_call(PSA_HASH_CLONE,
|
||||
params, (size_t) (pos - params), &result, &result_length);
|
||||
if (!ok) {
|
||||
printf("XXX server call failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *rpos = result;
|
||||
size_t rremain = result_length;
|
||||
|
||||
ok = psasim_deserialise_begin(&rpos, &rremain);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, target_operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(params);
|
||||
free(result);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
psa_status_t psa_hash_compare(
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input, size_t input_length,
|
||||
const uint8_t *hash, size_t hash_length
|
||||
)
|
||||
{
|
||||
uint8_t *params = NULL;
|
||||
uint8_t *result = NULL;
|
||||
size_t result_length;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t needed = psasim_serialise_begin_needs() +
|
||||
psasim_serialise_psa_algorithm_t_needs(alg) +
|
||||
psasim_serialise_buffer_needs(input, input_length) +
|
||||
psasim_serialise_buffer_needs(hash, hash_length);
|
||||
|
||||
params = malloc(needed);
|
||||
if (params == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *pos = params;
|
||||
size_t remaining = needed;
|
||||
int ok;
|
||||
ok = psasim_serialise_begin(&pos, &remaining);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psa_crypto_call(PSA_HASH_COMPARE,
|
||||
params, (size_t) (pos - params), &result, &result_length);
|
||||
if (!ok) {
|
||||
printf("XXX server call failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *rpos = result;
|
||||
size_t rremain = result_length;
|
||||
|
||||
ok = psasim_deserialise_begin(&rpos, &rremain);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(params);
|
||||
free(result);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
psa_status_t psa_hash_compute(
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input, size_t input_length,
|
||||
uint8_t *hash, size_t hash_size,
|
||||
size_t *hash_length
|
||||
)
|
||||
{
|
||||
uint8_t *params = NULL;
|
||||
uint8_t *result = NULL;
|
||||
size_t result_length;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t needed = psasim_serialise_begin_needs() +
|
||||
psasim_serialise_psa_algorithm_t_needs(alg) +
|
||||
psasim_serialise_buffer_needs(input, input_length) +
|
||||
psasim_serialise_buffer_needs(hash, hash_size) +
|
||||
psasim_serialise_size_t_needs(*hash_length);
|
||||
|
||||
params = malloc(needed);
|
||||
if (params == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *pos = params;
|
||||
size_t remaining = needed;
|
||||
int ok;
|
||||
ok = psasim_serialise_begin(&pos, &remaining);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_size);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_size_t(&pos, &remaining, *hash_length);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psa_crypto_call(PSA_HASH_COMPUTE,
|
||||
params, (size_t) (pos - params), &result, &result_length);
|
||||
if (!ok) {
|
||||
printf("XXX server call failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *rpos = result;
|
||||
size_t rremain = result_length;
|
||||
|
||||
ok = psasim_deserialise_begin(&rpos, &rremain);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_return_buffer(&rpos, &rremain, hash, hash_size);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_size_t(&rpos, &rremain, hash_length);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(params);
|
||||
free(result);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
psa_status_t psa_hash_finish(
|
||||
psa_hash_operation_t *operation,
|
||||
uint8_t *hash, size_t hash_size,
|
||||
size_t *hash_length
|
||||
)
|
||||
{
|
||||
uint8_t *params = NULL;
|
||||
uint8_t *result = NULL;
|
||||
size_t result_length;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t needed = psasim_serialise_begin_needs() +
|
||||
psasim_serialise_psa_hash_operation_t_needs(*operation) +
|
||||
psasim_serialise_buffer_needs(hash, hash_size) +
|
||||
psasim_serialise_size_t_needs(*hash_length);
|
||||
|
||||
params = malloc(needed);
|
||||
if (params == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *pos = params;
|
||||
size_t remaining = needed;
|
||||
int ok;
|
||||
ok = psasim_serialise_begin(&pos, &remaining);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_size);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_size_t(&pos, &remaining, *hash_length);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psa_crypto_call(PSA_HASH_FINISH,
|
||||
params, (size_t) (pos - params), &result, &result_length);
|
||||
if (!ok) {
|
||||
printf("XXX server call failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *rpos = result;
|
||||
size_t rremain = result_length;
|
||||
|
||||
ok = psasim_deserialise_begin(&rpos, &rremain);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_return_buffer(&rpos, &rremain, hash, hash_size);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_size_t(&rpos, &rremain, hash_length);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(params);
|
||||
free(result);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
psa_status_t psa_hash_setup(
|
||||
psa_hash_operation_t *operation,
|
||||
psa_algorithm_t alg
|
||||
)
|
||||
{
|
||||
uint8_t *params = NULL;
|
||||
uint8_t *result = NULL;
|
||||
size_t result_length;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t needed = psasim_serialise_begin_needs() +
|
||||
psasim_serialise_psa_hash_operation_t_needs(*operation) +
|
||||
psasim_serialise_psa_algorithm_t_needs(alg);
|
||||
|
||||
params = malloc(needed);
|
||||
if (params == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *pos = params;
|
||||
size_t remaining = needed;
|
||||
int ok;
|
||||
ok = psasim_serialise_begin(&pos, &remaining);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psa_crypto_call(PSA_HASH_SETUP,
|
||||
params, (size_t) (pos - params), &result, &result_length);
|
||||
if (!ok) {
|
||||
printf("XXX server call failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *rpos = result;
|
||||
size_t rremain = result_length;
|
||||
|
||||
ok = psasim_deserialise_begin(&rpos, &rremain);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(params);
|
||||
free(result);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
psa_status_t psa_hash_update(
|
||||
psa_hash_operation_t *operation,
|
||||
const uint8_t *input, size_t input_length
|
||||
)
|
||||
{
|
||||
uint8_t *params = NULL;
|
||||
uint8_t *result = NULL;
|
||||
size_t result_length;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t needed = psasim_serialise_begin_needs() +
|
||||
psasim_serialise_psa_hash_operation_t_needs(*operation) +
|
||||
psasim_serialise_buffer_needs(input, input_length);
|
||||
|
||||
params = malloc(needed);
|
||||
if (params == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *pos = params;
|
||||
size_t remaining = needed;
|
||||
int ok;
|
||||
ok = psasim_serialise_begin(&pos, &remaining);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psa_crypto_call(PSA_HASH_UPDATE,
|
||||
params, (size_t) (pos - params), &result, &result_length);
|
||||
if (!ok) {
|
||||
printf("XXX server call failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *rpos = result;
|
||||
size_t rremain = result_length;
|
||||
|
||||
ok = psasim_deserialise_begin(&rpos, &rremain);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(params);
|
||||
free(result);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
psa_status_t psa_hash_verify(
|
||||
psa_hash_operation_t *operation,
|
||||
const uint8_t *hash, size_t hash_length
|
||||
)
|
||||
{
|
||||
uint8_t *params = NULL;
|
||||
uint8_t *result = NULL;
|
||||
size_t result_length;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t needed = psasim_serialise_begin_needs() +
|
||||
psasim_serialise_psa_hash_operation_t_needs(*operation) +
|
||||
psasim_serialise_buffer_needs(hash, hash_length);
|
||||
|
||||
params = malloc(needed);
|
||||
if (params == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *pos = params;
|
||||
size_t remaining = needed;
|
||||
int ok;
|
||||
ok = psasim_serialise_begin(&pos, &remaining);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psa_crypto_call(PSA_HASH_VERIFY,
|
||||
params, (size_t) (pos - params), &result, &result_length);
|
||||
if (!ok) {
|
||||
printf("XXX server call failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint8_t *rpos = result;
|
||||
size_t rremain = result_length;
|
||||
|
||||
ok = psasim_deserialise_begin(&rpos, &rremain);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(params);
|
||||
free(result);
|
||||
|
||||
return status;
|
||||
}
|
834
tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
Normal file
834
tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
Normal file
@ -0,0 +1,834 @@
|
||||
/* 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"
|
||||
|
||||
// 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_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_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_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_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*out_params = result;
|
||||
*out_params_len = result_size;
|
||||
|
||||
return 1; // success
|
||||
|
||||
fail:
|
||||
free(result);
|
||||
|
||||
return 0; // This shouldn't happen!
|
||||
}
|
||||
|
||||
// Returns 1 for success, 0 for failure
|
||||
int psa_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_deserialise_psa_hash_operation_t(&pos, &remaining, &source_operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = psasim_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_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_serialise_psa_hash_operation_t(&rpos, &rremain, target_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_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_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_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_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
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_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_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_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*out_params = result;
|
||||
*out_params_len = result_size;
|
||||
|
||||
return 1; // success
|
||||
|
||||
fail:
|
||||
free(result);
|
||||
|
||||
return 0; // This shouldn't happen!
|
||||
}
|
||||
|
||||
// Returns 1 for success, 0 for failure
|
||||
int psa_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_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_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_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*out_params = result;
|
||||
*out_params_len = result_size;
|
||||
|
||||
free(input);
|
||||
|
||||
return 1; // success
|
||||
|
||||
fail:
|
||||
free(result);
|
||||
|
||||
free(input);
|
||||
|
||||
return 0; // This shouldn't happen!
|
||||
}
|
||||
|
||||
// Returns 1 for success, 0 for failure
|
||||
int psa_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_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_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_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
|
||||
if (!ok) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*out_params = result;
|
||||
*out_params_len = result_size;
|
||||
|
||||
free(hash);
|
||||
|
||||
return 1; // success
|
||||
|
||||
fail:
|
||||
free(result);
|
||||
|
||||
free(hash);
|
||||
|
||||
return 0; // This shouldn't happen!
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
1411
tests/psa-client-server/psasim/src/psa_sim_generate.pl
Executable file
1411
tests/psa-client-server/psasim/src/psa_sim_generate.pl
Executable file
File diff suppressed because it is too large
Load Diff
406
tests/psa-client-server/psasim/src/psa_sim_serialise.c
Normal file
406
tests/psa-client-server/psasim/src/psa_sim_serialise.c
Normal file
@ -0,0 +1,406 @@
|
||||
/**
|
||||
* \file psa_sim_serialise.c
|
||||
*
|
||||
* \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "psa_sim_serialise.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Basic idea:
|
||||
*
|
||||
* All arguments to a function will be serialised into a single buffer to
|
||||
* be sent to the server with the PSA crypto function to be called.
|
||||
*
|
||||
* All returned data (the function's return value and any values returned
|
||||
* via `out` parameters) will similarly be serialised into a buffer to be
|
||||
* sent back to the client from the server.
|
||||
*
|
||||
* For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer"
|
||||
* where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions,
|
||||
* psasim_serialise_foo() and psasim_deserialise_foo().
|
||||
*
|
||||
* We also have psasim_serialise_foo_needs() functions, which return a
|
||||
* size_t giving the number of bytes that serialising that instance of that
|
||||
* type will need. This allows callers to size buffers for serialisation.
|
||||
*
|
||||
* Each serialised buffer starts with a version byte, bytes that indicate
|
||||
* the size of basic C types, and four bytes that indicate the endianness
|
||||
* (to avoid incompatibilities if we ever run this over a network - we are
|
||||
* not aiming for universality, just for correctness and simplicity).
|
||||
*
|
||||
* Most types are serialised as a fixed-size (per type) octet string, with
|
||||
* no type indication. This is acceptable as (a) this is for the test PSA crypto
|
||||
* simulator only, not production, and (b) these functions are called by
|
||||
* code that itself is written by script.
|
||||
*
|
||||
* We also want to keep serialised data reasonably compact as communication
|
||||
* between client and server goes in messages of less than 200 bytes each.
|
||||
*
|
||||
* Many serialisation functions can be created by a script; an exemplar Perl
|
||||
* script is included. It is not hooked into the build and so must be run
|
||||
* manually, but is expected to be replaced by a Python script in due course.
|
||||
* Types that can have their functions created by script include plain old C
|
||||
* data types (e.g. int), types typedef'd to those, and even structures that
|
||||
* don't contain pointers.
|
||||
*/
|
||||
|
||||
size_t psasim_serialise_begin_needs(void)
|
||||
{
|
||||
/* The serialisation buffer will
|
||||
* start with a byte of 0 to indicate version 0,
|
||||
* then have 1 byte each for length of int, long, void *,
|
||||
* then have 4 bytes to indicate endianness. */
|
||||
return 4 + sizeof(uint32_t);
|
||||
}
|
||||
|
||||
int psasim_serialise_begin(uint8_t **pos, size_t *remaining)
|
||||
{
|
||||
uint32_t endian = 0x1234;
|
||||
|
||||
if (*remaining < 4 + sizeof(endian)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*(*pos)++ = 0; /* version */
|
||||
*(*pos)++ = (uint8_t) sizeof(int);
|
||||
*(*pos)++ = (uint8_t) sizeof(long);
|
||||
*(*pos)++ = (uint8_t) sizeof(void *);
|
||||
|
||||
memcpy(*pos, &endian, sizeof(endian));
|
||||
|
||||
*pos += sizeof(endian);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int psasim_deserialise_begin(uint8_t **pos, size_t *remaining)
|
||||
{
|
||||
uint8_t version = 255;
|
||||
uint8_t int_size = 0;
|
||||
uint8_t long_size = 0;
|
||||
uint8_t ptr_size = 0;
|
||||
uint32_t endian;
|
||||
|
||||
if (*remaining < 4 + sizeof(endian)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&version, (*pos)++, sizeof(version));
|
||||
if (version != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&int_size, (*pos)++, sizeof(int_size));
|
||||
if (int_size != sizeof(int)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&long_size, (*pos)++, sizeof(long_size));
|
||||
if (long_size != sizeof(long)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&ptr_size, (*pos)++, sizeof(ptr_size));
|
||||
if (ptr_size != sizeof(void *)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*remaining -= 4;
|
||||
|
||||
memcpy(&endian, *pos, sizeof(endian));
|
||||
if (endian != 0x1234) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pos += sizeof(endian);
|
||||
*remaining -= sizeof(endian);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t psasim_serialise_unsigned_int_needs(unsigned int value)
|
||||
{
|
||||
return sizeof(value);
|
||||
}
|
||||
|
||||
int psasim_serialise_unsigned_int(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
unsigned int value)
|
||||
{
|
||||
if (*remaining < sizeof(value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(*pos, &value, sizeof(value));
|
||||
*pos += sizeof(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int psasim_deserialise_unsigned_int(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
unsigned int *value)
|
||||
{
|
||||
if (*remaining < sizeof(*value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(value, *pos, sizeof(*value));
|
||||
|
||||
*pos += sizeof(*value);
|
||||
*remaining -= sizeof(*value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t psasim_serialise_int_needs(int value)
|
||||
{
|
||||
return sizeof(value);
|
||||
}
|
||||
|
||||
int psasim_serialise_int(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
int value)
|
||||
{
|
||||
if (*remaining < sizeof(value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(*pos, &value, sizeof(value));
|
||||
*pos += sizeof(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int psasim_deserialise_int(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
int *value)
|
||||
{
|
||||
if (*remaining < sizeof(*value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(value, *pos, sizeof(*value));
|
||||
|
||||
*pos += sizeof(*value);
|
||||
*remaining -= sizeof(*value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t psasim_serialise_size_t_needs(size_t value)
|
||||
{
|
||||
return sizeof(value);
|
||||
}
|
||||
|
||||
int psasim_serialise_size_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
size_t value)
|
||||
{
|
||||
if (*remaining < sizeof(value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(*pos, &value, sizeof(value));
|
||||
*pos += sizeof(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int psasim_deserialise_size_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
size_t *value)
|
||||
{
|
||||
if (*remaining < sizeof(*value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(value, *pos, sizeof(*value));
|
||||
|
||||
*pos += sizeof(*value);
|
||||
*remaining -= sizeof(*value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
(void) buffer;
|
||||
return sizeof(buffer_size) + buffer_size;
|
||||
}
|
||||
|
||||
int psasim_serialise_buffer(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_length)
|
||||
{
|
||||
if (*remaining < sizeof(buffer_length) + buffer_length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(*pos, &buffer_length, sizeof(buffer_length));
|
||||
*pos += sizeof(buffer_length);
|
||||
|
||||
if (buffer_length > 0) { // To be able to serialise (NULL, 0)
|
||||
memcpy(*pos, buffer, buffer_length);
|
||||
*pos += buffer_length;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int psasim_deserialise_buffer(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
uint8_t **buffer,
|
||||
size_t *buffer_length)
|
||||
{
|
||||
if (*remaining < sizeof(*buffer_length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buffer_length, *pos, sizeof(*buffer_length));
|
||||
|
||||
*pos += sizeof(buffer_length);
|
||||
*remaining -= sizeof(buffer_length);
|
||||
|
||||
if (*buffer_length == 0) { // Deserialise (NULL, 0)
|
||||
*buffer = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*remaining < *buffer_length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *data = malloc(*buffer_length);
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(data, *pos, *buffer_length);
|
||||
*pos += *buffer_length;
|
||||
*remaining -= *buffer_length;
|
||||
|
||||
*buffer = data;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* When the client is deserialising a buffer returned from the server, it needs
|
||||
* to use this function to deserialised the returned buffer. It should use the
|
||||
* usual \c psasim_serialise_buffer() function to serialise the outbound
|
||||
* buffer. */
|
||||
int psasim_deserialise_return_buffer(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_length)
|
||||
{
|
||||
if (*remaining < sizeof(buffer_length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t length_check;
|
||||
|
||||
memcpy(&length_check, *pos, sizeof(buffer_length));
|
||||
|
||||
*pos += sizeof(buffer_length);
|
||||
*remaining -= sizeof(buffer_length);
|
||||
|
||||
if (buffer_length != length_check) { // Make sure we're sent back the same we sent to the server
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (length_check == 0) { // Deserialise (NULL, 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*remaining < buffer_length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buffer, *pos, buffer_length);
|
||||
*pos += buffer_length;
|
||||
*remaining -= buffer_length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t psasim_serialise_psa_status_t_needs(psa_status_t value)
|
||||
{
|
||||
return psasim_serialise_int_needs(value);
|
||||
}
|
||||
|
||||
int psasim_serialise_psa_status_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_status_t value)
|
||||
{
|
||||
return psasim_serialise_int(pos, remaining, value);
|
||||
}
|
||||
|
||||
int psasim_deserialise_psa_status_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_status_t *value)
|
||||
{
|
||||
return psasim_deserialise_int(pos, remaining, value);
|
||||
}
|
||||
|
||||
size_t psasim_serialise_psa_algorithm_t_needs(psa_algorithm_t value)
|
||||
{
|
||||
return psasim_serialise_unsigned_int_needs(value);
|
||||
}
|
||||
|
||||
int psasim_serialise_psa_algorithm_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_algorithm_t value)
|
||||
{
|
||||
return psasim_serialise_unsigned_int(pos, remaining, value);
|
||||
}
|
||||
|
||||
int psasim_deserialise_psa_algorithm_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_algorithm_t *value)
|
||||
{
|
||||
return psasim_deserialise_unsigned_int(pos, remaining, value);
|
||||
}
|
||||
|
||||
size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t value)
|
||||
{
|
||||
return sizeof(value);
|
||||
}
|
||||
|
||||
int psasim_serialise_psa_hash_operation_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_hash_operation_t value)
|
||||
{
|
||||
if (*remaining < sizeof(value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(*pos, &value, sizeof(value));
|
||||
*pos += sizeof(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int psasim_deserialise_psa_hash_operation_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_hash_operation_t *value)
|
||||
{
|
||||
if (*remaining < sizeof(*value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(value, *pos, sizeof(*value));
|
||||
|
||||
*pos += sizeof(*value);
|
||||
*remaining -= sizeof(*value);
|
||||
|
||||
return 1;
|
||||
}
|
410
tests/psa-client-server/psasim/src/psa_sim_serialise.h
Normal file
410
tests/psa-client-server/psasim/src/psa_sim_serialise.h
Normal file
@ -0,0 +1,410 @@
|
||||
/**
|
||||
* \file psa_sim_serialise.h
|
||||
*
|
||||
* \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa/crypto_types.h"
|
||||
#include "psa/crypto_values.h"
|
||||
|
||||
/* Basic idea:
|
||||
*
|
||||
* All arguments to a function will be serialised into a single buffer to
|
||||
* be sent to the server with the PSA crypto function to be called.
|
||||
*
|
||||
* All returned data (the function's return value and any values returned
|
||||
* via `out` parameters) will similarly be serialised into a buffer to be
|
||||
* sent back to the client from the server.
|
||||
*
|
||||
* For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer"
|
||||
* where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions,
|
||||
* psasim_serialise_foo() and psasim_deserialise_foo().
|
||||
*
|
||||
* We also have psasim_serialise_foo_needs() functions, which return a
|
||||
* size_t giving the number of bytes that serialising that instance of that
|
||||
* type will need. This allows callers to size buffers for serialisation.
|
||||
*
|
||||
* Each serialised buffer starts with a version byte, bytes that indicate
|
||||
* the size of basic C types, and four bytes that indicate the endianness
|
||||
* (to avoid incompatibilities if we ever run this over a network - we are
|
||||
* not aiming for universality, just for correctness and simplicity).
|
||||
*
|
||||
* Most types are serialised as a fixed-size (per type) octet string, with
|
||||
* no type indication. This is acceptable as (a) this is for the test PSA crypto
|
||||
* simulator only, not production, and (b) these functions are called by
|
||||
* code that itself is written by script.
|
||||
*
|
||||
* We also want to keep serialised data reasonably compact as communication
|
||||
* between client and server goes in messages of less than 200 bytes each.
|
||||
*
|
||||
* Many serialisation functions can be created by a script; an exemplar Perl
|
||||
* script is included. It is not hooked into the build and so must be run
|
||||
* manually, but is expected to be replaced by a Python script in due course.
|
||||
* Types that can have their functions created by script include plain old C
|
||||
* data types (e.g. int), types typedef'd to those, and even structures that
|
||||
* don't contain pointers.
|
||||
*/
|
||||
|
||||
/** Return how much buffer space is needed by \c psasim_serialise_begin().
|
||||
*
|
||||
* \return The number of bytes needed in the buffer for
|
||||
* \c psasim_serialise_begin()'s output.
|
||||
*/
|
||||
size_t psasim_serialise_begin_needs(void);
|
||||
|
||||
/** Begin serialisation into a buffer.
|
||||
*
|
||||
* This must be the first serialisation API called
|
||||
* on a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error (likely
|
||||
* no space).
|
||||
*/
|
||||
int psasim_serialise_begin(uint8_t **pos, size_t *remaining);
|
||||
|
||||
/** Begin deserialisation of a buffer.
|
||||
*
|
||||
* This must be the first deserialisation API called
|
||||
* on a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_begin(uint8_t **pos, size_t *remaining);
|
||||
|
||||
/** Return how much buffer space is needed by \c psasim_serialise_unsigned_int()
|
||||
* to serialise an `unsigned int`.
|
||||
*
|
||||
* \param value The value that will be serialised into the buffer
|
||||
* (needed in case some serialisations are value-
|
||||
* dependent).
|
||||
*
|
||||
* \return The number of bytes needed in the buffer by
|
||||
* \c psasim_serialise_unsigned_int() to serialise
|
||||
* the given value.
|
||||
*/
|
||||
size_t psasim_serialise_unsigned_int_needs(unsigned int value);
|
||||
|
||||
/** Serialise an `unsigned int` into a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value The value to serialise into the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_serialise_unsigned_int(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
unsigned int value);
|
||||
|
||||
/** Deserialise an `unsigned int` from a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value Pointer to an `unsigned int` to receive the value
|
||||
* deserialised from the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_unsigned_int(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
unsigned int *value);
|
||||
|
||||
/** Return how much buffer space is needed by \c psasim_serialise_int()
|
||||
* to serialise an `int`.
|
||||
*
|
||||
* \param value The value that will be serialised into the buffer
|
||||
* (needed in case some serialisations are value-
|
||||
* dependent).
|
||||
*
|
||||
* \return The number of bytes needed in the buffer by
|
||||
* \c psasim_serialise_int() to serialise
|
||||
* the given value.
|
||||
*/
|
||||
size_t psasim_serialise_int_needs(int value);
|
||||
|
||||
/** Serialise an `int` into a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value The value to serialise into the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_serialise_int(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
int value);
|
||||
|
||||
/** Deserialise an `int` from a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value Pointer to an `int` to receive the value
|
||||
* deserialised from the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_int(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
int *value);
|
||||
|
||||
/** Return how much buffer space is needed by \c psasim_serialise_size_t()
|
||||
* to serialise a `size_t`.
|
||||
*
|
||||
* \param value The value that will be serialised into the buffer
|
||||
* (needed in case some serialisations are value-
|
||||
* dependent).
|
||||
*
|
||||
* \return The number of bytes needed in the buffer by
|
||||
* \c psasim_serialise_size_t() to serialise
|
||||
* the given value.
|
||||
*/
|
||||
size_t psasim_serialise_size_t_needs(size_t value);
|
||||
|
||||
/** Serialise a `size_t` into a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value The value to serialise into the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_serialise_size_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
size_t value);
|
||||
|
||||
/** Deserialise a `size_t` from a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value Pointer to a `size_t` to receive the value
|
||||
* deserialised from the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_size_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
size_t *value);
|
||||
|
||||
/** Return how much space is needed by \c psasim_serialise_buffer()
|
||||
* to serialise a buffer: a (`uint8_t *`, `size_t`) pair.
|
||||
*
|
||||
* \param buffer Pointer to the buffer to be serialised
|
||||
* (needed in case some serialisations are value-
|
||||
* dependent).
|
||||
* \param buffer_size Number of bytes in the buffer to be serialised.
|
||||
*
|
||||
* \return The number of bytes needed in the buffer by
|
||||
* \c psasim_serialise_buffer() to serialise
|
||||
* the specified buffer.
|
||||
*/
|
||||
size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size);
|
||||
|
||||
/** Serialise a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param buffer Pointer to the buffer to be serialised.
|
||||
* \param buffer_length Number of bytes in the buffer to be serialised.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_serialise_buffer(uint8_t **pos, size_t *remaining,
|
||||
const uint8_t *buffer, size_t buffer_length);
|
||||
|
||||
/** Deserialise a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the serialisation buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the serialisation buffer.
|
||||
* \param buffer Pointer to a `uint8_t *` to receive the address
|
||||
* of a newly-allocated buffer, which the caller
|
||||
* must `free()`.
|
||||
* \param buffer_length Pointer to a `size_t` to receive the number of
|
||||
* bytes in the deserialised buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_buffer(uint8_t **pos, size_t *remaining,
|
||||
uint8_t **buffer, size_t *buffer_length);
|
||||
|
||||
/** Deserialise a buffer returned from the server.
|
||||
*
|
||||
* When the client is deserialising a buffer returned from the server, it needs
|
||||
* to use this function to deserialised the returned buffer. It should use the
|
||||
* usual \c psasim_serialise_buffer() function to serialise the outbound
|
||||
* buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the serialisation buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the serialisation buffer.
|
||||
* \param buffer Pointer to a `uint8_t *` to receive the address
|
||||
* of a newly-allocated buffer, which the caller
|
||||
* must `free()`.
|
||||
* \param buffer_length Pointer to a `size_t` to receive the number of
|
||||
* bytes in the deserialised buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_return_buffer(uint8_t **pos, size_t *remaining,
|
||||
uint8_t *buffer, size_t buffer_length);
|
||||
|
||||
/** Return how much buffer space is needed by \c psasim_serialise_psa_status_t()
|
||||
* to serialise a `psa_status_t`.
|
||||
*
|
||||
* \param value The value that will be serialised into the buffer
|
||||
* (needed in case some serialisations are value-
|
||||
* dependent).
|
||||
*
|
||||
* \return The number of bytes needed in the buffer by
|
||||
* \c psasim_serialise_psa_status_t() to serialise
|
||||
* the given value.
|
||||
*/
|
||||
size_t psasim_serialise_psa_status_t_needs(psa_status_t value);
|
||||
|
||||
/** Serialise a `psa_status_t` into a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value The value to serialise into the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_serialise_psa_status_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_status_t value);
|
||||
|
||||
/** Deserialise a `psa_status_t` from a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value Pointer to a `psa_status_t` to receive the value
|
||||
* deserialised from the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_psa_status_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_status_t *value);
|
||||
|
||||
/** Return how much buffer space is needed by \c psasim_serialise_psa_algorithm_t()
|
||||
* to serialise a `psa_algorithm_t`.
|
||||
*
|
||||
* \param value The value that will be serialised into the buffer
|
||||
* (needed in case some serialisations are value-
|
||||
* dependent).
|
||||
*
|
||||
* \return The number of bytes needed in the buffer by
|
||||
* \c psasim_serialise_psa_algorithm_t() to serialise
|
||||
* the given value.
|
||||
*/
|
||||
size_t psasim_serialise_psa_algorithm_t_needs(psa_algorithm_t value);
|
||||
|
||||
/** Serialise a `psa_algorithm_t` into a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value The value to serialise into the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_serialise_psa_algorithm_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_algorithm_t value);
|
||||
|
||||
/** Deserialise a `psa_algorithm_t` from a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value Pointer to a `psa_algorithm_t` to receive the value
|
||||
* deserialised from the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_psa_algorithm_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_algorithm_t *value);
|
||||
|
||||
/** Return how much buffer space is needed by \c psasim_serialise_psa_hash_operation_t()
|
||||
* to serialise a `psa_hash_operation_t`.
|
||||
*
|
||||
* \param value The value that will be serialised into the buffer
|
||||
* (needed in case some serialisations are value-
|
||||
* dependent).
|
||||
*
|
||||
* \return The number of bytes needed in the buffer by
|
||||
* \c psasim_serialise_psa_hash_operation_t() to serialise
|
||||
* the given value.
|
||||
*/
|
||||
size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t value);
|
||||
|
||||
/** Serialise a `psa_hash_operation_t` into a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value The value to serialise into the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_serialise_psa_hash_operation_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_hash_operation_t value);
|
||||
|
||||
/** Deserialise a `psa_hash_operation_t` from a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param value Pointer to a `psa_hash_operation_t` to receive the value
|
||||
* deserialised from the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_psa_hash_operation_t(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
psa_hash_operation_t *value);
|
747
tests/psa-client-server/psasim/src/psa_sim_serialise.pl
Executable file
747
tests/psa-client-server/psasim/src/psa_sim_serialise.pl
Executable file
@ -0,0 +1,747 @@
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# psa_sim_serialise.pl - Sample Perl script to show how many serialisation
|
||||
# functions can be created by templated scripting.
|
||||
#
|
||||
# This is an example only, and is expected to be replaced by a Python script
|
||||
# for production use. It is not hooked into the build: it needs to be run
|
||||
# manually:
|
||||
#
|
||||
# perl psa_sim_serialise.pl h > psa_sim_serialise.h
|
||||
# perl psa_sim_serialise.pl c > psa_sim_serialise.c
|
||||
#
|
||||
# Copyright The Mbed TLS Contributors
|
||||
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
#
|
||||
use strict;
|
||||
|
||||
my $usage = "$0: usage: $0 c|h\n";
|
||||
my $which = lc(shift) || die($usage);
|
||||
die($usage) unless $which eq "c" || $which eq "h";
|
||||
|
||||
# Most types are serialised as a fixed-size (per type) octet string, with
|
||||
# no type indication. This is acceptable as (a) this is for the test PSA crypto
|
||||
# simulator only, not production, and (b) these functions are called by
|
||||
# code that itself is written by script.
|
||||
#
|
||||
# We also want to keep serialised data reasonably compact as communication
|
||||
# between client and server goes in messages of less than 200 bytes each.
|
||||
#
|
||||
# This script is able to create serialisation functions for plain old C data
|
||||
# types (e.g. unsigned int), types typedef'd to those, and even structures
|
||||
# that don't contain pointers.
|
||||
#
|
||||
# Structures that contain pointers will need to have their serialisation and
|
||||
# deserialisation functions written manually (like those for the "buffer" type
|
||||
# are).
|
||||
#
|
||||
my @types = qw(unsigned-int int size_t
|
||||
buffer
|
||||
psa_status_t psa_algorithm_t
|
||||
psa_hash_operation_t);
|
||||
grep(s/-/ /g, @types);
|
||||
|
||||
# IS-A: Some data types are typedef'd; we serialise them as the other type
|
||||
my %isa = (
|
||||
"psa_status_t" => "int",
|
||||
"psa_algorithm_t" => "unsigned int",
|
||||
);
|
||||
|
||||
if ($which eq "h") {
|
||||
|
||||
print h_header();
|
||||
|
||||
for my $type (@types) {
|
||||
if ($type eq "buffer") {
|
||||
print declare_buffer_functions();
|
||||
} else {
|
||||
print declare_needs($type);
|
||||
print declare_serialise($type);
|
||||
print declare_deserialise($type);
|
||||
}
|
||||
}
|
||||
|
||||
} elsif ($which eq "c") {
|
||||
|
||||
print c_header();
|
||||
|
||||
for my $type (@types) {
|
||||
if ($type eq "buffer") {
|
||||
print define_buffer_functions();
|
||||
} elsif (exists($isa{$type})) {
|
||||
print define_needs_isa($type, $isa{$type});
|
||||
print define_serialise_isa($type, $isa{$type});
|
||||
print define_deserialise_isa($type, $isa{$type});
|
||||
} else {
|
||||
print define_needs($type);
|
||||
print define_serialise($type);
|
||||
print define_deserialise($type);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
die("internal error - shouldn't happen");
|
||||
}
|
||||
|
||||
sub declare_needs
|
||||
{
|
||||
my ($type) = @_;
|
||||
|
||||
my $an = ($type =~ /^[ui]/) ? "an" : "a";
|
||||
my $type_d = $type;
|
||||
$type_d =~ s/ /_/g;
|
||||
|
||||
return <<EOF;
|
||||
|
||||
/** Return how much buffer space is needed by \\c psasim_serialise_$type_d()
|
||||
* to serialise $an `$type`.
|
||||
*
|
||||
* \\param value The value that will be serialised into the buffer
|
||||
* (needed in case some serialisations are value-
|
||||
* dependent).
|
||||
*
|
||||
* \\return The number of bytes needed in the buffer by
|
||||
* \\c psasim_serialise_$type_d() to serialise
|
||||
* the given value.
|
||||
*/
|
||||
size_t psasim_serialise_${type_d}_needs($type value);
|
||||
EOF
|
||||
}
|
||||
|
||||
sub declare_serialise
|
||||
{
|
||||
my ($type) = @_;
|
||||
|
||||
my $an = ($type =~ /^[ui]/) ? "an" : "a";
|
||||
my $type_d = $type;
|
||||
$type_d =~ s/ /_/g;
|
||||
|
||||
return align_declaration(<<EOF);
|
||||
|
||||
/** Serialise $an `$type` into a buffer.
|
||||
*
|
||||
* \\param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \\param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \\param value The value to serialise into the buffer.
|
||||
*
|
||||
* \\return \\c 1 on success ("okay"), \\c 0 on error.
|
||||
*/
|
||||
int psasim_serialise_$type_d(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
$type value);
|
||||
EOF
|
||||
}
|
||||
|
||||
sub declare_deserialise
|
||||
{
|
||||
my ($type) = @_;
|
||||
|
||||
my $an = ($type =~ /^[ui]/) ? "an" : "a";
|
||||
my $type_d = $type;
|
||||
$type_d =~ s/ /_/g;
|
||||
|
||||
return align_declaration(<<EOF);
|
||||
|
||||
/** Deserialise $an `$type` from a buffer.
|
||||
*
|
||||
* \\param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \\param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \\param value Pointer to $an `$type` to receive the value
|
||||
* deserialised from the buffer.
|
||||
*
|
||||
* \\return \\c 1 on success ("okay"), \\c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_$type_d(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
$type *value);
|
||||
EOF
|
||||
}
|
||||
|
||||
sub declare_buffer_functions
|
||||
{
|
||||
return <<'EOF';
|
||||
|
||||
/** Return how much space is needed by \c psasim_serialise_buffer()
|
||||
* to serialise a buffer: a (`uint8_t *`, `size_t`) pair.
|
||||
*
|
||||
* \param buffer Pointer to the buffer to be serialised
|
||||
* (needed in case some serialisations are value-
|
||||
* dependent).
|
||||
* \param buffer_size Number of bytes in the buffer to be serialised.
|
||||
*
|
||||
* \return The number of bytes needed in the buffer by
|
||||
* \c psasim_serialise_buffer() to serialise
|
||||
* the specified buffer.
|
||||
*/
|
||||
size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size);
|
||||
|
||||
/** Serialise a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
* \param buffer Pointer to the buffer to be serialised.
|
||||
* \param buffer_length Number of bytes in the buffer to be serialised.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_serialise_buffer(uint8_t **pos, size_t *remaining,
|
||||
const uint8_t *buffer, size_t buffer_length);
|
||||
|
||||
/** Deserialise a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the serialisation buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the serialisation buffer.
|
||||
* \param buffer Pointer to a `uint8_t *` to receive the address
|
||||
* of a newly-allocated buffer, which the caller
|
||||
* must `free()`.
|
||||
* \param buffer_length Pointer to a `size_t` to receive the number of
|
||||
* bytes in the deserialised buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_buffer(uint8_t **pos, size_t *remaining,
|
||||
uint8_t **buffer, size_t *buffer_length);
|
||||
|
||||
/** Deserialise a buffer returned from the server.
|
||||
*
|
||||
* When the client is deserialising a buffer returned from the server, it needs
|
||||
* to use this function to deserialised the returned buffer. It should use the
|
||||
* usual \c psasim_serialise_buffer() function to serialise the outbound
|
||||
* buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the serialisation buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the serialisation buffer.
|
||||
* \param buffer Pointer to a `uint8_t *` to receive the address
|
||||
* of a newly-allocated buffer, which the caller
|
||||
* must `free()`.
|
||||
* \param buffer_length Pointer to a `size_t` to receive the number of
|
||||
* bytes in the deserialised buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_return_buffer(uint8_t **pos, size_t *remaining,
|
||||
uint8_t *buffer, size_t buffer_length);
|
||||
EOF
|
||||
}
|
||||
|
||||
sub h_header
|
||||
{
|
||||
return <<'EOF';
|
||||
/**
|
||||
* \file psa_sim_serialise.h
|
||||
*
|
||||
* \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa/crypto_types.h"
|
||||
#include "psa/crypto_values.h"
|
||||
|
||||
/* Basic idea:
|
||||
*
|
||||
* All arguments to a function will be serialised into a single buffer to
|
||||
* be sent to the server with the PSA crypto function to be called.
|
||||
*
|
||||
* All returned data (the function's return value and any values returned
|
||||
* via `out` parameters) will similarly be serialised into a buffer to be
|
||||
* sent back to the client from the server.
|
||||
*
|
||||
* For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer"
|
||||
* where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions,
|
||||
* psasim_serialise_foo() and psasim_deserialise_foo().
|
||||
*
|
||||
* We also have psasim_serialise_foo_needs() functions, which return a
|
||||
* size_t giving the number of bytes that serialising that instance of that
|
||||
* type will need. This allows callers to size buffers for serialisation.
|
||||
*
|
||||
* Each serialised buffer starts with a version byte, bytes that indicate
|
||||
* the size of basic C types, and four bytes that indicate the endianness
|
||||
* (to avoid incompatibilities if we ever run this over a network - we are
|
||||
* not aiming for universality, just for correctness and simplicity).
|
||||
*
|
||||
* Most types are serialised as a fixed-size (per type) octet string, with
|
||||
* no type indication. This is acceptable as (a) this is for the test PSA crypto
|
||||
* simulator only, not production, and (b) these functions are called by
|
||||
* code that itself is written by script.
|
||||
*
|
||||
* We also want to keep serialised data reasonably compact as communication
|
||||
* between client and server goes in messages of less than 200 bytes each.
|
||||
*
|
||||
* Many serialisation functions can be created by a script; an exemplar Perl
|
||||
* script is included. It is not hooked into the build and so must be run
|
||||
* manually, but is expected to be replaced by a Python script in due course.
|
||||
* Types that can have their functions created by script include plain old C
|
||||
* data types (e.g. int), types typedef'd to those, and even structures that
|
||||
* don't contain pointers.
|
||||
*/
|
||||
|
||||
/** Return how much buffer space is needed by \c psasim_serialise_begin().
|
||||
*
|
||||
* \return The number of bytes needed in the buffer for
|
||||
* \c psasim_serialise_begin()'s output.
|
||||
*/
|
||||
size_t psasim_serialise_begin_needs(void);
|
||||
|
||||
/** Begin serialisation into a buffer.
|
||||
*
|
||||
* This must be the first serialisation API called
|
||||
* on a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error (likely
|
||||
* no space).
|
||||
*/
|
||||
int psasim_serialise_begin(uint8_t **pos, size_t *remaining);
|
||||
|
||||
/** Begin deserialisation of a buffer.
|
||||
*
|
||||
* This must be the first deserialisation API called
|
||||
* on a buffer.
|
||||
*
|
||||
* \param pos[in,out] Pointer to a `uint8_t *` holding current position
|
||||
* in the buffer.
|
||||
* \param remaining[in,out] Pointer to a `size_t` holding number of bytes
|
||||
* remaining in the buffer.
|
||||
*
|
||||
* \return \c 1 on success ("okay"), \c 0 on error.
|
||||
*/
|
||||
int psasim_deserialise_begin(uint8_t **pos, size_t *remaining);
|
||||
EOF
|
||||
}
|
||||
|
||||
sub define_needs
|
||||
{
|
||||
my ($type) = @_;
|
||||
|
||||
my $type_d = $type;
|
||||
$type_d =~ s/ /_/g;
|
||||
|
||||
return <<EOF;
|
||||
|
||||
size_t psasim_serialise_${type_d}_needs($type value)
|
||||
{
|
||||
return sizeof(value);
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
sub define_needs_isa
|
||||
{
|
||||
my ($type, $isa) = @_;
|
||||
|
||||
my $type_d = $type;
|
||||
$type_d =~ s/ /_/g;
|
||||
|
||||
my $isa_d = $isa;
|
||||
$isa_d =~ s/ /_/g;
|
||||
|
||||
return <<EOF;
|
||||
|
||||
size_t psasim_serialise_${type_d}_needs($type value)
|
||||
{
|
||||
return psasim_serialise_${isa_d}_needs(value);
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
sub define_serialise
|
||||
{
|
||||
my ($type) = @_;
|
||||
|
||||
my $type_d = $type;
|
||||
$type_d =~ s/ /_/g;
|
||||
|
||||
return align_signature(<<EOF);
|
||||
|
||||
int psasim_serialise_$type_d(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
$type value)
|
||||
{
|
||||
if (*remaining < sizeof(value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(*pos, &value, sizeof(value));
|
||||
*pos += sizeof(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
sub define_serialise_isa
|
||||
{
|
||||
my ($type, $isa) = @_;
|
||||
|
||||
my $type_d = $type;
|
||||
$type_d =~ s/ /_/g;
|
||||
|
||||
my $isa_d = $isa;
|
||||
$isa_d =~ s/ /_/g;
|
||||
|
||||
return align_signature(<<EOF);
|
||||
|
||||
int psasim_serialise_$type_d(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
$type value)
|
||||
{
|
||||
return psasim_serialise_$isa_d(pos, remaining, value);
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
sub define_deserialise
|
||||
{
|
||||
my ($type) = @_;
|
||||
|
||||
my $type_d = $type;
|
||||
$type_d =~ s/ /_/g;
|
||||
|
||||
return align_signature(<<EOF);
|
||||
|
||||
int psasim_deserialise_$type_d(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
$type *value)
|
||||
{
|
||||
if (*remaining < sizeof(*value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(value, *pos, sizeof(*value));
|
||||
|
||||
*pos += sizeof(*value);
|
||||
*remaining -= sizeof(*value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
sub define_deserialise_isa
|
||||
{
|
||||
my ($type, $isa) = @_;
|
||||
|
||||
my $type_d = $type;
|
||||
$type_d =~ s/ /_/g;
|
||||
|
||||
my $isa_d = $isa;
|
||||
$isa_d =~ s/ /_/g;
|
||||
|
||||
return align_signature(<<EOF);
|
||||
|
||||
int psasim_deserialise_$type_d(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
$type *value)
|
||||
{
|
||||
return psasim_deserialise_$isa_d(pos, remaining, value);
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
sub define_buffer_functions
|
||||
{
|
||||
return <<'EOF';
|
||||
|
||||
size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
(void) buffer;
|
||||
return sizeof(buffer_size) + buffer_size;
|
||||
}
|
||||
|
||||
int psasim_serialise_buffer(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_length)
|
||||
{
|
||||
if (*remaining < sizeof(buffer_length) + buffer_length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(*pos, &buffer_length, sizeof(buffer_length));
|
||||
*pos += sizeof(buffer_length);
|
||||
|
||||
if (buffer_length > 0) { // To be able to serialise (NULL, 0)
|
||||
memcpy(*pos, buffer, buffer_length);
|
||||
*pos += buffer_length;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int psasim_deserialise_buffer(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
uint8_t **buffer,
|
||||
size_t *buffer_length)
|
||||
{
|
||||
if (*remaining < sizeof(*buffer_length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buffer_length, *pos, sizeof(*buffer_length));
|
||||
|
||||
*pos += sizeof(buffer_length);
|
||||
*remaining -= sizeof(buffer_length);
|
||||
|
||||
if (*buffer_length == 0) { // Deserialise (NULL, 0)
|
||||
*buffer = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*remaining < *buffer_length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *data = malloc(*buffer_length);
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(data, *pos, *buffer_length);
|
||||
*pos += *buffer_length;
|
||||
*remaining -= *buffer_length;
|
||||
|
||||
*buffer = data;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* When the client is deserialising a buffer returned from the server, it needs
|
||||
* to use this function to deserialised the returned buffer. It should use the
|
||||
* usual \c psasim_serialise_buffer() function to serialise the outbound
|
||||
* buffer. */
|
||||
int psasim_deserialise_return_buffer(uint8_t **pos,
|
||||
size_t *remaining,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_length)
|
||||
{
|
||||
if (*remaining < sizeof(buffer_length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t length_check;
|
||||
|
||||
memcpy(&length_check, *pos, sizeof(buffer_length));
|
||||
|
||||
*pos += sizeof(buffer_length);
|
||||
*remaining -= sizeof(buffer_length);
|
||||
|
||||
if (buffer_length != length_check) { // Make sure we're sent back the same we sent to the server
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (length_check == 0) { // Deserialise (NULL, 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*remaining < buffer_length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buffer, *pos, buffer_length);
|
||||
*pos += buffer_length;
|
||||
*remaining -= buffer_length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
sub c_header
|
||||
{
|
||||
return <<'EOF';
|
||||
/**
|
||||
* \file psa_sim_serialise.c
|
||||
*
|
||||
* \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "psa_sim_serialise.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Basic idea:
|
||||
*
|
||||
* All arguments to a function will be serialised into a single buffer to
|
||||
* be sent to the server with the PSA crypto function to be called.
|
||||
*
|
||||
* All returned data (the function's return value and any values returned
|
||||
* via `out` parameters) will similarly be serialised into a buffer to be
|
||||
* sent back to the client from the server.
|
||||
*
|
||||
* For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer"
|
||||
* where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions,
|
||||
* psasim_serialise_foo() and psasim_deserialise_foo().
|
||||
*
|
||||
* We also have psasim_serialise_foo_needs() functions, which return a
|
||||
* size_t giving the number of bytes that serialising that instance of that
|
||||
* type will need. This allows callers to size buffers for serialisation.
|
||||
*
|
||||
* Each serialised buffer starts with a version byte, bytes that indicate
|
||||
* the size of basic C types, and four bytes that indicate the endianness
|
||||
* (to avoid incompatibilities if we ever run this over a network - we are
|
||||
* not aiming for universality, just for correctness and simplicity).
|
||||
*
|
||||
* Most types are serialised as a fixed-size (per type) octet string, with
|
||||
* no type indication. This is acceptable as (a) this is for the test PSA crypto
|
||||
* simulator only, not production, and (b) these functions are called by
|
||||
* code that itself is written by script.
|
||||
*
|
||||
* We also want to keep serialised data reasonably compact as communication
|
||||
* between client and server goes in messages of less than 200 bytes each.
|
||||
*
|
||||
* Many serialisation functions can be created by a script; an exemplar Perl
|
||||
* script is included. It is not hooked into the build and so must be run
|
||||
* manually, but is expected to be replaced by a Python script in due course.
|
||||
* Types that can have their functions created by script include plain old C
|
||||
* data types (e.g. int), types typedef'd to those, and even structures that
|
||||
* don't contain pointers.
|
||||
*/
|
||||
|
||||
size_t psasim_serialise_begin_needs(void)
|
||||
{
|
||||
/* The serialisation buffer will
|
||||
* start with a byte of 0 to indicate version 0,
|
||||
* then have 1 byte each for length of int, long, void *,
|
||||
* then have 4 bytes to indicate endianness. */
|
||||
return 4 + sizeof(uint32_t);
|
||||
}
|
||||
|
||||
int psasim_serialise_begin(uint8_t **pos, size_t *remaining)
|
||||
{
|
||||
uint32_t endian = 0x1234;
|
||||
|
||||
if (*remaining < 4 + sizeof(endian)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*(*pos)++ = 0; /* version */
|
||||
*(*pos)++ = (uint8_t) sizeof(int);
|
||||
*(*pos)++ = (uint8_t) sizeof(long);
|
||||
*(*pos)++ = (uint8_t) sizeof(void *);
|
||||
|
||||
memcpy(*pos, &endian, sizeof(endian));
|
||||
|
||||
*pos += sizeof(endian);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int psasim_deserialise_begin(uint8_t **pos, size_t *remaining)
|
||||
{
|
||||
uint8_t version = 255;
|
||||
uint8_t int_size = 0;
|
||||
uint8_t long_size = 0;
|
||||
uint8_t ptr_size = 0;
|
||||
uint32_t endian;
|
||||
|
||||
if (*remaining < 4 + sizeof(endian)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&version, (*pos)++, sizeof(version));
|
||||
if (version != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&int_size, (*pos)++, sizeof(int_size));
|
||||
if (int_size != sizeof(int)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&long_size, (*pos)++, sizeof(long_size));
|
||||
if (long_size != sizeof(long)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&ptr_size, (*pos)++, sizeof(ptr_size));
|
||||
if (ptr_size != sizeof(void *)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*remaining -= 4;
|
||||
|
||||
memcpy(&endian, *pos, sizeof(endian));
|
||||
if (endian != 0x1234) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pos += sizeof(endian);
|
||||
*remaining -= sizeof(endian);
|
||||
|
||||
return 1;
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# Horrible way to align first, second and third lines of function signature to
|
||||
# appease uncrustify (these are the 2nd-4th lines of code, indices 1, 2 and 3)
|
||||
#
|
||||
sub align_signature
|
||||
{
|
||||
my ($code) = @_;
|
||||
|
||||
my @code = split(/\n/, $code);
|
||||
|
||||
# Find where the ( is
|
||||
my $idx = index($code[1], "(");
|
||||
die("can't find (") if $idx < 0;
|
||||
|
||||
my $indent = " " x ($idx + 1);
|
||||
$code[2] =~ s/^\s+/$indent/;
|
||||
$code[3] =~ s/^\s+/$indent/;
|
||||
|
||||
return join("\n", @code) . "\n";
|
||||
}
|
||||
|
||||
# Horrible way to align the function declaration to appease uncrustify
|
||||
#
|
||||
sub align_declaration
|
||||
{
|
||||
my ($code) = @_;
|
||||
|
||||
my @code = split(/\n/, $code);
|
||||
|
||||
# Find out which lines we need to massage
|
||||
my $i;
|
||||
for ($i = 0; $i <= $#code; $i++) {
|
||||
last if $code[$i] =~ /^int psasim_/;
|
||||
}
|
||||
die("can't find int psasim_") if $i > $#code;
|
||||
|
||||
# Find where the ( is
|
||||
my $idx = index($code[$i], "(");
|
||||
die("can't find (") if $idx < 0;
|
||||
|
||||
my $indent = " " x ($idx + 1);
|
||||
$code[$i + 1] =~ s/^\s+/$indent/;
|
||||
$code[$i + 2] =~ s/^\s+/$indent/;
|
||||
|
||||
return join("\n", @code) . "\n";
|
||||
}
|
@ -53,6 +53,7 @@ int psa_server_main(int argc, char *argv[])
|
||||
const int magic_num = 66;
|
||||
int client_disconnected = 0;
|
||||
char mbedtls_version[18];
|
||||
extern psa_status_t psa_crypto_call(psa_msg_t msg);
|
||||
|
||||
mbedtls_version_get_string_full(mbedtls_version);
|
||||
SERVER_PRINT("%s", mbedtls_version);
|
||||
@ -83,14 +84,7 @@ int psa_server_main(int argc, char *argv[])
|
||||
break;
|
||||
default:
|
||||
SERVER_PRINT("Got an IPC call of type %d", msg.type);
|
||||
switch (msg.type) {
|
||||
case PSA_CRYPTO_INIT:
|
||||
ret = psa_crypto_init();
|
||||
break;
|
||||
default:
|
||||
SERVER_PRINT("Unknown PSA function code");
|
||||
break;
|
||||
}
|
||||
ret = psa_crypto_call(msg);
|
||||
SERVER_PRINT("Internal function call returned %d", ret);
|
||||
|
||||
if (msg.client_id > 0) {
|
||||
|
@ -30,8 +30,8 @@ function wait_for_server_startup() {
|
||||
|
||||
clean_run
|
||||
|
||||
./psa_partition -k > psa_partition.log 2>&1 &
|
||||
./psa_partition -k &
|
||||
SERV_PID=$!
|
||||
wait_for_server_startup
|
||||
./psa_client > psa_client.log 2>&1
|
||||
./psa_client
|
||||
wait $SERV_PID
|
||||
|
@ -6228,6 +6228,30 @@ component_test_psasim() {
|
||||
msg "test psasim"
|
||||
tests/psa-client-server/psasim/test/run_test.sh
|
||||
|
||||
msg "build psasim to test psa_hash_compute"
|
||||
# Delete the executable to ensure we build using the right MAIN
|
||||
rm tests/psa-client-server/psasim/test/psa_client
|
||||
# API under test: psa_hash_compute()
|
||||
make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="src/aut_psa_hash_compute.c"
|
||||
|
||||
msg "test psasim running psa_hash_compute"
|
||||
tests/psa-client-server/psasim/test/run_test.sh
|
||||
|
||||
# Next APIs under test: psa_hash_*(). Just use the PSA hash example.
|
||||
aut_psa_hash="../../../programs/psa/psa_hash.c"
|
||||
if [ -f "tests/psa-client-server/psasim/$aut_psa_hash" ]; then
|
||||
|
||||
msg "build psasim to test all psa_hash_* APIs"
|
||||
# Delete the executable to ensure we build using the right MAIN
|
||||
rm tests/psa-client-server/psasim/test/psa_client
|
||||
make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="$aut_psa_hash"
|
||||
|
||||
msg "test psasim running psa_hash sample"
|
||||
tests/psa-client-server/psasim/test/run_test.sh
|
||||
else
|
||||
echo $aut_psa_hash NOT FOUND, so not running that test
|
||||
fi
|
||||
|
||||
msg "clean psasim"
|
||||
make -C tests/psa-client-server/psasim clean
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user