Store operation_ts on PSA sim server side; only send handle to client

Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
index 919eb84..e511c74 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
@@ -72,7 +72,7 @@
     uint8_t **out_params, size_t *out_params_len)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_hash_operation_t operation;
+    psa_hash_operation_t *operation;
 
     uint8_t *pos = in_params;
     size_t remaining = in_params_len;
@@ -84,7 +84,7 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
     if (!ok) {
         goto fail;
     }
@@ -92,14 +92,14 @@
     // Now we call the actual target function
 
     status = psa_hash_abort(
-        &operation
+        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);
+        psasim_server_serialise_psa_hash_operation_t_needs(operation);
 
     result = malloc(result_size);
     if (result == NULL) {
@@ -119,7 +119,7 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
     if (!ok) {
         goto fail;
     }
@@ -141,8 +141,8 @@
     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;
+    psa_hash_operation_t *source_operation;
+    psa_hash_operation_t *target_operation;
 
     uint8_t *pos = in_params;
     size_t remaining = in_params_len;
@@ -154,12 +154,12 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &source_operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &source_operation);
     if (!ok) {
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &target_operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &target_operation);
     if (!ok) {
         goto fail;
     }
@@ -167,15 +167,15 @@
     // Now we call the actual target function
 
     status = psa_hash_clone(
-        &source_operation,
-        &target_operation
+        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);
+        psasim_server_serialise_psa_hash_operation_t_needs(target_operation);
 
     result = malloc(result_size);
     if (result == NULL) {
@@ -195,7 +195,7 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, target_operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, target_operation);
     if (!ok) {
         goto fail;
     }
@@ -406,7 +406,7 @@
     uint8_t **out_params, size_t *out_params_len)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_hash_operation_t operation;
+    psa_hash_operation_t *operation;
     uint8_t *hash = NULL;
     size_t hash_size;
     size_t hash_length;
@@ -421,7 +421,7 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
     if (!ok) {
         goto fail;
     }
@@ -439,7 +439,7 @@
     // Now we call the actual target function
 
     status = psa_hash_finish(
-        &operation,
+        operation,
         hash, hash_size,
         &hash_length
         );
@@ -448,7 +448,7 @@
     size_t result_size =
         psasim_serialise_begin_needs() +
         psasim_serialise_psa_status_t_needs(status) +
-        psasim_serialise_psa_hash_operation_t_needs(operation) +
+        psasim_server_serialise_psa_hash_operation_t_needs(operation) +
         psasim_serialise_buffer_needs(hash, hash_size) +
         psasim_serialise_size_t_needs(hash_length);
 
@@ -470,7 +470,7 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
     if (!ok) {
         goto fail;
     }
@@ -506,7 +506,7 @@
     uint8_t **out_params, size_t *out_params_len)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_hash_operation_t operation;
+    psa_hash_operation_t *operation;
     psa_algorithm_t alg;
 
     uint8_t *pos = in_params;
@@ -519,7 +519,7 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
     if (!ok) {
         goto fail;
     }
@@ -532,7 +532,7 @@
     // Now we call the actual target function
 
     status = psa_hash_setup(
-        &operation,
+        operation,
         alg
         );
 
@@ -540,7 +540,7 @@
     size_t result_size =
         psasim_serialise_begin_needs() +
         psasim_serialise_psa_status_t_needs(status) +
-        psasim_serialise_psa_hash_operation_t_needs(operation);
+        psasim_server_serialise_psa_hash_operation_t_needs(operation);
 
     result = malloc(result_size);
     if (result == NULL) {
@@ -560,7 +560,7 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
     if (!ok) {
         goto fail;
     }
@@ -582,7 +582,7 @@
     uint8_t **out_params, size_t *out_params_len)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_hash_operation_t operation;
+    psa_hash_operation_t *operation;
     uint8_t *input = NULL;
     size_t input_length;
 
@@ -596,7 +596,7 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
     if (!ok) {
         goto fail;
     }
@@ -609,7 +609,7 @@
     // Now we call the actual target function
 
     status = psa_hash_update(
-        &operation,
+        operation,
         input, input_length
         );
 
@@ -617,7 +617,7 @@
     size_t result_size =
         psasim_serialise_begin_needs() +
         psasim_serialise_psa_status_t_needs(status) +
-        psasim_serialise_psa_hash_operation_t_needs(operation);
+        psasim_server_serialise_psa_hash_operation_t_needs(operation);
 
     result = malloc(result_size);
     if (result == NULL) {
@@ -637,7 +637,7 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
     if (!ok) {
         goto fail;
     }
@@ -663,7 +663,7 @@
     uint8_t **out_params, size_t *out_params_len)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_hash_operation_t operation;
+    psa_hash_operation_t *operation;
     uint8_t *hash = NULL;
     size_t hash_length;
 
@@ -677,7 +677,7 @@
         goto fail;
     }
 
-    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    ok = psasim_server_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
     if (!ok) {
         goto fail;
     }
@@ -690,7 +690,7 @@
     // Now we call the actual target function
 
     status = psa_hash_verify(
-        &operation,
+        operation,
         hash, hash_length
         );
 
@@ -698,7 +698,7 @@
     size_t result_size =
         psasim_serialise_begin_needs() +
         psasim_serialise_psa_status_t_needs(status) +
-        psasim_serialise_psa_hash_operation_t_needs(operation);
+        psasim_server_serialise_psa_hash_operation_t_needs(operation);
 
     result = malloc(result_size);
     if (result == NULL) {
@@ -718,7 +718,7 @@
         goto fail;
     }
 
-    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    ok = psasim_server_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
     if (!ok) {
         goto fail;
     }
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.c b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
index 78ae9d6..20d89c5 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.c
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
@@ -13,6 +13,51 @@
 #include <stdlib.h>
 #include <string.h>
 
+/* 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 */
+        fprintf(stderr, "MAX HASH HANDLES REACHED\n");
+        exit(1);
+    }
+
+    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;
+        }
+    }
+
+    return -1;  /* all in use */
+}
+
+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;
+        }
+    }
+
+    return -1;  /* all in use */
+}
+
 /* Basic idea:
  *
  * All arguments to a function will be serialised into a single buffer to
@@ -404,3 +449,65 @@
 
     return 1;
 }
+
+/* On the server side, we have a certain number of slots. One array holds the
+ * psa_XXX_operation_t values by slot, the other holds the client-side handles
+ * for the slots.
+ */
+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;
+}
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.h b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
index d5eaccf..7a5881e 100644
--- a/tests/psa-client-server/psasim/src/psa_sim_serialise.h
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
@@ -408,3 +408,13 @@
 int psasim_deserialise_psa_hash_operation_t(uint8_t **pos,
                                             size_t *remaining,
                                             psa_hash_operation_t *value);
+
+size_t psasim_server_serialise_psa_hash_operation_t_needs(psa_hash_operation_t *operation);
+
+int psasim_server_serialise_psa_hash_operation_t(uint8_t **pos,
+                                                 size_t *remaining,
+                                                 psa_hash_operation_t *operation);
+
+int psasim_server_deserialise_psa_hash_operation_t(uint8_t **pos,
+                                                   size_t *remaining,
+                                                   psa_hash_operation_t **operation);