crypto-client: reorganize source files/folders

The goal is to keep psasim as simple as possible:

- do not build a separate lib for psa-ff; build those source
  files as part of server or client
- do not have lot of different makefiles: just 1 that does all
  we need
- do not have several subfolders for headers: only 1 is enough
  for this kind of project

Signed-off-by: Valerio Setti <valerio.setti@nordicsemi.no>
diff --git a/tests/psa-client-server/psasim/Makefile b/tests/psa-client-server/psasim/Makefile
index 50fd0ad..45b3196 100644
--- a/tests/psa-client-server/psasim/Makefile
+++ b/tests/psa-client-server/psasim/Makefile
@@ -1,23 +1,51 @@
 CFLAGS += -Wall -Werror -std=c99 -D_XOPEN_SOURCE=1 -D_POSIX_C_SOURCE=200809L
 
 ifeq ($(DEBUG),1)
-	CFLAGS += -DDEBUG -O0 -g
+	CFLAGS += -DDEBUG
 endif
 
-.PHONY: all lib test run
+LIBPSACLIENT_PATH := ../../libpsaclient
+LIBPSASERVER_PATH := ../../libpsaserver
 
-all: lib test
+LIBPSACLIENT := -L$(LIBPSACLIENT_PATH)/library -lmbedcrypto -lmbedx509 -lmbedtls
+LIBPSASERVER := -L$(LIBPSASERVER_PATH)/library -lmbedcrypto
 
-lib:
-	$(MAKE) -C src CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"
+LIBPSACLIENT_H := -I$(LIBPSACLIENT_PATH)/include
+LIBPSASERVER_H := -I$(LIBPSASERVER_PATH)/include
 
-test: lib
-	$(MAKE) -C test CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"
+COMMON_INCLUDE := -I./include
+
+TEST_BIN = 	test/psa_client \
+			test/psa_partition
+
+GENERATED_H_FILES =	include/psa_manifest/manifest.h \
+					include/psa_manifest/pid.h \
+					include/psa_manifest/sid.h
+
+PSA_CLIENT_SRC = src/psa_ff_client.c \
+				 src/client.c
+
+PARTITION_SERVER_BOOTSTRAP = src/psa_ff_bootstrap_TEST_PARTITION.c
+
+PSA_SERVER_SRC = $(PARTITION_SERVER_BOOTSTRAP) \
+				 src/psa_ff_server.c
+
+.PHONY: all clean
+
+all: $(TEST_BIN)
+
+test/psa_client: $(PSA_CLIENT_SRC) $(GENERATED_H_FILES)
+	$(CC) $(COMMON_INCLUDE) $(LIBPSACLIENT_H) $(CFLAGS) $(PSA_CLIENT_SRC) $(LIBPSACLIENT) $(LDFLAGS) -o $@
+
+test/psa_partition: $(PSA_SERVER_SRC) $(GENERATED_H_FILES)
+	$(CC) $(COMMON_INCLUDE) $(LIBPSASERVER_H) $(CFLAGS) $(PSA_SERVER_SRC) $(LIBPSASERVER) $(LDFLAGS) -o $@
+
+$(PARTITION_SERVER_BOOTSTRAP) $(GENERATED_H_FILES): src/manifest.json src/server.c
+	tools/psa_autogen.py src/manifest.json
 
 clean:
-	rm -f $(PSA_LIB) $(PSA_LIB_OBJS)
-	$(MAKE) -C test clean
-	$(MAKE) -C src clean
+	rm -f $(TEST_BIN)
+	rm -f $(PARTITION_SERVER_BOOTSTRAP)
+	rm -rf include/psa_manifest
+	rm -f test/psa_service_* test/psa_notify_*
 
-run: test
-	cd test && ./run_test.sh
diff --git a/tests/psa-client-server/psasim/include/psa/client.h b/tests/psa-client-server/psasim/include/client.h
similarity index 98%
rename from tests/psa-client-server/psasim/include/psa/client.h
rename to tests/psa-client-server/psasim/include/client.h
index 1044c84..d48498e 100644
--- a/tests/psa-client-server/psasim/include/psa/client.h
+++ b/tests/psa-client-server/psasim/include/client.h
@@ -17,7 +17,7 @@
 
 #include "psa/crypto.h"
 
-#include "psa/error_ext.h"
+#include "error_ext.h"
 /*********************** PSA Client Macros and Types *************************/
 
 #define PSA_FRAMEWORK_VERSION  (0x0100)
diff --git a/tests/psa-client-server/psasim/include/psa/common.h b/tests/psa-client-server/psasim/include/common.h
similarity index 100%
rename from tests/psa-client-server/psasim/include/psa/common.h
rename to tests/psa-client-server/psasim/include/common.h
diff --git a/tests/psa-client-server/psasim/include/psa/error_ext.h b/tests/psa-client-server/psasim/include/error_ext.h
similarity index 94%
rename from tests/psa-client-server/psasim/include/psa/error_ext.h
rename to tests/psa-client-server/psasim/include/error_ext.h
index efbba86..6c82b8a 100644
--- a/tests/psa-client-server/psasim/include/psa/error_ext.h
+++ b/tests/psa-client-server/psasim/include/error_ext.h
@@ -10,7 +10,7 @@
 
 #include <stdint.h>
 
-#include "psa/common.h"
+#include "common.h"
 
 #define PSA_ERROR_PROGRAMMER_ERROR      ((psa_status_t) -129)
 #define PSA_ERROR_CONNECTION_REFUSED    ((psa_status_t) -130)
