Add crypto service
Change-Id: Ifd55a4caaf0b95e3d1b6504863fba112a7e18f15
Signed-off-by: Julian Hall <julian.hall@arm.com>
diff --git a/components/service/crypto/client/test/component.cmake b/components/service/crypto/client/test/component.cmake
new file mode 100644
index 0000000..0374e84
--- /dev/null
+++ b/components/service/crypto/client/test/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/test_crypto_client.cpp"
+ )
+
diff --git a/components/service/crypto/client/test/mock/component.cmake b/components/service/crypto/client/test/mock/component.cmake
new file mode 100644
index 0000000..8202578
--- /dev/null
+++ b/components/service/crypto/client/test/mock/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/mock_crypto_client.cpp"
+ )
+
diff --git a/components/service/crypto/client/test/mock/mock_crypto_client.cpp b/components/service/crypto/client/test/mock/mock_crypto_client.cpp
new file mode 100644
index 0000000..8e55d34
--- /dev/null
+++ b/components/service/crypto/client/test/mock/mock_crypto_client.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "mock_crypto_client.h"
+
+mock_crypto_client::mock_crypto_client() :
+ test_crypto_client(),
+ m_crypto_provider(),
+ m_storage_provider(),
+ m_crypto_caller(),
+ m_storage_caller()
+{
+
+}
+
+mock_crypto_client::~mock_crypto_client()
+{
+
+}
+
+bool mock_crypto_client::init()
+{
+ bool should_do = test_crypto_client::init();
+
+ if (should_do) {
+
+ struct call_ep *storage_ep = mock_store_provider_init(&m_storage_provider);
+ struct rpc_caller *storage_caller = direct_caller_init_default(&m_storage_caller, storage_ep);
+
+ struct call_ep *crypto_ep = mbed_crypto_provider_init(&m_crypto_provider, storage_caller);
+ struct rpc_caller *crypto_caller = direct_caller_init_default(&m_crypto_caller, crypto_ep);
+
+ crypto_client::set_caller(crypto_caller);
+ }
+
+ return should_do;
+}
+
+bool mock_crypto_client::deinit()
+{
+ bool should_do = test_crypto_client::deinit();
+
+ if (should_do) {
+
+ mbed_crypto_provider_deinit(&m_crypto_provider);
+ mock_store_provider_deinit(&m_storage_provider);
+
+ direct_caller_deinit(&m_storage_caller);
+ direct_caller_deinit(&m_crypto_caller);
+ }
+
+ return should_do;
+}
+
+/* Test Methods */
+bool mock_crypto_client::keystore_reset_is_supported() const
+{
+ return true;
+}
+
+void mock_crypto_client::keystore_reset()
+{
+ mock_store_reset(&m_storage_provider);
+}
+
+bool mock_crypto_client::keystore_key_exists_is_supported() const
+{
+ return true;
+}
+
+bool mock_crypto_client::keystore_key_exists(uint32_t id) const
+{
+ return mock_store_exists(&m_storage_provider, id);
+}
+
+bool mock_crypto_client::keystore_keys_held_is_supported() const
+{
+ return true;
+}
+
+size_t mock_crypto_client::keystore_keys_held() const
+{
+ return mock_store_num_items(&m_storage_provider);
+}
+
+/* Factory for creating mock_crypto_client objects */
+class mock_crypto_client_factory : public test_crypto_client::factory
+{
+public:
+ mock_crypto_client_factory() :
+ test_crypto_client::factory()
+ {
+ test_crypto_client::register_factory(this);
+ }
+
+ ~mock_crypto_client_factory()
+ {
+ test_crypto_client::deregister_factory(this);
+ }
+
+ test_crypto_client *create()
+ {
+ return new mock_crypto_client;
+ };
+};
+
+/*
+ * Static construction causes this to be registered
+ * as the default factory for constructing test_crypto_client objects.
+ */
+static mock_crypto_client_factory default_factory;
diff --git a/components/service/crypto/client/test/mock/mock_crypto_client.h b/components/service/crypto/client/test/mock/mock_crypto_client.h
new file mode 100644
index 0000000..92ee6a9
--- /dev/null
+++ b/components/service/crypto/client/test/mock/mock_crypto_client.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOCK_CRYPTO_CLIENT_H
+#define MOCK_CRYPTO_CLIENT_H
+
+#include <service/crypto/client/test/test_crypto_client.h>
+#include <rpc/direct/direct_caller.h>
+#include <service/crypto/provider/mbedcrypto/crypto_provider.h>
+#include <service/secure_storage/provider/mock_store/mock_store_provider.h>
+
+/*
+ * A specialization of the crypto_client class that extends it to add crypto
+ * and storage providers to offer a viable crypto service from a single object.
+ * The mock_store storage provider is used for persistent key storage.
+ * This is only used for test purposes and should not be used for production
+ * deployments. Provides methods used for inspecting service state that
+ * support test.
+ */
+class mock_crypto_client : public test_crypto_client
+{
+public:
+ mock_crypto_client();
+ virtual ~mock_crypto_client();
+
+ bool init();
+ bool deinit();
+
+ /* Test support methods */
+ bool keystore_reset_is_supported() const;
+ void keystore_reset();
+
+ bool keystore_key_exists_is_supported() const;
+ bool keystore_key_exists(uint32_t id) const;
+
+ bool keystore_keys_held_is_supported() const;
+ size_t keystore_keys_held() const;
+
+private:
+ struct mbed_crypto_provider m_crypto_provider;
+ struct mock_store_provider m_storage_provider;
+ struct direct_caller m_crypto_caller;
+ struct direct_caller m_storage_caller;
+};
+
+#endif /* MOCK_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/test/standalone/component.cmake b/components/service/crypto/client/test/standalone/component.cmake
new file mode 100644
index 0000000..13488e8
--- /dev/null
+++ b/components/service/crypto/client/test/standalone/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/standalone_crypto_client.cpp"
+ )
+
diff --git a/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp b/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp
new file mode 100644
index 0000000..da3224d
--- /dev/null
+++ b/components/service/crypto/client/test/standalone/standalone_crypto_client.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "standalone_crypto_client.h"
+#include <protocols/rpc/common/packed-c/status.h>
+#include <protocols/service/psa/packed-c/status.h>
+
+standalone_crypto_client::standalone_crypto_client() :
+ test_crypto_client(),
+ m_crypto_provider(),
+ m_storage_provider(),
+ m_crypto_caller(),
+ m_storage_caller(),
+ m_dummy_storage_caller()
+{
+
+}
+
+standalone_crypto_client::~standalone_crypto_client()
+{
+
+}
+
+bool standalone_crypto_client::init()
+{
+ bool should_do = test_crypto_client::init();
+
+ if (should_do) {
+
+ struct rpc_caller *storage_caller;
+
+ if (!is_fault_injected(FAILED_TO_DISCOVER_SECURE_STORAGE)) {
+
+ /* Establish rpc session with storage provider */
+ struct call_ep *storage_ep = sfs_provider_init(&m_storage_provider);
+ storage_caller = direct_caller_init_default(&m_storage_caller, storage_ep);
+ }
+ else {
+
+ /*
+ * Missing storage service fault injected. To allow a somewhat viable
+ * crypto service to be started, use a dummy _caller that will safely
+ * terminate storage calls with an appropriate error.
+ */
+ storage_caller = dummy_caller_init(&m_dummy_storage_caller,
+ TS_RPC_CALL_ACCEPTED, PSA_ERROR_STORAGE_FAILURE);
+ }
+
+ struct call_ep *crypto_ep = mbed_crypto_provider_init(&m_crypto_provider, storage_caller);
+ struct rpc_caller *crypto_caller = direct_caller_init_default(&m_crypto_caller, crypto_ep);
+
+ crypto_client::set_caller(crypto_caller);
+ }
+
+ return should_do;
+}
+
+bool standalone_crypto_client::deinit()
+{
+ bool should_do = test_crypto_client::deinit();
+
+ if (should_do) {
+
+ mbed_crypto_provider_deinit(&m_crypto_provider);
+
+ direct_caller_deinit(&m_storage_caller);
+ direct_caller_deinit(&m_crypto_caller);
+ }
+
+ return should_do;
+}
+
+/* Fault injection */
+bool standalone_crypto_client::is_fault_supported(enum fault_code code) const
+{
+ return (code == test_crypto_client::FAILED_TO_DISCOVER_SECURE_STORAGE);
+}
+
+/* Test Methods */
+bool standalone_crypto_client::keystore_reset_is_supported() const
+{
+ return test_crypto_client::keystore_reset_is_supported();
+}
+
+void standalone_crypto_client::keystore_reset()
+{
+ test_crypto_client::keystore_reset();
+}
+
+bool standalone_crypto_client::keystore_key_exists_is_supported() const
+{
+ return test_crypto_client::keystore_key_exists_is_supported() ;
+}
+
+bool standalone_crypto_client::keystore_key_exists(uint32_t id) const
+{
+ return test_crypto_client::keystore_key_exists(id);
+}
+
+bool standalone_crypto_client::keystore_keys_held_is_supported() const
+{
+ return test_crypto_client::keystore_keys_held_is_supported();
+}
+
+size_t standalone_crypto_client::keystore_keys_held() const
+{
+ return test_crypto_client::keystore_keys_held();
+}
+
+/* Factory for creating standalone_crypto_client objects */
+class standalone_crypto_client_factory : public test_crypto_client::factory
+{
+public:
+ standalone_crypto_client_factory() :
+ test_crypto_client::factory()
+ {
+ test_crypto_client::register_factory(this);
+ }
+
+ ~standalone_crypto_client_factory()
+ {
+ test_crypto_client::deregister_factory(this);
+ }
+
+ test_crypto_client *create()
+ {
+ return new standalone_crypto_client;
+ };
+};
+
+/*
+ * Static construction causes this to be registered
+ * as the default factory for constructing test_crypto_client objects.
+ */
+static standalone_crypto_client_factory default_factory;
diff --git a/components/service/crypto/client/test/standalone/standalone_crypto_client.h b/components/service/crypto/client/test/standalone/standalone_crypto_client.h
new file mode 100644
index 0000000..9327fdc
--- /dev/null
+++ b/components/service/crypto/client/test/standalone/standalone_crypto_client.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STANDALONE_CRYPTO_CLIENT_H
+#define STANDALONE_CRYPTO_CLIENT_H
+
+#include <service/crypto/client/test/test_crypto_client.h>
+#include <rpc/direct/direct_caller.h>
+#include <rpc/dummy/dummy_caller.h>
+#include <service/crypto/provider/mbedcrypto/crypto_provider.h>
+#include <service/secure_storage/provider/secure_flash_store/sfs_provider.h>
+
+/*
+ * A specialization of the crypto_client class that extends it to add crypto
+ * and storage providers to offer a viable crypto service from a single object.
+ * This is only used for test purposes and should not be used for production
+ * deployments. Provides methods used for inspecting service state that
+ * support test.
+ */
+class standalone_crypto_client : public test_crypto_client
+{
+public:
+ standalone_crypto_client();
+ virtual ~standalone_crypto_client();
+
+ bool init();
+ bool deinit();
+
+ /* Test support methods */
+ bool keystore_reset_is_supported() const;
+ void keystore_reset();
+
+ bool keystore_key_exists_is_supported() const;
+ bool keystore_key_exists(uint32_t id) const;
+
+ bool keystore_keys_held_is_supported() const;
+ size_t keystore_keys_held() const;
+
+private:
+ bool is_fault_supported(enum fault_code code) const;
+
+ struct mbed_crypto_provider m_crypto_provider;
+ struct sfs_provider m_storage_provider;
+ struct direct_caller m_crypto_caller;
+ struct direct_caller m_storage_caller;
+ struct dummy_caller m_dummy_storage_caller;
+};
+
+#endif /* STANDALONE_CRYPTO_CLIENT_H */
diff --git a/components/service/crypto/client/test/test_crypto_client.cpp b/components/service/crypto/client/test/test_crypto_client.cpp
new file mode 100644
index 0000000..7232790
--- /dev/null
+++ b/components/service/crypto/client/test/test_crypto_client.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cassert>
+#include "test_crypto_client.h"
+
+test_crypto_client::factory *test_crypto_client::m_default_factory = NULL;
+
+test_crypto_client::test_crypto_client() :
+ crypto_client(),
+ m_is_initialized(false),
+ m_injected_faults()
+{
+
+}
+
+test_crypto_client::~test_crypto_client()
+{
+ deinit();
+}
+
+bool test_crypto_client::init()
+{
+ bool success = !m_is_initialized;
+ m_is_initialized = true;
+ return success;
+}
+
+bool test_crypto_client::deinit()
+{
+ bool success = m_is_initialized;
+ m_is_initialized = false;
+ return success;
+}
+
+test_crypto_client *test_crypto_client::create_default()
+{
+ /*
+ * It's mandatory to include a concrete test_crypto_client
+ * that registers its own factory in a deployment if you
+ * want to use this factory method.
+ */
+ assert(m_default_factory);
+ return m_default_factory->create();
+}
+
+void test_crypto_client::register_factory(factory *factory)
+{
+ /*
+ * Don't allow overriding of an existing default. This
+ * will happen if two test_crypto_client components have
+ * been included in a deployment.
+ */
+ assert(!m_default_factory);
+ m_default_factory = factory;
+}
+
+void test_crypto_client::deregister_factory(factory *factory)
+{
+ if (m_default_factory == factory) m_default_factory = NULL;
+}
+
+bool test_crypto_client::inject_fault(enum fault_code code)
+{
+ assert(!m_is_initialized);
+
+ bool is_supported = is_fault_supported(code);
+ if (is_supported) m_injected_faults.push_back(code);
+ return is_supported;
+}
+
+bool test_crypto_client::is_fault_supported(enum fault_code code) const
+{
+ /* Derived classes may override this if fault simualtion is supported */
+ (void)code;
+ return false;
+}
+
+bool test_crypto_client::is_fault_injected(enum fault_code code) const
+{
+ bool is_injected = false;
+
+ for (size_t i = 0; !is_injected && i < m_injected_faults.size(); ++i) {
+ is_injected = (m_injected_faults[i] == code);
+ }
+
+ return is_injected;
+}
+
+/*
+ * Test methods by default are not supported. Calling a non-supported
+ * method will trigger an assert. A class derived from this one may
+ * pick and choose which test methods it supports.
+ */
+bool test_crypto_client::keystore_reset_is_supported() const { return false; }
+void test_crypto_client::keystore_reset() { assert(false); }
+
+bool test_crypto_client::keystore_key_exists_is_supported() const { return false; }
+bool test_crypto_client::keystore_key_exists(uint32_t id) const { (void)id; assert(false); return false; }
+
+bool test_crypto_client::keystore_keys_held_is_supported() const { return false; }
+size_t test_crypto_client::keystore_keys_held() const { assert(false); return 0; }
\ No newline at end of file
diff --git a/components/service/crypto/client/test/test_crypto_client.h b/components/service/crypto/client/test/test_crypto_client.h
new file mode 100644
index 0000000..5b927db
--- /dev/null
+++ b/components/service/crypto/client/test/test_crypto_client.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEST_CRYPTO_CLIENT_H
+#define TEST_CRYPTO_CLIENT_H
+
+#include <service/crypto/client/cpp/crypto_client.h>
+#include <vector>
+
+/*
+ * A specialization of the crypto_client class that extends it to add
+ * virtial methods to support test. Depending on the deployment,
+ * real implementations of test methods may or may not exist. For example,
+ * for a real distributed deployment where the key store is located in
+ * a secure processing environment, back door test methods that peak
+ * into the keystore are clearly not possible (or at least desirable!).
+ * Each virtual test method is paired with a is_supported() method to
+ * allow test cases to adapt to circumstances.
+ */
+class test_crypto_client : public crypto_client
+{
+public:
+ virtual ~test_crypto_client();
+
+ virtual bool init();
+ virtual bool deinit();
+
+ /*
+ * A factory method for contsructing the default class
+ * of test_crypto_client for the deployment.
+ */
+ static test_crypto_client *create_default();
+
+ /*
+ * Fault conditions that may be injected to allow error
+ * handling to be tested.
+ */
+ enum fault_code
+ {
+ FAILED_TO_DISCOVER_SECURE_STORAGE
+ };
+
+ /*
+ * Injects the specified fault. May be called multiple
+ * times to inject different fault conditions. Faults
+ * should be injected prior to calling the init() method
+ * to allow startup faults to be simulated. Returns true
+ * if the fault condition can be simulated.
+ */
+ bool inject_fault(enum fault_code code);
+
+ /* Wipe all keys held in the keystore */
+ virtual bool keystore_reset_is_supported() const;
+ virtual void keystore_reset();
+
+ /* Check if a key is held in the keystore */
+ virtual bool keystore_key_exists_is_supported() const;
+ virtual bool keystore_key_exists(uint32_t id) const;
+
+ /* Return the number of keys in the keystore */
+ virtual bool keystore_keys_held_is_supported() const;
+ virtual size_t keystore_keys_held() const;
+
+ /* An abstract factory for constructing concrete test_crypto_client objects */
+ class factory
+ {
+ public:
+ virtual test_crypto_client *create() = 0;
+ };
+
+ static void register_factory(factory *factory);
+ static void deregister_factory(factory *factory);
+
+protected:
+ test_crypto_client();
+ virtual bool is_fault_supported(enum fault_code code) const;
+ bool is_fault_injected(enum fault_code code) const;
+
+private:
+ bool m_is_initialized;
+ std::vector<fault_code> m_injected_faults;
+ static factory *m_default_factory;
+};
+
+#endif /* STANDALONE_CRYPTO_CLIENT_H */