Test: Add rollback protection tests for SST
This patch adds a test suite to test the rollback protection feature
in the SST service.
Change-Id: I3f4bb980cad37c11bb279916fa3d689c0672a68a
Signed-off-by: Marc Moreno <marc.morenoberengue@arm.com>
diff --git a/secure_fw/services/secure_storage/CMakeLists.inc b/secure_fw/services/secure_storage/CMakeLists.inc
index e3d6737..a0430d1 100644
--- a/secure_fw/services/secure_storage/CMakeLists.inc
+++ b/secure_fw/services/secure_storage/CMakeLists.inc
@@ -76,8 +76,12 @@
set_property(DIRECTORY ${TEST_DIR} APPEND PROPERTY COMPILE_DEFINITIONS SST_ENCRYPTION)
if (SST_ROLLBACK_PROTECTION)
- list (APPEND SECURE_STORAGE_C_SRC
- "${SECURE_STORAGE_DIR}/nv_counters/sst_nv_counters.c")
+ if (NOT REGRESSION OR TFM_LVL GREATER 1)
+ # In case of regression test executed in TFM level 1, the SST rollback test suite has
+ # its own implementation of sst_nv_counters intefaces to be able to test different scenarios.
+ list (APPEND SECURE_STORAGE_C_SRC
+ "${SECURE_STORAGE_DIR}/nv_counters/sst_nv_counters.c")
+ endif()
set_property(SOURCE ${SECURE_STORAGE_C_SRC} APPEND PROPERTY COMPILE_DEFINITIONS SST_ROLLBACK_PROTECTION)
endif()
endif()
diff --git a/test/framework/CMakeLists.inc b/test/framework/CMakeLists.inc
index d8abf61..e5b7d51 100644
--- a/test/framework/CMakeLists.inc
+++ b/test/framework/CMakeLists.inc
@@ -40,6 +40,11 @@
list(APPEND ALL_SRC_C_S ${TEST_FRAMEWORK_C_SRC_S})
list(APPEND ALL_SRC_C_NS ${TEST_FRAMEWORK_C_SRC_NS})
+#Add compile definitions
+if (SST_ROLLBACK_PROTECTION AND SST_ENCRYPTION AND TFM_LVL EQUAL 1)
+ set_property(SOURCE ${TEST_FRAMEWORK_C_SRC_S} APPEND PROPERTY COMPILE_DEFINITIONS SST_ROLLBACK_PROTECTION)
+endif()
+
#Setting include directories
embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
diff --git a/test/framework/secure_suites.c b/test/framework/secure_suites.c
index 3ed95dd..89369cb 100644
--- a/test/framework/secure_suites.c
+++ b/test/framework/secure_suites.c
@@ -29,6 +29,10 @@
{®ister_testsuite_s_sst_sec_interface, 0, 0, 0},
{®ister_testsuite_s_sst_reliability, 0, 0, 0},
+#if defined(SST_ROLLBACK_PROTECTION) && defined(SST_ENCRYPTION)
+ {®ister_testsuite_s_rollback_protection, 0, 0, 0},
+#endif
+
/* Secure Audit Logging test cases */
{®ister_testsuite_s_audit_interface, 0, 0, 0},
diff --git a/test/suites/sst/CMakeLists.inc b/test/suites/sst/CMakeLists.inc
index fdb3e65..f527bc5 100644
--- a/test/suites/sst/CMakeLists.inc
+++ b/test/suites/sst/CMakeLists.inc
@@ -31,6 +31,10 @@
"${SECURE_STORAGE_TEST_DIR}/secure/sst_sec_interface_testsuite.c"
"${SECURE_STORAGE_TEST_DIR}/secure/sst_reliability_testsuite.c"
)
+ if (SST_ROLLBACK_PROTECTION AND SST_ENCRYPTION AND TFM_LVL EQUAL 1)
+ list(APPEND ALL_SRC_C_S "${SECURE_STORAGE_TEST_DIR}/secure/sst_rollback_protection_testsuite.c"
+ "${SECURE_STORAGE_TEST_DIR}/secure/nv_counters/test_sst_nv_counters.c")
+ endif()
list(APPEND ALL_SRC_C_NS "${SECURE_STORAGE_TEST_DIR}/non_secure/ns_test_helpers.c"
"${SECURE_STORAGE_TEST_DIR}/non_secure/sst_ns_interface_testsuite.c"
diff --git a/test/suites/sst/secure/nv_counters/test_sst_nv_counters.c b/test/suites/sst/secure/nv_counters/test_sst_nv_counters.c
new file mode 100644
index 0000000..ca47569
--- /dev/null
+++ b/test/suites/sst/secure/nv_counters/test_sst_nv_counters.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "test_sst_nv_counters.h"
+
+#include <limits.h>
+#include "secure_fw/services/secure_storage/nv_counters/sst_nv_counters.h"
+#include "secure_fw/services/secure_storage/sst_utils.h"
+
+#define DISABLE_INCREMENT 0
+#define ENABLE_INCREMENT 1
+
+#define TOTAL_SST_NV_COUNTERS 3
+#define INIT_NV_COUNTERS_VALUE 42
+
+static uint8_t nv_increment_status = ENABLE_INCREMENT;
+static uint32_t test_nv_counters[TOTAL_SST_NV_COUNTERS] = {0};
+
+static uint32_t get_nv_counter_position(enum tfm_nv_counter_t counter_id)
+{
+ switch (counter_id) {
+ case TFM_SST_NV_COUNTER_1:
+ return 0;
+ case TFM_SST_NV_COUNTER_2:
+ return 1;
+ case TFM_SST_NV_COUNTER_3:
+ return 2;
+ default:
+ return TOTAL_SST_NV_COUNTERS;
+ }
+}
+
+/* Implementation of SST NV counter interfaces defined by sst_nv_counters.h */
+enum psa_sst_err_t sst_init_nv_counter(void)
+{
+ static uint8_t is_init = 0;
+
+ if (is_init == 0) {
+ test_nv_counters[0] = INIT_NV_COUNTERS_VALUE;
+ test_nv_counters[1] = INIT_NV_COUNTERS_VALUE;
+ test_nv_counters[2] = INIT_NV_COUNTERS_VALUE;
+ is_init = 1;
+ }
+
+ return PSA_SST_ERR_SUCCESS;
+}
+
+enum psa_sst_err_t sst_read_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t *val)
+{
+ uint32_t nv_pos;
+
+ nv_pos = get_nv_counter_position(counter_id);
+ if (nv_pos >= TOTAL_SST_NV_COUNTERS) {
+ return PSA_SST_ERR_SYSTEM_ERROR;
+ }
+
+ /* Reads counter value */
+ *val = test_nv_counters[nv_pos];
+
+ return PSA_SST_ERR_SUCCESS;
+}
+
+enum psa_sst_err_t sst_increment_nv_counter(enum tfm_nv_counter_t counter_id)
+{
+ uint32_t nv_pos;
+
+ if (nv_increment_status == DISABLE_INCREMENT) {
+ return PSA_SST_ERR_SYSTEM_ERROR;
+ }
+
+ nv_pos = get_nv_counter_position(counter_id);
+ if (nv_pos >= TOTAL_SST_NV_COUNTERS) {
+ return PSA_SST_ERR_SYSTEM_ERROR;
+ }
+
+ if (test_nv_counters[nv_pos] == UINT32_MAX) {
+ return PSA_SST_ERR_SYSTEM_ERROR;
+ }
+
+ /* Increments counter value */
+ test_nv_counters[nv_pos]++;
+
+ return PSA_SST_ERR_SUCCESS;
+}
+
+/* Implementation of SST NV counter interfaces defined by
+ * test_sst_nv_counters.h
+ */
+void test_sst_disable_increment_nv_counter(void)
+{
+ nv_increment_status = DISABLE_INCREMENT;
+}
+
+void test_sst_enable_increment_nv_counter(void)
+{
+ nv_increment_status = ENABLE_INCREMENT;
+}
+
+enum psa_sst_err_t test_sst_read_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t *val)
+{
+ return sst_read_nv_counter(counter_id, val);
+}
+
+enum psa_sst_err_t test_sst_increment_nv_counter(
+ enum tfm_nv_counter_t counter_id)
+{
+ return sst_increment_nv_counter(counter_id);
+}
+
+enum psa_sst_err_t test_sst_decrement_nv_counter(
+ enum tfm_nv_counter_t counter_id)
+{
+ uint32_t nv_pos;
+
+ nv_pos = get_nv_counter_position(counter_id);
+ if (nv_pos >= TOTAL_SST_NV_COUNTERS) {
+ return PSA_SST_ERR_SYSTEM_ERROR;
+ }
+
+ if (test_nv_counters[nv_pos] == 0) {
+ return PSA_SST_ERR_SYSTEM_ERROR;
+ }
+
+ /* Decrements counter value */
+ test_nv_counters[nv_pos]--;
+
+ return PSA_SST_ERR_SUCCESS;
+}
+
+enum psa_sst_err_t test_sst_set_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t value)
+{
+ uint32_t nv_pos;
+
+ nv_pos = get_nv_counter_position(counter_id);
+ if (nv_pos >= TOTAL_SST_NV_COUNTERS) {
+ return PSA_SST_ERR_SYSTEM_ERROR;
+ }
+
+ /* Sets counter value */
+ test_nv_counters[nv_pos] = value;
+
+ return PSA_SST_ERR_SUCCESS;
+}
diff --git a/test/suites/sst/secure/nv_counters/test_sst_nv_counters.h b/test/suites/sst/secure/nv_counters/test_sst_nv_counters.h
new file mode 100644
index 0000000..c57203d
--- /dev/null
+++ b/test/suites/sst/secure/nv_counters/test_sst_nv_counters.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TEST_SST_NV_COUNTERS_H__
+#define __TEST_SST_NV_COUNTERS_H__
+
+#include <stdint.h>
+#include "psa_sst_api.h"
+#include "platform/include/tfm_plat_nv_counters.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Reads the given non-volatile (NV) counter.
+ *
+ * \param[in] counter_id NV counter ID.
+ * \param[out] val Pointer to store the current NV counter value.
+ *
+ * \return PSA_SST_ERR_SUCCESS if the value is read correctly, otherwise
+ * PSA_SST_ERR_SYSTEM_ERROR
+ */
+enum psa_sst_err_t test_sst_read_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t *val);
+
+/**
+ * \brief Increments the given non-volatile (NV) counter.
+ *
+ * \param[in] counter_id NV counter ID.
+ *
+ * \return When the NV counter reaches its maximum value, the
+ * PSA_SST_ERR_SYSTEM_ERROR error is returned to indicate the value
+ * cannot be incremented. Otherwise, PSA_SST_ERR_SUCCESS.
+ */
+enum psa_sst_err_t test_sst_increment_nv_counter(
+ enum tfm_nv_counter_t counter_id);
+
+/**
+ * \brief Decrements the given non-volatile (NV) counter.
+ *
+ * \param[in] counter_id NV counter ID.
+ *
+ * \return When the NV counter reaches its minimum value, the
+ * PSA_SST_ERR_SYSTEM_ERROR error is returned to indicate the value
+ * cannot be decremented. Otherwise, PSA_SST_ERR_SUCCESS.
+ */
+enum psa_sst_err_t test_sst_decrement_nv_counter(
+ enum tfm_nv_counter_t counter_id);
+/**
+ * \brief Disables SST increment nv counter function to force
+ * PSA_SST_ERR_SYSTEM_ERROR return value as an indication that NV counter
+ * reaches its maximum value.
+ */
+void test_sst_disable_increment_nv_counter(void);
+
+/**
+ * \brief Enables SST increment nv counter function to work normally.
+ */
+void test_sst_enable_increment_nv_counter(void);
+
+/**
+ * \brief Sets a new value into the given non-volatile (NV) counter.
+ *
+ * \param[in] counter_id NV counter Id.
+ * \param[in] value New NV counter value.
+ *
+ * \return When the NV counter reaches its maximum value, the
+ * PSA_SST_ERR_SYSTEM_ERROR error is returned to indicate the value
+ * cannot be set. Otherwise, PSA_SST_ERR_SUCCESS.
+ */
+enum psa_sst_err_t test_sst_set_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TEST_SST_NV_COUNTERS_H__ */
+
diff --git a/test/suites/sst/secure/sst_rollback_protection_testsuite.c b/test/suites/sst/secure/sst_rollback_protection_testsuite.c
new file mode 100644
index 0000000..e7400db
--- /dev/null
+++ b/test/suites/sst/secure/sst_rollback_protection_testsuite.c
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "sst_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "nv_counters/test_sst_nv_counters.h"
+#include "psa_sst_api.h"
+#include "secure_fw/services/secure_storage/assets/sst_asset_defs.h"
+#include "secure_fw/services/secure_storage/sst_object_system.h"
+#include "s_test_helpers.h"
+#include "test/framework/test_framework_helpers.h"
+
+/* Test suite defines */
+#define READ_BUF_SIZE 1UL
+#define WRITE_BUF_SIZE 1UL
+
+/* Define default asset's token */
+#define ASSET_TOKEN NULL
+#define ASSET_TOKEN_SIZE 0
+
+/*
+ * Summary of tests covered by the test suite.
+ *
+ * SST version | NVC1 | NVC2 | NVC3 | Result | Test Num
+ * ------------|------|------|------|----------|------------
+ * X | X | X | X | Valid | 1
+ * N | X | X | X | Invalid | 2
+ * X | X | X | N | Valid | 3
+ * N | X | N | N | Valid | 4
+ * X | X | N | N | Valid | 5
+ * X | X | M | N | Valid | 6
+ * M | X | M | N | Invalid | 7
+ * N | X | M | N | Invalid | 8
+ *
+ * Test 9 checks the SST result when the non-volatile (NV) counter 1 cannot be
+ * incremented (e.g it has reached its maximum value).
+ */
+
+/* List of tests */
+static void tfm_sst_test_4001(struct test_result_t *ret);
+static void tfm_sst_test_4002(struct test_result_t *ret);
+static void tfm_sst_test_4003(struct test_result_t *ret);
+static void tfm_sst_test_4004(struct test_result_t *ret);
+static void tfm_sst_test_4005(struct test_result_t *ret);
+static void tfm_sst_test_4006(struct test_result_t *ret);
+static void tfm_sst_test_4007(struct test_result_t *ret);
+static void tfm_sst_test_4008(struct test_result_t *ret);
+static void tfm_sst_test_4009(struct test_result_t *ret);
+
+static struct test_t interface_tests[] = {
+ {&tfm_sst_test_4001, "TFM_SST_TEST_4001",
+ "Check SST area version when NV counters 1/2/3 have the same value",
+ {0}},
+ {&tfm_sst_test_4002, "TFM_SST_TEST_4002",
+ "Check SST area version when it is different from NV counters 1/2/3",
+ {0}},
+ {&tfm_sst_test_4003, "TFM_SST_TEST_4003",
+ "Check SST area version when NV counters 1 and 2 are equals, 3 is "
+ "different, and SST area version match NV counters 1 and 2", {0}},
+ {&tfm_sst_test_4004, "TFM_SST_TEST_4004",
+ "Check SST area version when NV counters 2 and 3 are equals, 1 is "
+ "different and SST area version match NV counter 2 and 3", {0}},
+ {&tfm_sst_test_4005, "TFM_SST_TEST_4005",
+ "Check SST area version when NV counters 2 and 3 are equals, 1 is "
+ "different and SST area version match NV counter 1", {0}},
+ {&tfm_sst_test_4006, "TFM_SST_TEST_4006",
+ "Check SST area version when NV counters 1, 2 and 3 have different values "
+ "and SST area version match NV counter 1 value", {0}},
+ {&tfm_sst_test_4007, "TFM_SST_TEST_4007",
+ "Check SST area version when NV counters 1, 2 and 3 have different values "
+ "and SST area version match NV counter 2 value", {0}},
+ {&tfm_sst_test_4008, "TFM_SST_TEST_4008",
+ "Check SST area version when NV counters 1, 2 and 3 have different values "
+ "and SST area version match NV counter 3 value", {0}},
+ {&tfm_sst_test_4009, "TFM_SST_TEST_4009",
+ "Check SST area version when NV counter 1 cannot be incremented", {0}},
+};
+
+void register_testsuite_s_rollback_protection(struct test_suite_t *p_test_suite)
+{
+ uint32_t list_size = (sizeof(interface_tests) / sizeof(interface_tests[0]));
+
+ set_testsuite("SST rollback protection tests (TFM_SST_TEST_4XXX)",
+ interface_tests, list_size, p_test_suite);
+}
+
+/**
+ * \brief Check SST area version when NV counters 1/2/3 have the same value.
+ * It also checks that the 3 NV counters are aligned and they have been
+ * increased by 1 unit.
+ */
+static void tfm_sst_test_4001(struct test_result_t *ret)
+{
+ struct sst_test_buf_t io_data;
+ enum psa_sst_err_t err;
+ uint32_t old_nvc_1, nvc_1, nvc_2, nvc_3;
+ uint8_t read_data = 'X';
+ uint8_t wrt_data = 'D';
+
+ /* Prepares test context */
+ if (prepare_test_ctx(ret) != 0) {
+ return;
+ }
+
+ /* Creates an asset in the SST area to generate a new SST area version */
+ err = psa_sst_create(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN,
+ ASSET_TOKEN_SIZE);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Create should not fail for application S_APP_ID");
+ return;
+ }
+
+ /* Reads NV counter 1 to get the save the value to compare it later */
+ err = test_sst_read_nv_counter(TFM_SST_NV_COUNTER_1, &old_nvc_1);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Read should not fail");
+ return;
+ }
+
+ /* Sets data structure for write request */
+ io_data.data = &wrt_data;
+ io_data.size = WRITE_BUF_SIZE;
+ io_data.offset = 0;
+
+ /* Writes data into the asset */
+ err = psa_sst_write(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN, ASSET_TOKEN_SIZE,
+ io_data.size, io_data.offset, io_data.data);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Write should not fail for application S_APP_ID");
+ return;
+ }
+
+ /* Validates the 3 NV counters have the same value and it has been increased
+ * by 1 unit.
+ */
+
+ /* Reads NV counter 1 to get the current value */
+ err = test_sst_read_nv_counter(TFM_SST_NV_COUNTER_1, &nvc_1);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Read should not fail");
+ return;
+ }
+
+ /* Checks if NV counter 1 value has been increased by 1 unit as result of
+ * process the write request.
+ */
+ if (nvc_1 != (old_nvc_1 + 1)) {
+ TEST_FAIL("NV counter 1 has been increased more than 1 unit");
+ return;
+ }
+
+ /* Reads NV counter 2 to get the current value */
+ err = test_sst_read_nv_counter(TFM_SST_NV_COUNTER_2, &nvc_2);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Read should not fail");
+ return;
+ }
+
+ if (nvc_1 != nvc_2) {
+ TEST_FAIL("NV counter 1 and 2 should have the same value");
+ return;
+ }
+
+ /* Reads NV counter 3 to get the current value */
+ err = test_sst_read_nv_counter(TFM_SST_NV_COUNTER_3, &nvc_3);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Read should not fail");
+ return;
+ }
+
+ if (nvc_2 != nvc_3) {
+ TEST_FAIL("NV counter 2 and 3 should have the same value");
+ return;
+ }
+
+ /* Simulates a reboot in the system by calling sst_system_prepare(). This
+ * function is called when the SST service is initialized.
+ *
+ * Prepare should not fail as the NV counters has the same values and
+ * the SST area authentication is aligned with those values.
+ */
+ err = sst_system_prepare();
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("AM prepare should not fail");
+ return;
+ }
+
+ /* Sets data structure for read request */
+ io_data.data = &read_data;
+ io_data.size = READ_BUF_SIZE;
+ io_data.offset = 0;
+
+ /* Reads data from the asset */
+ err = psa_sst_read(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN, ASSET_TOKEN_SIZE,
+ io_data.size, io_data.offset, io_data.data);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Read should not fail for application S_APP_ID");
+ return;
+ }
+
+ if (read_data != wrt_data) {
+ TEST_FAIL("Read and write data values are different");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Check SST area version when it is different from NV counters
+ * 1/2/3.
+ */
+static void tfm_sst_test_4002(struct test_result_t *ret)
+{
+ enum psa_sst_err_t err;
+
+ /* Prepares test context */
+ if (prepare_test_ctx(ret) != 0) {
+ return;
+ }
+
+ /* Creates an asset in the SST area to generate a new SST area version */
+ err = psa_sst_create(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN,
+ ASSET_TOKEN_SIZE);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Create should not fail for application S_APP_ID");
+ return;
+ }
+
+ /* Increments all counters to make that SST area version old/invalid */
+ err = test_sst_increment_nv_counter(TFM_SST_NV_COUNTER_1);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Increment should not fail");
+ return;
+ }
+
+ err = test_sst_increment_nv_counter(TFM_SST_NV_COUNTER_2);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Increment should not fail");
+ return;
+ }
+
+ err = test_sst_increment_nv_counter(TFM_SST_NV_COUNTER_3);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Increment should not fail");
+ return;
+ }
+
+ /* Simulates a reboot in the system by calling sst_system_prepare(). This
+ * function is called when the SST service is initialized.
+ *
+ * Prepare should fail as the SST area version does not match the
+ * NV counters values.
+ */
+ err = sst_system_prepare();
+ if (err != PSA_SST_ERR_SYSTEM_ERROR) {
+ TEST_FAIL("AM prepare should fail as version is old");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Check SST area version when NV counters 1 and 2 are equals, 3 is
+ * different and SST area version match NV counter 1 and 2 values.
+ * It simulates a power cut during write action while the counter 3 is
+ * being increased.
+ */
+static void tfm_sst_test_4003(struct test_result_t *ret)
+{
+ enum psa_sst_err_t err;
+
+ /* Prepares test context */
+ if (prepare_test_ctx(ret) != 0) {
+ return;
+ }
+
+ /* Creates an asset in the SST area to generate a new SST area version */
+ err = psa_sst_create(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN,
+ ASSET_TOKEN_SIZE);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Create should not fail");
+ return;
+ }
+
+ /* Decrements NV counters 3 to make it different from the other two counters
+ * and make the current SST area version match NV counter 1 and 2 values.
+ */
+ err = test_sst_decrement_nv_counter(TFM_SST_NV_COUNTER_3);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Decrement should not fail");
+ return;
+ }
+
+ /* Simulates a reboot in the system by calling sst_system_prepare(). This
+ * function is called when the SST service is initialized.
+ *
+ * Prepare should not fail as the SST area version match NV counters 1 and
+ * 2 values.
+ */
+ err = sst_system_prepare();
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("AM prepare should not fail");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Check SST area version when NV counters 2 and 3 are equals, 1 is
+ * different and SST area version match NV counter 2 and 3 values.
+ * It simulates a power cut during write action before increment counter
+ * 2 and 3, and the new SST area version is corrupted and only the old
+ * version match the NV counters.
+ */
+static void tfm_sst_test_4004(struct test_result_t *ret)
+{
+ enum psa_sst_err_t err;
+
+ /* Prepares test context */
+ if (prepare_test_ctx(ret) != 0) {
+ return;
+ }
+
+ /* Creates an asset in the SST area to generate a new SST area version */
+ err = psa_sst_create(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN,
+ ASSET_TOKEN_SIZE);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Create should not fail");
+ return;
+ }
+
+ /* Increments NV counters 1 to make it different from the other two counters
+ * and make the current SST area version match NV counter 2 and 3 values.
+ */
+ err = test_sst_increment_nv_counter(TFM_SST_NV_COUNTER_1);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Increment should not fail");
+ return;
+ }
+
+ /* Simulates a reboot in the system by calling sst_system_prepare(). This
+ * function is called when the SST service is initialized.
+ *
+ * Prepare should not fail as the SST area version match the NV counter 2
+ * and 3 values.
+ */
+ err = sst_system_prepare();
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("AM prepare should not fail");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Check SST area version when NV counters 2 and 3 are equals, 1 is
+ * different and SST area version match NV counter 1 value.
+ * It simulates a power cut during write action before increment counter
+ * 2 and 3, and the new SST area version is corrupted and only the old
+ * version match the NV counters.
+ */
+static void tfm_sst_test_4005(struct test_result_t *ret)
+{
+ enum psa_sst_err_t err;
+
+ /* Prepares test context */
+ if (prepare_test_ctx(ret) != 0) {
+ return;
+ }
+
+ /* Creates an asset in the SST area to generate a new SST area version */
+ err = psa_sst_create(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN,
+ ASSET_TOKEN_SIZE);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Create should not fail");
+ return;
+ }
+
+ /* Decrements NV counter 2 and 3 to make the SST area version match NV
+ * counter 1 only.
+ */
+ err = test_sst_decrement_nv_counter(TFM_SST_NV_COUNTER_2);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Decrement should not fail");
+ return;
+ }
+
+ err = test_sst_decrement_nv_counter(TFM_SST_NV_COUNTER_3);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Decrement should not fail");
+ return;
+ }
+
+ /* Simulates a reboot in the system by calling sst_system_prepare(). This
+ * function is called when the SST service is initialized.
+ *
+ * Prepare should not fail as the SST area version match the NV counter 1.
+ */
+ err = sst_system_prepare();
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("AM prepare should not fail");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Check SST area version when NV counters 1, 2 and 3 have different
+ * values and SST area version match NV counter 1 value.
+ */
+static void tfm_sst_test_4006(struct test_result_t *ret)
+{
+ enum psa_sst_err_t err;
+
+ /* Prepares test context */
+ if (prepare_test_ctx(ret) != 0) {
+ return;
+ }
+
+ /* Creates an asset in the SST area to generate a new SST area version */
+ err = psa_sst_create(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN,
+ ASSET_TOKEN_SIZE);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Create should not fail");
+ return;
+ }
+
+ /* Decrements NV counter 2 (1 time) and 3 (2 times) to make the SST area
+ * version match NV counter 1 only.
+ */
+ err = test_sst_decrement_nv_counter(TFM_SST_NV_COUNTER_2);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Decrement should not fail");
+ return;
+ }
+
+ err = test_sst_decrement_nv_counter(TFM_SST_NV_COUNTER_3);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Decrement should not fail");
+ return;
+ }
+
+ err = test_sst_decrement_nv_counter(TFM_SST_NV_COUNTER_3);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Decrement should not fail");
+ return;
+ }
+
+ /* Simulates a reboot in the system by calling sst_system_prepare(). This
+ * function is called when the SST service is initialized.
+ *
+ * Prepare should not fail as the SST area version match the NV counter 1.
+ */
+ err = sst_system_prepare();
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("AM prepare should not fail");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Check SST area version when NV counters 1, 2 and 3 have different
+ * values and SST area version match NV counter 2 value.
+ */
+static void tfm_sst_test_4007(struct test_result_t *ret)
+{
+ enum psa_sst_err_t err;
+
+ /* Prepares test context */
+ if (prepare_test_ctx(ret) != 0) {
+ return;
+ }
+
+ /* Creates an asset in the SST area to generate a new SST area version */
+ err = psa_sst_create(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN,
+ ASSET_TOKEN_SIZE);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Create should not fail");
+ return;
+ }
+
+ /* Increments NV counter 1 and decrements 3 to make the SST area
+ * version match NV counter 2 only.
+ */
+ err = test_sst_increment_nv_counter(TFM_SST_NV_COUNTER_1);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Increment should not fail");
+ return;
+ }
+
+ err = test_sst_decrement_nv_counter(TFM_SST_NV_COUNTER_3);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Decrement should not fail");
+ return;
+ }
+
+ /* Simulates a reboot in the system by calling sst_system_prepare(). This
+ * function is called when the SST service is initialized.
+ *
+ * Prepare should fail as the SST area version match the NV counter 2 and
+ * the other counters are different.
+ */
+ err = sst_system_prepare();
+ if (err != PSA_SST_ERR_SYSTEM_ERROR) {
+ TEST_FAIL("AM prepare should fail");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Check SST area version when NV counters 1, 2 and 3 have different
+ * values and SST area version match NV counter 3 value.
+ */
+static void tfm_sst_test_4008(struct test_result_t *ret)
+{
+ enum psa_sst_err_t err;
+
+ /* Prepares test context */
+ if (prepare_test_ctx(ret) != 0) {
+ return;
+ }
+
+ /* Creates an asset in the SST area to generate a new SST area version */
+ err = psa_sst_create(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN,
+ ASSET_TOKEN_SIZE);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Create should not fail");
+ return;
+ }
+
+ /* Increments NV counter 1 (2 times) and 2 (1 time) to make the SST area
+ * version match NV counter 3 only.
+ */
+ err = test_sst_increment_nv_counter(TFM_SST_NV_COUNTER_1);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Increment should not fail");
+ return;
+ }
+
+ err = test_sst_increment_nv_counter(TFM_SST_NV_COUNTER_1);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Increment should not fail");
+ return;
+ }
+
+ err = test_sst_increment_nv_counter(TFM_SST_NV_COUNTER_2);
+ if (err != PSA_SST_ERR_SUCCESS) {
+ TEST_FAIL("Increment should not fail");
+ return;
+ }
+
+ /* Simulates a reboot in the system by calling sst_system_prepare(). This
+ * function is called when the SST service is initialized.
+ *
+ * Prepare should fail as the SST area version match the NV counter 2 and
+ * the other counters are different.
+ */
+ err = sst_system_prepare();
+ if (err != PSA_SST_ERR_SYSTEM_ERROR) {
+ TEST_FAIL("AM prepare should fail");
+ return;
+ }
+
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Check SST area version when NV counter 1 cannot be incremented
+ * (e.g it has reached its maximum value)
+ */
+static void tfm_sst_test_4009(struct test_result_t *ret)
+{
+ enum psa_sst_err_t err;
+
+ /* Prepares test context */
+ if (prepare_test_ctx(ret) != 0) {
+ return;
+ }
+
+ /* Disables increment function to simulate that NV counter 1 has
+ * reached its maximum value.
+ */
+ test_sst_disable_increment_nv_counter();
+
+ /* Creates an asset in the SST area to generate a new SST area version */
+ err = psa_sst_create(SST_ASSET_ID_AES_KEY_192, ASSET_TOKEN,
+ ASSET_TOKEN_SIZE);
+ if (err != PSA_SST_ERR_SYSTEM_ERROR) {
+ TEST_FAIL("Create should fail as NV counter cannot be incremented");
+ return;
+ }
+
+ /* Enables counter again to not affect the next tests, if any */
+ test_sst_enable_increment_nv_counter();
+
+ ret->val = TEST_PASSED;
+}
diff --git a/test/suites/sst/secure/sst_tests.h b/test/suites/sst/secure/sst_tests.h
index 360550b..fc3ee3b 100644
--- a/test/suites/sst/secure/sst_tests.h
+++ b/test/suites/sst/secure/sst_tests.h
@@ -28,6 +28,17 @@
*/
void register_testsuite_s_sst_reliability(struct test_suite_t *p_test_suite);
+#if defined(SST_ROLLBACK_PROTECTION) && defined(SST_ENCRYPTION) \
+ && (TFM_LVL == 1)
+/**
+ * \brief Register testsuite for the sst rollback protection tests.
+ *
+ * \param[in] p_test_suite The test suite to be executed.
+ */
+void register_testsuite_s_rollback_protection(
+ struct test_suite_t *p_test_suite);
+#endif
+
#ifdef __cplusplus
}
#endif