diff --git a/tests/psa-client-server/psasim/include/psasim/init.h b/tests/psa-client-server/psasim/include/init.h
similarity index 94%
rename from tests/psa-client-server/psasim/include/psasim/init.h
rename to tests/psa-client-server/psasim/include/init.h
index 9496fc2..de95d90 100644
--- a/tests/psa-client-server/psasim/include/psasim/init.h
+++ b/tests/psa-client-server/psasim/include/init.h
@@ -6,7 +6,7 @@
  */
 
 #include <stdint.h>
-#include <psa/service.h>
+#include <service.h>
 void raise_signal(psa_signal_t signal);
 void __init_psasim(const char **array,
                    int size,
diff --git a/tests/psa-client-server/psasim/include/psa/lifecycle.h b/tests/psa-client-server/psasim/include/lifecycle.h
similarity index 100%
rename from tests/psa-client-server/psasim/include/psa/lifecycle.h
rename to tests/psa-client-server/psasim/include/lifecycle.h
diff --git a/tests/psa-client-server/psasim/include/psa/service.h b/tests/psa-client-server/psasim/include/service.h
similarity index 99%
rename from tests/psa-client-server/psasim/include/psa/service.h
rename to tests/psa-client-server/psasim/include/service.h
index b6c9684..cbcb918 100644
--- a/tests/psa-client-server/psasim/include/psa/service.h
+++ b/tests/psa-client-server/psasim/include/service.h
@@ -15,7 +15,7 @@
 #include <stdint.h>
 #include <stddef.h>
 
-#include "psa/common.h"
+#include "common.h"
 
 #include "psa/crypto.h"
 
diff --git a/tests/psa-client-server/psasim/include/psa/util.h b/tests/psa-client-server/psasim/include/util.h
similarity index 96%
rename from tests/psa-client-server/psasim/include/psa/util.h
rename to tests/psa-client-server/psasim/include/util.h
index c3669a1..558149f 100644
--- a/tests/psa-client-server/psasim/include/psa/util.h
+++ b/tests/psa-client-server/psasim/include/util.h
@@ -5,7 +5,7 @@
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#include "psa/service.h"
+#include "service.h"
 
 #define PRINT(fmt, ...) \
     fprintf(stdout, fmt "\n", ##__VA_ARGS__)
diff --git a/tests/psa-client-server/psasim/src/Makefile b/tests/psa-client-server/psasim/src/Makefile
deleted file mode 100644
index 119971b..0000000
--- a/tests/psa-client-server/psasim/src/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# Here I'm picking also libpsaclient/include because I just need it for the
-# psa/crypto.h include. libpsaserver would have worked the same.
-INCLUDE = -I../include/ -I../../../libpsaclient/include
-PSA_LIB = libpsaff.a
-
-PSA_LIB_OBJS = client.o service.o
-
-.PHONY: all lib
-
-all: $(PSA_LIB)
-
-%.o: %.c
-	$(CC) $(INCLUDE) $(CFLAGS) -c $< -o $@
-
-$(PSA_LIB): $(PSA_LIB_OBJS)
-	$(AR) rcs $(PSA_LIB) client.o service.o
-
-clean:
-	rm -f $(PSA_LIB) $(PSA_LIB_OBJS)
diff --git a/tests/psa-client-server/psasim/src/client.c b/tests/psa-client-server/psasim/src/client.c
index bd1d5d8..e8f370d 100644
--- a/tests/psa-client-server/psasim/src/client.c
+++ b/tests/psa-client-server/psasim/src/client.c
@@ -1,392 +1,54 @@
-/* PSA firmware framework client API */
+/* psasim test client */
 
 /*
  *  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#include <stdint.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <assert.h>
 #include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
+#include <unistd.h>
 
-#include "psa/client.h"
-#include "psa/common.h"
-#include "psa/error_ext.h"
-#include "psa/util.h"
+/* Includes from psasim */
+#include <client.h>
+#include <util.h>
+#include "psa_manifest/sid.h"
+#include "psa_functions_codes.h"
 
-typedef struct internal_handle {
-    int server_qid;
-    int client_qid;
-    int internal_server_qid;
-    int valid;
-} internal_handle_t;
+/* Includes from mbedtls */
+#include "mbedtls/version.h"
+#include "psa/crypto.h"
 
-typedef struct vectors {
-    const psa_invec *in_vec;
-    size_t in_len;
-    psa_outvec *out_vec;
-    size_t out_len;
-} vectors_t;
+#define CLIENT_PRINT(fmt, ...) \
+    PRINT("Client: " fmt, ##__VA_ARGS__)
 
-/* Note that this implementation is functional and not secure */
-int __psa_ff_client_security_state = NON_SECURE;
-
-/* Access to this global is not thread safe */
-#define MAX_HANDLES 32
-static internal_handle_t handles[MAX_HANDLES] = { { 0 } };
-
-static int get_next_free_handle()
+int main()
 {
-    /* Never return handle 0 as it's a special null handle */
-    for (int i = 1; i < MAX_HANDLES; i++) {
-        if (handles[i].valid == 0) {
-            return i;
-        }
-    }
-    return -1;
-}
+    char mbedtls_version[18];
+    // psa_invec invecs[1];
+    // psa_outvec outvecs[1];
+    psa_status_t status;
 
-static int handle_is_valid(psa_handle_t handle)
-{
-    if (handle > 0 && handle < MAX_HANDLES) {
-        if (handles[handle].valid == 1) {
-            return 1;
-        }
+    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_SHA256_SID));
+    psa_handle_t h = psa_connect(PSA_SID_SHA256_SID, 1);
+
+    if (h < 0) {
+        CLIENT_PRINT("Couldn't connect %d", h);
+        return 1;
     }
-    ERROR("ERROR: Invalid handle");
+
+    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);
+
+    if (status != PSA_SUCCESS) {
+        return 1;
+    }
     return 0;
 }
-
-static int get_queue_info(char *path, int *cqid, int *sqid)
-{
-
-    key_t server_queue_key;
-    int rx_qid, server_qid;
-
-    INFO("Attempting to contact a RoT service queue");
-
-    if ((rx_qid = msgget(IPC_PRIVATE, 0660)) == -1) {
-        ERROR("msgget: rx_qid");
-        return -1;
-    }
-
-    if ((server_queue_key = ftok(path, PROJECT_ID)) == -1) {
-        ERROR("ftok");
-        return -2;
-    }
-
-    if ((server_qid = msgget(server_queue_key, 0)) == -1) {
-        ERROR("msgget: server_qid");
-        return -3;
-    }
-
-    *cqid = rx_qid;
-    *sqid = server_qid;
-
-    return 0;
-}
-
-static psa_status_t process_response(int rx_qid, vectors_t *vecs, int type,
-                                     int *internal_server_qid)
-{
-
-    struct message response, request;
-    psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED;
-    size_t invec_seek[4] = { 0 };
-    size_t data_size;
-    psa_status_t invec, outvec; /* TODO: Should these be size_t ? */
-
-    assert(internal_server_qid > 0);
-
-    while (1) {
-        data_size = 0;
-        invec = 0;
-        outvec = 0;
-
-        // read response from server
-        if (msgrcv(rx_qid, &response, sizeof(struct message_text), 0, 0) == -1) {
-            ERROR("   msgrcv failed");
-            return ret;
-        }
-
-        // process return message from server
-        switch (response.message_type) {
-            case PSA_REPLY:
-                memcpy(&ret, response.message_text.buf, sizeof(psa_status_t));
-                INFO("   Message received from server: %d", ret);
-                if (type == PSA_IPC_CONNECT && ret > 0) {
-                    *internal_server_qid = ret;
-                    INFO("   ASSSIGNED q ID %d", *internal_server_qid);
-                    ret = PSA_SUCCESS;
-                }
-                return ret;
-                break;
-            case READ_REQUEST:
-                /* read data request */
-                request.message_type = READ_RESPONSE;
-
-                assert(vecs != 0);
-
-                memcpy(&invec, response.message_text.buf, sizeof(psa_status_t));
-                memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t));
-                INFO("   Partition asked for %lu bytes from invec %d", data_size, invec);
-
-                /* need to add more checks here */
-                assert(invec >= 0 && invec < PSA_MAX_IOVEC);
-
-                if (data_size > MAX_FRAGMENT_SIZE) {
-                    data_size = MAX_FRAGMENT_SIZE;
-                }
-
-                /* send response */
-                INFO("   invec_seek[invec] is %lu", invec_seek[invec]);
-                INFO("   Reading from offset %p", vecs->in_vec[invec].base + invec_seek[invec]);
-                memcpy(request.message_text.buf,
-                       (vecs->in_vec[invec].base + invec_seek[invec]),
-                       data_size);
-
-                /* update invec base TODO: check me */
-                invec_seek[invec] = invec_seek[invec] + data_size;
-
-                INFO("   Sending message of type %li", request.message_type);
-                INFO("       with content %s", request.message_text.buf);
-
-                if (msgsnd(*internal_server_qid, &request,
-                           sizeof(int) + sizeof(uint32_t) + data_size, 0) == -1) {
-                    ERROR("Internal error: failed to respond to read request");
-                }
-                break;
-            case WRITE_REQUEST:
-                assert(vecs != 0);
-
-                request.message_type = WRITE_RESPONSE;
-
-                memcpy(&outvec, response.message_text.buf, sizeof(psa_status_t));
-                memcpy(&data_size, response.message_text.buf + sizeof(size_t), sizeof(size_t));
-                INFO("   Partition wants to write %lu bytes to outvec %d", data_size, outvec);
-
-                assert(outvec >= 0 && outvec < PSA_MAX_IOVEC);
-
-                /* copy memory into message and send back amount written */
-                size_t sofar = vecs->out_vec[outvec].len;
-                memcpy(vecs->out_vec[outvec].base + sofar,
-                       response.message_text.buf+(sizeof(size_t)*2), data_size);
-                INFO("   Data size is %lu", data_size);
-                vecs->out_vec[outvec].len += data_size;
-
-                INFO("   Sending message of type %li", request.message_type);
-
-                /* send response */
-                if (msgsnd(*internal_server_qid, &request, sizeof(int) + data_size, 0) == -1) {
-                    ERROR("Internal error: failed to respond to write request");
-                }
-                break;
-            case SKIP_REQUEST:
-                memcpy(&invec, response.message_text.buf, sizeof(psa_status_t));
-                memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t));
-                INFO("   Partition asked to skip %lu bytes in invec %d", data_size, invec);
-                assert(invec >= 0 && invec < PSA_MAX_IOVEC);
-                /* update invec base TODO: check me */
-                invec_seek[invec] = invec_seek[invec] + data_size;
-                break;
-
-            default:
-                FATAL("   ERROR: unknown internal message type: %ld",
-                      response.message_type);
-                return ret;
-        }
-    }
-}
-
-static psa_status_t send(int rx_qid, int server_qid, int *internal_server_qid,
-                         int32_t type, uint32_t minor_version, vectors_t *vecs)
-{
-    {
-        psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED;
-        size_t request_msg_size = (sizeof(int) + sizeof(long)); /* msg type plus queue id */
-        struct message request;
-        request.message_type = 1; /* TODO: change this */
-        request.message_text.psa_type = type;
-        vector_sizes_t vec_sizes;
-
-        /* If the client is non-secure then set the NS bit */
-        if (__psa_ff_client_security_state != 0) {
-            request.message_type |= NON_SECURE;
-        }
-
-        assert(request.message_type >= 0);
-
-        INFO("SEND: Sending message of type %ld with psa_type %d", request.message_type, type);
-        INFO("     internal_server_qid = %i", *internal_server_qid);
-
-        request.message_text.qid = rx_qid;
-
-        if (type == PSA_IPC_CONNECT) {
-            memcpy(request.message_text.buf, &minor_version, sizeof(minor_version));
-            request_msg_size = request_msg_size + sizeof(minor_version);
-            INFO("   Request msg size is %lu", request_msg_size);
-        } else {
-            assert(internal_server_qid > 0);
-        }
-
-        if (vecs != NULL && type >= PSA_IPC_CALL) {
-
-            memset(&vec_sizes, 0, sizeof(vec_sizes));
-
-            /* Copy invec sizes */
-            for (size_t i = 0; i < (vecs->in_len); i++) {
-                vec_sizes.invec_sizes[i] = vecs->in_vec[i].len;
-                INFO("   Client sending vector %lu: %lu", i, vec_sizes.invec_sizes[i]);
-            }
-
-            /* Copy outvec sizes */
-            for (size_t i = 0; i < (vecs->out_len); i++) {
-                vec_sizes.outvec_sizes[i] = vecs->out_vec[i].len;
-
-                /* Reset to 0 since we need to eventually fill in with bytes written */
-                vecs->out_vec[i].len = 0;
-            }
-
-            memcpy(request.message_text.buf, &vec_sizes, sizeof(vec_sizes));
-            request_msg_size = request_msg_size + sizeof(vec_sizes);
-        }
-
-        INFO("   Sending and then waiting");
-
-        // send message to server
-        if (msgsnd(server_qid, &request, request_msg_size, 0) == -1) {
-            ERROR("   msgsnd failed");
-            return ret;
-        }
-
-        return process_response(rx_qid, vecs, type, internal_server_qid);
-    }
-}
-
-
-uint32_t psa_framework_version(void)
-{
-    return PSA_FRAMEWORK_VERSION;
-}
-
-psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
-{
-
-    int idx;
-    psa_status_t ret;
-    char pathname[PATHNAMESIZE] = { 0 };
-
-    idx = get_next_free_handle();
-
-    /* if there's a free handle available */
-    if (idx >= 0) {
-        snprintf(pathname, PATHNAMESIZE - 1, TMP_FILE_BASE_PATH "psa_service_%u", sid);
-        INFO("Attempting to contact RoT service at %s", pathname);
-
-        /* if communication is possible */
-        if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) {
-
-            ret = send(handles[idx].client_qid,
-                       handles[idx].server_qid,
-                       &handles[idx].internal_server_qid,
-                       PSA_IPC_CONNECT,
-                       minor_version,
-                       NULL);
-
-            /* if connection accepted by RoT service */
-            if (ret >= 0) {
-                handles[idx].valid = 1;
-                return idx;
-            } else {
-                INFO("Server didn't like you");
-            }
-        } else {
-            INFO("Couldn't contact RoT service. Does it exist?");
-
-            if (__psa_ff_client_security_state == 0) {
-                ERROR("Invalid SID");
-            }
-        }
-    }
-
-    INFO("Couldn't obtain a free handle");
-    return PSA_ERROR_CONNECTION_REFUSED;
-}
-
-uint32_t psa_version(uint32_t sid)
-{
-    int idx;
-    psa_status_t ret;
-    char pathname[PATHNAMESIZE] = { 0 };
-
-    idx = get_next_free_handle();
-
-    if (idx >= 0) {
-        snprintf(pathname, PATHNAMESIZE, TMP_FILE_BASE_PATH "psa_service_%u", sid);
-        if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) {
-            ret = send(handles[idx].client_qid,
-                       handles[idx].server_qid,
-                       &handles[idx].internal_server_qid,
-                       VERSION_REQUEST,
-                       0,
-                       NULL);
-            INFO("psa_version: Recieved from server %d", ret);
-            if (ret > 0) {
-                return ret;
-            }
-        }
-    }
-    INFO("psa_version failed: does the service exist?");
-    return PSA_VERSION_NONE;
-}
-
-psa_status_t psa_call(psa_handle_t handle,
-                      int32_t type,
-                      const psa_invec *in_vec,
-                      size_t in_len,
-                      psa_outvec *out_vec,
-                      size_t out_len)
-{
-
-    handle_is_valid(handle);
-
-    if ((in_len + out_len) > PSA_MAX_IOVEC) {
-        ERROR("Too many iovecs: %lu + %lu", in_len, out_len);
-    }
-
-    vectors_t vecs = { 0 };
-    vecs.in_vec = in_vec;
-    vecs.in_len = in_len;
-    vecs.out_vec = out_vec;
-    vecs.out_len = out_len;
-
-    return send(handles[handle].client_qid,
-                handles[handle].server_qid,
-                &handles[handle].internal_server_qid,
-                type,
-                0,
-                &vecs);
-}
-
-void psa_close(psa_handle_t handle)
-{
-    handle_is_valid(handle);
-    if (send(handles[handle].client_qid, handles[handle].server_qid,
-             &handles[handle].internal_server_qid, PSA_IPC_DISCONNECT, 0, NULL)) {
-        ERROR("ERROR: Couldn't send disconnect msg");
-    } else {
-        if (msgctl(handles[handle].client_qid, IPC_RMID, NULL) != 0) {
-            ERROR("ERROR: Failed to delete msg queue");
-        }
-    }
-    INFO("Closing handle %u", handle);
-    handles[handle].valid = 0;
-}
diff --git a/tests/psa-client-server/psasim/src/common.c b/tests/psa-client-server/psasim/src/common.c
deleted file mode 100644
index 287bb50..0000000
--- a/tests/psa-client-server/psasim/src/common.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* Common code between clients and services */
-
-/*
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
- */
-
-#include "psa/common.h"
diff --git a/tests/psa-client-server/psasim/test/manifest.json b/tests/psa-client-server/psasim/src/manifest.json
similarity index 100%
rename from tests/psa-client-server/psasim/test/manifest.json
rename to tests/psa-client-server/psasim/src/manifest.json
diff --git a/tests/psa-client-server/psasim/src/psa_ff_client.c b/tests/psa-client-server/psasim/src/psa_ff_client.c
new file mode 100644
index 0000000..bc2989f
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_ff_client.c
@@ -0,0 +1,392 @@
+/* PSA firmware framework client API */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+#include "client.h"
+#include "common.h"
+#include "error_ext.h"
+#include "util.h"
+
+typedef struct internal_handle {
+    int server_qid;
+    int client_qid;
+    int internal_server_qid;
+    int valid;
+} internal_handle_t;
+
+typedef struct vectors {
+    const psa_invec *in_vec;
+    size_t in_len;
+    psa_outvec *out_vec;
+    size_t out_len;
+} vectors_t;
+
+/* Note that this implementation is functional and not secure */
+int __psa_ff_client_security_state = NON_SECURE;
+
+/* Access to this global is not thread safe */
+#define MAX_HANDLES 32
+static internal_handle_t handles[MAX_HANDLES] = { { 0 } };
+
+static int get_next_free_handle()
+{
+    /* Never return handle 0 as it's a special null handle */
+    for (int i = 1; i < MAX_HANDLES; i++) {
+        if (handles[i].valid == 0) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+static int handle_is_valid(psa_handle_t handle)
+{
+    if (handle > 0 && handle < MAX_HANDLES) {
+        if (handles[handle].valid == 1) {
+            return 1;
+        }
+    }
+    ERROR("ERROR: Invalid handle");
+    return 0;
+}
+
+static int get_queue_info(char *path, int *cqid, int *sqid)
+{
+
+    key_t server_queue_key;
+    int rx_qid, server_qid;
+
+    INFO("Attempting to contact a RoT service queue");
+
+    if ((rx_qid = msgget(IPC_PRIVATE, 0660)) == -1) {
+        ERROR("msgget: rx_qid");
+        return -1;
+    }
+
+    if ((server_queue_key = ftok(path, PROJECT_ID)) == -1) {
+        ERROR("ftok");
+        return -2;
+    }
+
+    if ((server_qid = msgget(server_queue_key, 0)) == -1) {
+        ERROR("msgget: server_qid");
+        return -3;
+    }
+
+    *cqid = rx_qid;
+    *sqid = server_qid;
+
+    return 0;
+}
+
+static psa_status_t process_response(int rx_qid, vectors_t *vecs, int type,
+                                     int *internal_server_qid)
+{
+
+    struct message response, request;
+    psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED;
+    size_t invec_seek[4] = { 0 };
+    size_t data_size;
+    psa_status_t invec, outvec; /* TODO: Should these be size_t ? */
+
+    assert(internal_server_qid > 0);
+
+    while (1) {
+        data_size = 0;
+        invec = 0;
+        outvec = 0;
+
+        // read response from server
+        if (msgrcv(rx_qid, &response, sizeof(struct message_text), 0, 0) == -1) {
+            ERROR("   msgrcv failed");
+            return ret;
+        }
+
+        // process return message from server
+        switch (response.message_type) {
+            case PSA_REPLY:
+                memcpy(&ret, response.message_text.buf, sizeof(psa_status_t));
+                INFO("   Message received from server: %d", ret);
+                if (type == PSA_IPC_CONNECT && ret > 0) {
+                    *internal_server_qid = ret;
+                    INFO("   ASSSIGNED q ID %d", *internal_server_qid);
+                    ret = PSA_SUCCESS;
+                }
+                return ret;
+                break;
+            case READ_REQUEST:
+                /* read data request */
+                request.message_type = READ_RESPONSE;
+
+                assert(vecs != 0);
+
+                memcpy(&invec, response.message_text.buf, sizeof(psa_status_t));
+                memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t));
+                INFO("   Partition asked for %lu bytes from invec %d", data_size, invec);
+
+                /* need to add more checks here */
+                assert(invec >= 0 && invec < PSA_MAX_IOVEC);
+
+                if (data_size > MAX_FRAGMENT_SIZE) {
+                    data_size = MAX_FRAGMENT_SIZE;
+                }
+
+                /* send response */
+                INFO("   invec_seek[invec] is %lu", invec_seek[invec]);
+                INFO("   Reading from offset %p", vecs->in_vec[invec].base + invec_seek[invec]);
+                memcpy(request.message_text.buf,
+                       (vecs->in_vec[invec].base + invec_seek[invec]),
+                       data_size);
+
+                /* update invec base TODO: check me */
+                invec_seek[invec] = invec_seek[invec] + data_size;
+
+                INFO("   Sending message of type %li", request.message_type);
+                INFO("       with content %s", request.message_text.buf);
+
+                if (msgsnd(*internal_server_qid, &request,
+                           sizeof(int) + sizeof(uint32_t) + data_size, 0) == -1) {
+                    ERROR("Internal error: failed to respond to read request");
+                }
+                break;
+            case WRITE_REQUEST:
+                assert(vecs != 0);
+
+                request.message_type = WRITE_RESPONSE;
+
+                memcpy(&outvec, response.message_text.buf, sizeof(psa_status_t));
+                memcpy(&data_size, response.message_text.buf + sizeof(size_t), sizeof(size_t));
+                INFO("   Partition wants to write %lu bytes to outvec %d", data_size, outvec);
+
+                assert(outvec >= 0 && outvec < PSA_MAX_IOVEC);
+
+                /* copy memory into message and send back amount written */
+                size_t sofar = vecs->out_vec[outvec].len;
+                memcpy(vecs->out_vec[outvec].base + sofar,
+                       response.message_text.buf+(sizeof(size_t)*2), data_size);
+                INFO("   Data size is %lu", data_size);
+                vecs->out_vec[outvec].len += data_size;
+
+                INFO("   Sending message of type %li", request.message_type);
+
+                /* send response */
+                if (msgsnd(*internal_server_qid, &request, sizeof(int) + data_size, 0) == -1) {
+                    ERROR("Internal error: failed to respond to write request");
+                }
+                break;
+            case SKIP_REQUEST:
+                memcpy(&invec, response.message_text.buf, sizeof(psa_status_t));
+                memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t));
+                INFO("   Partition asked to skip %lu bytes in invec %d", data_size, invec);
+                assert(invec >= 0 && invec < PSA_MAX_IOVEC);
+                /* update invec base TODO: check me */
+                invec_seek[invec] = invec_seek[invec] + data_size;
+                break;
+
+            default:
+                FATAL("   ERROR: unknown internal message type: %ld",
+                      response.message_type);
+                return ret;
+        }
+    }
+}
+
+static psa_status_t send(int rx_qid, int server_qid, int *internal_server_qid,
+                         int32_t type, uint32_t minor_version, vectors_t *vecs)
+{
+    {
+        psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED;
+        size_t request_msg_size = (sizeof(int) + sizeof(long)); /* msg type plus queue id */
+        struct message request;
+        request.message_type = 1; /* TODO: change this */
+        request.message_text.psa_type = type;
+        vector_sizes_t vec_sizes;
+
+        /* If the client is non-secure then set the NS bit */
+        if (__psa_ff_client_security_state != 0) {
+            request.message_type |= NON_SECURE;
+        }
+
+        assert(request.message_type >= 0);
+
+        INFO("SEND: Sending message of type %ld with psa_type %d", request.message_type, type);
+        INFO("     internal_server_qid = %i", *internal_server_qid);
+
+        request.message_text.qid = rx_qid;
+
+        if (type == PSA_IPC_CONNECT) {
+            memcpy(request.message_text.buf, &minor_version, sizeof(minor_version));
+            request_msg_size = request_msg_size + sizeof(minor_version);
+            INFO("   Request msg size is %lu", request_msg_size);
+        } else {
+            assert(internal_server_qid > 0);
+        }
+
+        if (vecs != NULL && type >= PSA_IPC_CALL) {
+
+            memset(&vec_sizes, 0, sizeof(vec_sizes));
+
+            /* Copy invec sizes */
+            for (size_t i = 0; i < (vecs->in_len); i++) {
+                vec_sizes.invec_sizes[i] = vecs->in_vec[i].len;
+                INFO("   Client sending vector %lu: %lu", i, vec_sizes.invec_sizes[i]);
+            }
+
+            /* Copy outvec sizes */
+            for (size_t i = 0; i < (vecs->out_len); i++) {
+                vec_sizes.outvec_sizes[i] = vecs->out_vec[i].len;
+
+                /* Reset to 0 since we need to eventually fill in with bytes written */
+                vecs->out_vec[i].len = 0;
+            }
+
+            memcpy(request.message_text.buf, &vec_sizes, sizeof(vec_sizes));
+            request_msg_size = request_msg_size + sizeof(vec_sizes);
+        }
+
+        INFO("   Sending and then waiting");
+
+        // send message to server
+        if (msgsnd(server_qid, &request, request_msg_size, 0) == -1) {
+            ERROR("   msgsnd failed");
+            return ret;
+        }
+
+        return process_response(rx_qid, vecs, type, internal_server_qid);
+    }
+}
+
+
+uint32_t psa_framework_version(void)
+{
+    return PSA_FRAMEWORK_VERSION;
+}
+
+psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
+{
+
+    int idx;
+    psa_status_t ret;
+    char pathname[PATHNAMESIZE] = { 0 };
+
+    idx = get_next_free_handle();
+
+    /* if there's a free handle available */
+    if (idx >= 0) {
+        snprintf(pathname, PATHNAMESIZE - 1, TMP_FILE_BASE_PATH "psa_service_%u", sid);
+        INFO("Attempting to contact RoT service at %s", pathname);
+
+        /* if communication is possible */
+        if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) {
+
+            ret = send(handles[idx].client_qid,
+                       handles[idx].server_qid,
+                       &handles[idx].internal_server_qid,
+                       PSA_IPC_CONNECT,
+                       minor_version,
+                       NULL);
+
+            /* if connection accepted by RoT service */
+            if (ret >= 0) {
+                handles[idx].valid = 1;
+                return idx;
+            } else {
+                INFO("Server didn't like you");
+            }
+        } else {
+            INFO("Couldn't contact RoT service. Does it exist?");
+
+            if (__psa_ff_client_security_state == 0) {
+                ERROR("Invalid SID");
+            }
+        }
+    }
+
+    INFO("Couldn't obtain a free handle");
+    return PSA_ERROR_CONNECTION_REFUSED;
+}
+
+uint32_t psa_version(uint32_t sid)
+{
+    int idx;
+    psa_status_t ret;
+    char pathname[PATHNAMESIZE] = { 0 };
+
+    idx = get_next_free_handle();
+
+    if (idx >= 0) {
+        snprintf(pathname, PATHNAMESIZE, TMP_FILE_BASE_PATH "psa_service_%u", sid);
+        if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) {
+            ret = send(handles[idx].client_qid,
+                       handles[idx].server_qid,
+                       &handles[idx].internal_server_qid,
+                       VERSION_REQUEST,
+                       0,
+                       NULL);
+            INFO("psa_version: Recieved from server %d", ret);
+            if (ret > 0) {
+                return ret;
+            }
+        }
+    }
+    INFO("psa_version failed: does the service exist?");
+    return PSA_VERSION_NONE;
+}
+
+psa_status_t psa_call(psa_handle_t handle,
+                      int32_t type,
+                      const psa_invec *in_vec,
+                      size_t in_len,
+                      psa_outvec *out_vec,
+                      size_t out_len)
+{
+
+    handle_is_valid(handle);
+
+    if ((in_len + out_len) > PSA_MAX_IOVEC) {
+        ERROR("Too many iovecs: %lu + %lu", in_len, out_len);
+    }
+
+    vectors_t vecs = { 0 };
+    vecs.in_vec = in_vec;
+    vecs.in_len = in_len;
+    vecs.out_vec = out_vec;
+    vecs.out_len = out_len;
+
+    return send(handles[handle].client_qid,
+                handles[handle].server_qid,
+                &handles[handle].internal_server_qid,
+                type,
+                0,
+                &vecs);
+}
+
+void psa_close(psa_handle_t handle)
+{
+    handle_is_valid(handle);
+    if (send(handles[handle].client_qid, handles[handle].server_qid,
+             &handles[handle].internal_server_qid, PSA_IPC_DISCONNECT, 0, NULL)) {
+        ERROR("ERROR: Couldn't send disconnect msg");
+    } else {
+        if (msgctl(handles[handle].client_qid, IPC_RMID, NULL) != 0) {
+            ERROR("ERROR: Failed to delete msg queue");
+        }
+    }
+    INFO("Closing handle %u", handle);
+    handles[handle].valid = 0;
+}
diff --git a/tests/psa-client-server/psasim/src/service.c b/tests/psa-client-server/psasim/src/psa_ff_server.c
similarity index 98%
rename from tests/psa-client-server/psasim/src/service.c
rename to tests/psa-client-server/psasim/src/psa_ff_server.c
index 69c25a2..ea797d8 100644
--- a/tests/psa-client-server/psasim/src/service.c
+++ b/tests/psa-client-server/psasim/src/psa_ff_server.c
@@ -16,11 +16,11 @@
 #include <time.h>
 #include <assert.h>
 
