mirror of
https://github.com/cuberite/polarssl.git
synced 2025-10-04 02:52:38 -04:00
1306 lines
35 KiB
C
1306 lines
35 KiB
C
/**
|
|
* \file psa_sim_serialise.c
|
|
*
|
|
* \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator
|
|
*/
|
|
|
|
/*
|
|
* Copyright The Mbed TLS Contributors
|
|
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "psa_sim_serialise.h"
|
|
#include "util.h"
|
|
#include <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.
|
|
*/
|
|
|
|
/* include/psa/crypto_platform.h:typedef uint32_t mbedtls_psa_client_handle_t;
|
|
* but we don't get it on server builds, so redefine it here with a unique type name
|
|
*/
|
|
typedef uint32_t psasim_client_handle_t;
|
|
|
|
typedef struct psasim_operation_s {
|
|
psasim_client_handle_t handle;
|
|
} psasim_operation_t;
|
|
|
|
#define MAX_LIVE_HANDLES_PER_CLASS 100 /* this many slots */
|
|
|
|
static psa_hash_operation_t hash_operations[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t hash_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t next_hash_operation_handle = 1;
|
|
|
|
/* Get a free slot */
|
|
static ssize_t allocate_hash_operation_slot(void)
|
|
{
|
|
psasim_client_handle_t handle = next_hash_operation_handle++;
|
|
if (next_hash_operation_handle == 0) { /* wrapped around */
|
|
FATAL("Hash operation handle wrapped");
|
|
}
|
|
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (hash_operation_handles[i] == 0) {
|
|
hash_operation_handles[i] = handle;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("All slots are currently used. Unable to allocate a new one.");
|
|
|
|
return -1; /* all in use */
|
|
}
|
|
|
|
/* Find the slot given the handle */
|
|
static ssize_t find_hash_slot_by_handle(psasim_client_handle_t handle)
|
|
{
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (hash_operation_handles[i] == handle) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("Unable to find slot by handle %u", handle);
|
|
|
|
return -1; /* not found */
|
|
}
|
|
|
|
static psa_aead_operation_t aead_operations[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t aead_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t next_aead_operation_handle = 1;
|
|
|
|
/* Get a free slot */
|
|
static ssize_t allocate_aead_operation_slot(void)
|
|
{
|
|
psasim_client_handle_t handle = next_aead_operation_handle++;
|
|
if (next_aead_operation_handle == 0) { /* wrapped around */
|
|
FATAL("Aead operation handle wrapped");
|
|
}
|
|
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (aead_operation_handles[i] == 0) {
|
|
aead_operation_handles[i] = handle;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("All slots are currently used. Unable to allocate a new one.");
|
|
|
|
return -1; /* all in use */
|
|
}
|
|
|
|
/* Find the slot given the handle */
|
|
static ssize_t find_aead_slot_by_handle(psasim_client_handle_t handle)
|
|
{
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (aead_operation_handles[i] == handle) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("Unable to find slot by handle %u", handle);
|
|
|
|
return -1; /* not found */
|
|
}
|
|
|
|
static psa_mac_operation_t mac_operations[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t mac_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t next_mac_operation_handle = 1;
|
|
|
|
/* Get a free slot */
|
|
static ssize_t allocate_mac_operation_slot(void)
|
|
{
|
|
psasim_client_handle_t handle = next_mac_operation_handle++;
|
|
if (next_mac_operation_handle == 0) { /* wrapped around */
|
|
FATAL("Mac operation handle wrapped");
|
|
}
|
|
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (mac_operation_handles[i] == 0) {
|
|
mac_operation_handles[i] = handle;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("All slots are currently used. Unable to allocate a new one.");
|
|
|
|
return -1; /* all in use */
|
|
}
|
|
|
|
/* Find the slot given the handle */
|
|
static ssize_t find_mac_slot_by_handle(psasim_client_handle_t handle)
|
|
{
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (mac_operation_handles[i] == handle) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("Unable to find slot by handle %u", handle);
|
|
|
|
return -1; /* not found */
|
|
}
|
|
|
|
static psa_cipher_operation_t cipher_operations[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t cipher_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t next_cipher_operation_handle = 1;
|
|
|
|
/* Get a free slot */
|
|
static ssize_t allocate_cipher_operation_slot(void)
|
|
{
|
|
psasim_client_handle_t handle = next_cipher_operation_handle++;
|
|
if (next_cipher_operation_handle == 0) { /* wrapped around */
|
|
FATAL("Cipher operation handle wrapped");
|
|
}
|
|
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (cipher_operation_handles[i] == 0) {
|
|
cipher_operation_handles[i] = handle;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("All slots are currently used. Unable to allocate a new one.");
|
|
|
|
return -1; /* all in use */
|
|
}
|
|
|
|
/* Find the slot given the handle */
|
|
static ssize_t find_cipher_slot_by_handle(psasim_client_handle_t handle)
|
|
{
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (cipher_operation_handles[i] == handle) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("Unable to find slot by handle %u", handle);
|
|
|
|
return -1; /* not found */
|
|
}
|
|
|
|
static psa_key_derivation_operation_t key_derivation_operations[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t key_derivation_operation_handles[MAX_LIVE_HANDLES_PER_CLASS];
|
|
static psasim_client_handle_t next_key_derivation_operation_handle = 1;
|
|
|
|
/* Get a free slot */
|
|
static ssize_t allocate_key_derivation_operation_slot(void)
|
|
{
|
|
psasim_client_handle_t handle = next_key_derivation_operation_handle++;
|
|
if (next_key_derivation_operation_handle == 0) { /* wrapped around */
|
|
FATAL("Key_derivation operation handle wrapped");
|
|
}
|
|
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (key_derivation_operation_handles[i] == 0) {
|
|
key_derivation_operation_handles[i] = handle;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("All slots are currently used. Unable to allocate a new one.");
|
|
|
|
return -1; /* all in use */
|
|
}
|
|
|
|
/* Find the slot given the handle */
|
|
static ssize_t find_key_derivation_slot_by_handle(psasim_client_handle_t handle)
|
|
{
|
|
for (ssize_t i = 0; i < MAX_LIVE_HANDLES_PER_CLASS; i++) {
|
|
if (key_derivation_operation_handles[i] == handle) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
ERROR("Unable to find slot by handle %u", handle);
|
|
|
|
return -1; /* not found */
|
|
}
|
|
|
|
size_t psasim_serialise_begin_needs(void)
|
|
{
|
|
/* The serialisation buffer will
|
|
* start with a byte of 0 to indicate version 0,
|
|
* then have 1 byte each for length of int, long, void *,
|
|
* then have 4 bytes to indicate endianness. */
|
|
return 4 + sizeof(uint32_t);
|
|
}
|
|
|
|
int psasim_serialise_begin(uint8_t **pos, size_t *remaining)
|
|
{
|
|
uint32_t endian = 0x1234;
|
|
|
|
if (*remaining < 4 + sizeof(endian)) {
|
|
return 0;
|
|
}
|
|
|
|
*(*pos)++ = 0; /* version */
|
|
*(*pos)++ = (uint8_t) sizeof(int);
|
|
*(*pos)++ = (uint8_t) sizeof(long);
|
|
*(*pos)++ = (uint8_t) sizeof(void *);
|
|
|
|
memcpy(*pos, &endian, sizeof(endian));
|
|
|
|
*pos += sizeof(endian);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_begin(uint8_t **pos, size_t *remaining)
|
|
{
|
|
uint8_t version = 255;
|
|
uint8_t int_size = 0;
|
|
uint8_t long_size = 0;
|
|
uint8_t ptr_size = 0;
|
|
uint32_t endian;
|
|
|
|
if (*remaining < 4 + sizeof(endian)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&version, (*pos)++, sizeof(version));
|
|
if (version != 0) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&int_size, (*pos)++, sizeof(int_size));
|
|
if (int_size != sizeof(int)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&long_size, (*pos)++, sizeof(long_size));
|
|
if (long_size != sizeof(long)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&ptr_size, (*pos)++, sizeof(ptr_size));
|
|
if (ptr_size != sizeof(void *)) {
|
|
return 0;
|
|
}
|
|
|
|
*remaining -= 4;
|
|
|
|
memcpy(&endian, *pos, sizeof(endian));
|
|
if (endian != 0x1234) {
|
|
return 0;
|
|
}
|
|
|
|
*pos += sizeof(endian);
|
|
*remaining -= sizeof(endian);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_unsigned_int_needs(unsigned int value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_unsigned_int(uint8_t **pos,
|
|
size_t *remaining,
|
|
unsigned int value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_unsigned_int(uint8_t **pos,
|
|
size_t *remaining,
|
|
unsigned int *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_int_needs(int value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_int(uint8_t **pos,
|
|
size_t *remaining,
|
|
int value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_int(uint8_t **pos,
|
|
size_t *remaining,
|
|
int *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_size_t_needs(size_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_size_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
size_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_size_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
size_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_uint16_t_needs(uint16_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_uint16_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
uint16_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_uint16_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
uint16_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_uint64_t_needs(uint64_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_uint64_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
uint64_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_uint64_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
uint64_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size)
|
|
{
|
|
(void) buffer;
|
|
return sizeof(buffer_size) + buffer_size;
|
|
}
|
|
|
|
int psasim_serialise_buffer(uint8_t **pos,
|
|
size_t *remaining,
|
|
const uint8_t *buffer,
|
|
size_t buffer_length)
|
|
{
|
|
if (*remaining < sizeof(buffer_length) + buffer_length) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &buffer_length, sizeof(buffer_length));
|
|
*pos += sizeof(buffer_length);
|
|
|
|
if (buffer_length > 0) { // To be able to serialise (NULL, 0)
|
|
memcpy(*pos, buffer, buffer_length);
|
|
*pos += buffer_length;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_buffer(uint8_t **pos,
|
|
size_t *remaining,
|
|
uint8_t **buffer,
|
|
size_t *buffer_length)
|
|
{
|
|
if (*remaining < sizeof(*buffer_length)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(buffer_length, *pos, sizeof(*buffer_length));
|
|
|
|
*pos += sizeof(buffer_length);
|
|
*remaining -= sizeof(buffer_length);
|
|
|
|
if (*buffer_length == 0) { // Deserialise (NULL, 0)
|
|
*buffer = NULL;
|
|
return 1;
|
|
}
|
|
|
|
if (*remaining < *buffer_length) {
|
|
return 0;
|
|
}
|
|
|
|
uint8_t *data = malloc(*buffer_length);
|
|
if (data == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(data, *pos, *buffer_length);
|
|
*pos += *buffer_length;
|
|
*remaining -= *buffer_length;
|
|
|
|
*buffer = data;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* When the client is deserialising a buffer returned from the server, it needs
|
|
* to use this function to deserialised the returned buffer. It should use the
|
|
* usual \c psasim_serialise_buffer() function to serialise the outbound
|
|
* buffer. */
|
|
int psasim_deserialise_return_buffer(uint8_t **pos,
|
|
size_t *remaining,
|
|
uint8_t *buffer,
|
|
size_t buffer_length)
|
|
{
|
|
if (*remaining < sizeof(buffer_length)) {
|
|
return 0;
|
|
}
|
|
|
|
size_t length_check;
|
|
|
|
memcpy(&length_check, *pos, sizeof(buffer_length));
|
|
|
|
*pos += sizeof(buffer_length);
|
|
*remaining -= sizeof(buffer_length);
|
|
|
|
if (buffer_length != length_check) { // Make sure we're sent back the same we sent to the server
|
|
return 0;
|
|
}
|
|
|
|
if (length_check == 0) { // Deserialise (NULL, 0)
|
|
return 1;
|
|
}
|
|
|
|
if (*remaining < buffer_length) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(buffer, *pos, buffer_length);
|
|
*pos += buffer_length;
|
|
*remaining -= buffer_length;
|
|
|
|
return 1;
|
|
}
|
|
|
|
#define SER_TAG_SIZE 4
|
|
|
|
size_t psasim_serialise_psa_key_production_parameters_t_needs(
|
|
const psa_key_production_parameters_t *params,
|
|
size_t data_length)
|
|
{
|
|
/* We will serialise with 4-byte tag = "PKPP" + 4-byte overall length at the beginning,
|
|
* followed by size_t data_length, then the actual data from the structure.
|
|
*/
|
|
return SER_TAG_SIZE + sizeof(uint32_t) + sizeof(data_length) + sizeof(*params) + data_length;
|
|
}
|
|
|
|
int psasim_serialise_psa_key_production_parameters_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
const psa_key_production_parameters_t *params,
|
|
size_t data_length)
|
|
{
|
|
if (data_length > UINT32_MAX / 2) { /* arbitrary limit */
|
|
return 0; /* too big to serialise */
|
|
}
|
|
|
|
/* We use 32-bit lengths, which should be enough for any reasonable usage :) */
|
|
/* (the UINT32_MAX / 2 above is an even more conservative check to avoid overflow here) */
|
|
uint32_t len = (uint32_t) (sizeof(data_length) + sizeof(*params) + data_length);
|
|
if (*remaining < SER_TAG_SIZE + sizeof(uint32_t) + len) {
|
|
return 0;
|
|
}
|
|
|
|
char tag[SER_TAG_SIZE] = "PKPP";
|
|
|
|
memcpy(*pos, tag, sizeof(tag));
|
|
memcpy(*pos + sizeof(tag), &len, sizeof(len));
|
|
*pos += sizeof(tag) + sizeof(len);
|
|
*remaining -= sizeof(tag) + sizeof(len);
|
|
|
|
memcpy(*pos, &data_length, sizeof(data_length));
|
|
memcpy(*pos + sizeof(data_length), params, sizeof(*params) + data_length);
|
|
*pos += sizeof(data_length) + sizeof(*params) + data_length;
|
|
*remaining -= sizeof(data_length) + sizeof(*params) + data_length;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_psa_key_production_parameters_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_key_production_parameters_t **params,
|
|
size_t *data_length)
|
|
{
|
|
if (*remaining < SER_TAG_SIZE + sizeof(uint32_t)) {
|
|
return 0; /* can't even be an empty serialisation */
|
|
}
|
|
|
|
char tag[SER_TAG_SIZE] = "PKPP"; /* expected */
|
|
uint32_t len;
|
|
|
|
memcpy(&len, *pos + sizeof(tag), sizeof(len));
|
|
|
|
if (memcmp(*pos, tag, sizeof(tag)) != 0) {
|
|
return 0; /* wrong tag */
|
|
}
|
|
|
|
*pos += sizeof(tag) + sizeof(len);
|
|
*remaining -= sizeof(tag) + sizeof(len);
|
|
|
|
if (*remaining < sizeof(*data_length)) {
|
|
return 0; /* missing data_length */
|
|
}
|
|
memcpy(data_length, *pos, sizeof(*data_length));
|
|
|
|
if ((size_t)len != (sizeof(data_length) + sizeof(**params) + *data_length)) {
|
|
return 0; /* wrong length */
|
|
}
|
|
|
|
if (*remaining < sizeof(*data_length) + sizeof(**params) + *data_length) {
|
|
return 0; /* not enough data provided */
|
|
}
|
|
|
|
*pos += sizeof(data_length);
|
|
*remaining -= sizeof(data_length);
|
|
|
|
psa_key_production_parameters_t *out = malloc(sizeof(**params) + *data_length);
|
|
if (out == NULL) {
|
|
return 0; /* allocation failure */
|
|
}
|
|
|
|
memcpy(out, *pos, sizeof(*out) + *data_length);
|
|
*pos += sizeof(*out) + *data_length;
|
|
*remaining -= sizeof(*out) + *data_length;
|
|
|
|
*params = out;
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_psa_status_t_needs(psa_status_t value)
|
|
{
|
|
return psasim_serialise_int_needs(value);
|
|
}
|
|
|
|
int psasim_serialise_psa_status_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_status_t value)
|
|
{
|
|
return psasim_serialise_int(pos, remaining, value);
|
|
}
|
|
|
|
int psasim_deserialise_psa_status_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_status_t *value)
|
|
{
|
|
return psasim_deserialise_int(pos, remaining, value);
|
|
}
|
|
|
|
size_t psasim_serialise_psa_algorithm_t_needs(psa_algorithm_t value)
|
|
{
|
|
return psasim_serialise_unsigned_int_needs(value);
|
|
}
|
|
|
|
int psasim_serialise_psa_algorithm_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_algorithm_t value)
|
|
{
|
|
return psasim_serialise_unsigned_int(pos, remaining, value);
|
|
}
|
|
|
|
int psasim_deserialise_psa_algorithm_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_algorithm_t *value)
|
|
{
|
|
return psasim_deserialise_unsigned_int(pos, remaining, value);
|
|
}
|
|
|
|
size_t psasim_serialise_psa_key_derivation_step_t_needs(psa_key_derivation_step_t value)
|
|
{
|
|
return psasim_serialise_uint16_t_needs(value);
|
|
}
|
|
|
|
int psasim_serialise_psa_key_derivation_step_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_key_derivation_step_t value)
|
|
{
|
|
return psasim_serialise_uint16_t(pos, remaining, value);
|
|
}
|
|
|
|
int psasim_deserialise_psa_key_derivation_step_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_key_derivation_step_t *value)
|
|
{
|
|
return psasim_deserialise_uint16_t(pos, remaining, value);
|
|
}
|
|
|
|
size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_psa_hash_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_hash_operation_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_psa_hash_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_hash_operation_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_server_serialise_psa_hash_operation_t_needs(psa_hash_operation_t *operation)
|
|
{
|
|
(void) operation;
|
|
|
|
/* We will actually return a handle */
|
|
return sizeof(psasim_operation_t);
|
|
}
|
|
|
|
int psasim_server_serialise_psa_hash_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_hash_operation_t *operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(client_operation)) {
|
|
return 0;
|
|
}
|
|
|
|
ssize_t slot = operation - hash_operations;
|
|
|
|
client_operation.handle = hash_operation_handles[slot];
|
|
|
|
memcpy(*pos, &client_operation, sizeof(client_operation));
|
|
*pos += sizeof(client_operation);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_server_deserialise_psa_hash_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_hash_operation_t **operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(psasim_operation_t)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
|
|
*pos += sizeof(psasim_operation_t);
|
|
*remaining -= sizeof(psasim_operation_t);
|
|
|
|
ssize_t slot;
|
|
if (client_operation.handle == 0) { /* We need a new handle */
|
|
slot = allocate_hash_operation_slot();
|
|
} else {
|
|
slot = find_hash_slot_by_handle(client_operation.handle);
|
|
}
|
|
|
|
if (slot < 0) {
|
|
return 0;
|
|
}
|
|
|
|
*operation = &hash_operations[slot];
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_psa_aead_operation_t_needs(psa_aead_operation_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_psa_aead_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_aead_operation_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_psa_aead_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_aead_operation_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_server_serialise_psa_aead_operation_t_needs(psa_aead_operation_t *operation)
|
|
{
|
|
(void) operation;
|
|
|
|
/* We will actually return a handle */
|
|
return sizeof(psasim_operation_t);
|
|
}
|
|
|
|
int psasim_server_serialise_psa_aead_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_aead_operation_t *operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(client_operation)) {
|
|
return 0;
|
|
}
|
|
|
|
ssize_t slot = operation - aead_operations;
|
|
|
|
client_operation.handle = aead_operation_handles[slot];
|
|
|
|
memcpy(*pos, &client_operation, sizeof(client_operation));
|
|
*pos += sizeof(client_operation);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_server_deserialise_psa_aead_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_aead_operation_t **operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(psasim_operation_t)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
|
|
*pos += sizeof(psasim_operation_t);
|
|
*remaining -= sizeof(psasim_operation_t);
|
|
|
|
ssize_t slot;
|
|
if (client_operation.handle == 0) { /* We need a new handle */
|
|
slot = allocate_aead_operation_slot();
|
|
} else {
|
|
slot = find_aead_slot_by_handle(client_operation.handle);
|
|
}
|
|
|
|
if (slot < 0) {
|
|
return 0;
|
|
}
|
|
|
|
*operation = &aead_operations[slot];
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_psa_key_attributes_t_needs(psa_key_attributes_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_psa_key_attributes_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_key_attributes_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_psa_key_attributes_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_key_attributes_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_psa_mac_operation_t_needs(psa_mac_operation_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_psa_mac_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_mac_operation_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_psa_mac_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_mac_operation_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_server_serialise_psa_mac_operation_t_needs(psa_mac_operation_t *operation)
|
|
{
|
|
(void) operation;
|
|
|
|
/* We will actually return a handle */
|
|
return sizeof(psasim_operation_t);
|
|
}
|
|
|
|
int psasim_server_serialise_psa_mac_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_mac_operation_t *operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(client_operation)) {
|
|
return 0;
|
|
}
|
|
|
|
ssize_t slot = operation - mac_operations;
|
|
|
|
client_operation.handle = mac_operation_handles[slot];
|
|
|
|
memcpy(*pos, &client_operation, sizeof(client_operation));
|
|
*pos += sizeof(client_operation);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_server_deserialise_psa_mac_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_mac_operation_t **operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(psasim_operation_t)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
|
|
*pos += sizeof(psasim_operation_t);
|
|
*remaining -= sizeof(psasim_operation_t);
|
|
|
|
ssize_t slot;
|
|
if (client_operation.handle == 0) { /* We need a new handle */
|
|
slot = allocate_mac_operation_slot();
|
|
} else {
|
|
slot = find_mac_slot_by_handle(client_operation.handle);
|
|
}
|
|
|
|
if (slot < 0) {
|
|
return 0;
|
|
}
|
|
|
|
*operation = &mac_operations[slot];
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_psa_cipher_operation_t_needs(psa_cipher_operation_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_psa_cipher_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_cipher_operation_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_psa_cipher_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_cipher_operation_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_server_serialise_psa_cipher_operation_t_needs(psa_cipher_operation_t *operation)
|
|
{
|
|
(void) operation;
|
|
|
|
/* We will actually return a handle */
|
|
return sizeof(psasim_operation_t);
|
|
}
|
|
|
|
int psasim_server_serialise_psa_cipher_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_cipher_operation_t *operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(client_operation)) {
|
|
return 0;
|
|
}
|
|
|
|
ssize_t slot = operation - cipher_operations;
|
|
|
|
client_operation.handle = cipher_operation_handles[slot];
|
|
|
|
memcpy(*pos, &client_operation, sizeof(client_operation));
|
|
*pos += sizeof(client_operation);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_server_deserialise_psa_cipher_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_cipher_operation_t **operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(psasim_operation_t)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
|
|
*pos += sizeof(psasim_operation_t);
|
|
*remaining -= sizeof(psasim_operation_t);
|
|
|
|
ssize_t slot;
|
|
if (client_operation.handle == 0) { /* We need a new handle */
|
|
slot = allocate_cipher_operation_slot();
|
|
} else {
|
|
slot = find_cipher_slot_by_handle(client_operation.handle);
|
|
}
|
|
|
|
if (slot < 0) {
|
|
return 0;
|
|
}
|
|
|
|
*operation = &cipher_operations[slot];
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_psa_key_derivation_operation_t_needs(psa_key_derivation_operation_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_psa_key_derivation_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_key_derivation_operation_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_psa_key_derivation_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_key_derivation_operation_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_server_serialise_psa_key_derivation_operation_t_needs(psa_key_derivation_operation_t *operation)
|
|
{
|
|
(void) operation;
|
|
|
|
/* We will actually return a handle */
|
|
return sizeof(psasim_operation_t);
|
|
}
|
|
|
|
int psasim_server_serialise_psa_key_derivation_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_key_derivation_operation_t *operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(client_operation)) {
|
|
return 0;
|
|
}
|
|
|
|
ssize_t slot = operation - key_derivation_operations;
|
|
|
|
client_operation.handle = key_derivation_operation_handles[slot];
|
|
|
|
memcpy(*pos, &client_operation, sizeof(client_operation));
|
|
*pos += sizeof(client_operation);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_server_deserialise_psa_key_derivation_operation_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
psa_key_derivation_operation_t **operation)
|
|
{
|
|
psasim_operation_t client_operation;
|
|
|
|
if (*remaining < sizeof(psasim_operation_t)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(&client_operation, *pos, sizeof(psasim_operation_t));
|
|
*pos += sizeof(psasim_operation_t);
|
|
*remaining -= sizeof(psasim_operation_t);
|
|
|
|
ssize_t slot;
|
|
if (client_operation.handle == 0) { /* We need a new handle */
|
|
slot = allocate_key_derivation_operation_slot();
|
|
} else {
|
|
slot = find_key_derivation_slot_by_handle(client_operation.handle);
|
|
}
|
|
|
|
if (slot < 0) {
|
|
return 0;
|
|
}
|
|
|
|
*operation = &key_derivation_operations[slot];
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t psasim_serialise_mbedtls_svc_key_id_t_needs(mbedtls_svc_key_id_t value)
|
|
{
|
|
return sizeof(value);
|
|
}
|
|
|
|
int psasim_serialise_mbedtls_svc_key_id_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
mbedtls_svc_key_id_t value)
|
|
{
|
|
if (*remaining < sizeof(value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(*pos, &value, sizeof(value));
|
|
*pos += sizeof(value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int psasim_deserialise_mbedtls_svc_key_id_t(uint8_t **pos,
|
|
size_t *remaining,
|
|
mbedtls_svc_key_id_t *value)
|
|
{
|
|
if (*remaining < sizeof(*value)) {
|
|
return 0;
|
|
}
|
|
|
|
memcpy(value, *pos, sizeof(*value));
|
|
|
|
*pos += sizeof(*value);
|
|
*remaining -= sizeof(*value);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void psa_sim_serialize_reset(void)
|
|
{
|
|
memset(hash_operation_handles, 0, sizeof(hash_operation_handles));
|
|
memset(hash_operations, 0, sizeof(hash_operations));
|
|
memset(aead_operation_handles, 0, sizeof(aead_operation_handles));
|
|
memset(aead_operations, 0, sizeof(aead_operations));
|
|
memset(mac_operation_handles, 0, sizeof(mac_operation_handles));
|
|
memset(mac_operations, 0, sizeof(mac_operations));
|
|
memset(cipher_operation_handles, 0, sizeof(cipher_operation_handles));
|
|
memset(cipher_operations, 0, sizeof(cipher_operations));
|
|
memset(key_derivation_operation_handles, 0, sizeof(key_derivation_operation_handles));
|
|
memset(key_derivation_operations, 0, sizeof(key_derivation_operations));
|
|
}
|