-#include "psa/service.h"
-#include "psasim/init.h"
-#include "psa/error_ext.h"
-#include "psa/common.h"
-#include "psa/util.h"
+#include "service.h"
+#include "init.h"
+#include "error_ext.h"
+#include "common.h"
+#include "util.h"
 
 #define MAX_CLIENTS 128
 #define MAX_MESSAGES 32
@@ -34,7 +34,7 @@
 };
 
 /* Note that this implementation is functional and not secure. */
-extern int __psa_ff_client_security_state;
+int __psa_ff_client_security_state = NON_SECURE;
 
 static psa_msg_t messages[MAX_MESSAGES]; /* Message slots */
 static uint8_t pending_message[MAX_MESSAGES] = { 0 }; /* Booleans indicating active message slots */
diff --git a/tests/psa-client-server/psasim/test/psa_functions_codes.h b/tests/psa-client-server/psasim/src/psa_functions_codes.h
similarity index 100%
rename from tests/psa-client-server/psasim/test/psa_functions_codes.h
rename to tests/psa-client-server/psasim/src/psa_functions_codes.h
diff --git a/tests/psa-client-server/psasim/test/server.c b/tests/psa-client-server/psasim/src/server.c
similarity index 97%
rename from tests/psa-client-server/psasim/test/server.c
rename to tests/psa-client-server/psasim/src/server.c
index b88a7ba..630bd73 100644
--- a/tests/psa-client-server/psasim/test/server.c
+++ b/tests/psa-client-server/psasim/src/server.c
@@ -9,9 +9,9 @@
 #include <stdio.h>
 
 /* Includes from psasim */
-#include "psa/service.h"
-#include "psa/error_ext.h"
-#include "psa/util.h"
+#include "service.h"
+#include "error_ext.h"
+#include "util.h"
 #include "psa_manifest/manifest.h"
 #include "psa_functions_codes.h"
 
diff --git a/tests/psa-client-server/psasim/test/Makefile b/tests/psa-client-server/psasim/test/Makefile
deleted file mode 100644
index 41f4bd4..0000000
--- a/tests/psa-client-server/psasim/test/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-LIBPSASIM_PATH := ..
-LIBPSACLIENT_PATH := ../../../libpsaclient
-LIBPSASERVER_PATH := ../../../libpsaserver
-
-LIBPSASIM := -L$(LIBPSASIM_PATH)/src -lpsaff
-LIBPSACLIENT := -L$(LIBPSACLIENT_PATH)/library -lmbedcrypto -lmbedx509 -lmbedtls
-LIBPSASERVER := -L$(LIBPSASERVER_PATH)/library -lmbedcrypto
-
-LIBPSASIM_H := -I$(LIBPSASIM_PATH)/include
-LIBPSACLIENT_H := -I$(LIBPSACLIENT_PATH)/include
-LIBPSASERVER_H := -I$(LIBPSASERVER_PATH)/include
-
-COMMON_INCLUDE := $(LIBPSASIM_H) -I./psa_manifest
-
-TEST_BIN = 	psa_client \
-			psa_partition
-
-GENERATED_H_FILES =	psa_manifest/manifest.h \
-					psa_manifest/pid.h \
-					psa_manifest/sid.h
-
-PARTITION_SERVER_BOOTSTRAP = psa_ff_bootstrap_TEST_PARTITION.c
-
-.PHONY: all clean
-
-all: $(TEST_BIN)
-
-psa_client: client.c $(GENERATED_H_FILES)
-	$(CC) $(COMMON_INCLUDE) $(LIBPSACLIENT_H) $(CFLAGS) $< $(LIBPSASIM) $(LIBPSACLIENT) $(LDFLAGS) -o $@
-
-psa_partition: $(PARTITION_SERVER_BOOTSTRAP) $(GENERATED_H_FILES)
-	$(CC) $(COMMON_INCLUDE) $(LIBPSASERVER_H) $(CFLAGS) $< $(LIBPSASIM) $(LIBPSASERVER) $(LDFLAGS) -o $@
-
-$(PARTITION_SERVER_BOOTSTRAP) $(GENERATED_H_FILES): manifest.json server.c
-	../tools/psa_autogen.py $<
-
-clean:
-	rm -f $(TEST_BIN) psa_ff_bootstrap_*.c
-	rm -f psa_notify_* psa_service_*
-	rm -f psa_manifest/*
diff --git a/tests/psa-client-server/psasim/test/client.c b/tests/psa-client-server/psasim/test/client.c
deleted file mode 100644
index 74e7bcb..0000000
--- a/tests/psa-client-server/psasim/test/client.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* psasim test client */
-
-/*
- *  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 <psa/client.h>
-#include <psa/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_SHA256_SID));
-    psa_handle_t h = psa_connect(PSA_SID_SHA256_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);
-
-    if (status != PSA_SUCCESS) {
-        return 1;
-    }
-    return 0;
-}
diff --git a/tests/psa-client-server/psasim/tools/psa_autogen.py b/tests/psa-client-server/psasim/tools/psa_autogen.py
index 53b1fea..cece2b7 100755
--- a/tests/psa-client-server/psasim/tools/psa_autogen.py
+++ b/tests/psa-client-server/psasim/tools/psa_autogen.py
@@ -15,6 +15,9 @@
 
 FILENAME = str(sys.argv[1])
 
+SCRIPT_PATH = os.path.dirname(__file__)
+GENERATED_H_PATH = os.path.join(SCRIPT_PATH, "..", "include", "psa_manifest")
+GENERATED_C_PATH = os.path.join(SCRIPT_PATH, "..", "src")
 
 with open(str(FILENAME), "r") as read_file:
     data = json.load(read_file)
@@ -32,14 +35,14 @@
             irqs = []
 
         try:
-            os.mkdir("psa_manifest")
+            os.mkdir(GENERATED_H_PATH)
             print("Generating psa_manifest directory")
         except OSError:
             print ("PSA manifest directory already exists")
 
-        man  = open(str("psa_manifest/" + FILENAME + ".h"), "w")
-        pids = open("psa_manifest/pid.h", "a")
-        sids = open("psa_manifest/sid.h", "a")
+        man  = open(os.path.join(GENERATED_H_PATH, FILENAME + ".h"), "w")
+        pids = open(os.path.join(GENERATED_H_PATH, "pid.h"), "a")
+        sids = open(os.path.join(GENERATED_H_PATH, "sid.h"), "a")
 
         if len(services) > 28:
            print ("Unsupported number of services")
@@ -116,23 +119,20 @@
         man.close()
 
         symbols = []
-        # Go through all the files in the current directory and look for the entrypoint
 
-        for root, directories, filenames in os.walk('.'):
+        # Go through source files and look for the entrypoint
+        for root, directories, filenames in os.walk(GENERATED_C_PATH):
             for filename in filenames:
-
                 if "psa_ff_bootstrap" in filename or filename == "psa_manifest":
                     continue
-
                 try:
                     fullpath = os.path.join(root,filename)
                     with open(fullpath, encoding='utf-8') as currentFile:
                         text = currentFile.read()
                         if str(entry_point + "(") in text:
-                            symbols.append(fullpath)
+                            symbols.append(filename)
                 except IOError:
                     print("Couldn't open " + filename)
-
                 except UnicodeDecodeError:
                     pass
 
@@ -144,8 +144,9 @@
             print("Duplicate entrypoint symbol detected: " + str(symbols))
             sys.exit(2)
         else:
-            bs = open(str("psa_ff_bootstrap_" + str(partition_name) + ".c"), "w")
-            bs.write("#include <psasim/init.h>\n")
+            bs = open(os.path.join(GENERATED_C_PATH, "psa_ff_bootstrap_" + partition_name + ".c"),
+                      "w")
+            bs.write("#include <init.h>\n")
             bs.write("#include \"" + symbols[0] + "\"\n")
             bs.write("#include <signal.h>\n\n")
             bs.write(qcode)