Platform: Added a Non-Volatile counters service

This patch introduces a new platform service exposing
the non-volatile counters. Secure partitions can use
this secure API to access the initialisation,
increment and read operations on the nv counters,
by setting "TFM_SP_PLATFORM_NV_COUNTER" as a dependency.

Change-Id: Ia564e24417dfd9bb95cc61634dbbea17caa5974c
Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
diff --git a/docs/user_guides/services/tfm_platform_integration_guide.rst b/docs/user_guides/services/tfm_platform_integration_guide.rst
index db9d00d..767236e 100644
--- a/docs/user_guides/services/tfm_platform_integration_guide.rst
+++ b/docs/user_guides/services/tfm_platform_integration_guide.rst
@@ -73,6 +73,31 @@
 An IOCTL request type not supported on a particular platform should return
 ``TFM_PLATFORM_ERR_NOT_SUPPORTED``
 
+Non-Volatile counters
+=====================
+
+The Platform Service provides an abstracted service for exposing the NV counters
+to the secure world. The following operations are supported:
+
+- Increment a counter.
+- Read a counter value to a preallocated buffer.
+
+.. code-block:: c
+
+    enum tfm_platform_err_t
+    tfm_platform_nv_counter_increment(uint32_t counter_id);
+
+    enum tfm_platform_err_t
+    tfm_platform_nv_counter_read(uint32_t counter_id,
+                                 uint32_t size, uint8_t *val);
+
+The range of counters id is defined in :
+``platform/include/tfm_plat_nv_counters.h``
+
+For Level 2,3 isolation implementations, secure partitions in the
+Application Root of Trust, should have ``TFM_SP_PLATFORM_NV_COUNTER`` set as a
+dependency for access to the NV counter API.
+
 ***************************
 Current Service Limitations
 ***************************
diff --git a/interface/include/psa_manifest/sid.h b/interface/include/psa_manifest/sid.h
index 4e9e440..4b9b8c9 100644
--- a/interface/include/psa_manifest/sid.h
+++ b/interface/include/psa_manifest/sid.h
@@ -45,6 +45,8 @@
 #define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION                       (1U)
 #define TFM_SP_PLATFORM_IOCTL_SID                                  (0x00000041U)
 #define TFM_SP_PLATFORM_IOCTL_VERSION                              (1U)
+#define TFM_SP_PLATFORM_NV_COUNTER_SID                             (0x00000042U)
+#define TFM_SP_PLATFORM_NV_COUNTER_VERSION                         (1U)
 
 /******** TFM_SP_INITIAL_ATTESTATION ********/
 #define TFM_ATTEST_GET_TOKEN_SID                                   (0x00000020U)
diff --git a/interface/include/tfm_platform_api.h b/interface/include/tfm_platform_api.h
index fbbd757..8c9b0db 100644
--- a/interface/include/tfm_platform_api.h
+++ b/interface/include/tfm_platform_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -23,6 +23,9 @@
 #define TFM_PLATFORM_API_VERSION_MAJOR (0)
 #define TFM_PLATFORM_API_VERSION_MINOR (3)
 
+#define TFM_PLATFORM_API_ID_NV_READ       (1010)
+#define TFM_PLATFORM_API_ID_NV_INCREMENT  (1011)
+
 /*!
  * \enum tfm_platform_err_t
  *
@@ -62,6 +65,31 @@
                                            psa_invec *input,
                                            psa_outvec *output);
 
+/*!
+ * \brief Increments the given non-volatile (NV) counter by one
+ *
+ * \param[in]  counter_id  NV counter ID.
+ *
+ * \return  TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise,
+ *          it returns TFM_PLATFORM_ERR_SYSTEM_ERROR.
+ */
+enum tfm_platform_err_t
+tfm_platform_nv_counter_increment(uint32_t counter_id);
+
+/*!
+ * \brief Reads the given non-volatile (NV) counter
+ *
+ * \param[in]  counter_id  NV counter ID.
+ * \param[in]  size        Size of the buffer to store NV counter value
+ *                         in bytes.
+ * \param[out] val         Pointer to store the current NV counter value.
+ *
+ * \return  TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise,
+ *          it returns TFM_PLATFORM_ERR_SYSTEM_ERROR.
+ */
+enum tfm_platform_err_t
+tfm_platform_nv_counter_read(uint32_t counter_id,
+                             uint32_t size, uint8_t *val);
 
 #ifdef __cplusplus
 }
diff --git a/interface/include/tfm_veneers.h b/interface/include/tfm_veneers.h
index 5f9c5b6..d2d9207 100644
--- a/interface/include/tfm_veneers.h
+++ b/interface/include/tfm_veneers.h
@@ -112,6 +112,8 @@
 /******** TFM_SP_PLATFORM ********/
 psa_status_t tfm_platform_sp_system_reset_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 psa_status_t tfm_platform_sp_ioctl_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_platform_sp_nv_counter_read_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_platform_sp_nv_counter_increment_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 #endif /* TFM_PARTITION_PLATFORM */
 
 #ifdef TFM_PARTITION_INITIAL_ATTESTATION
diff --git a/platform/include/tfm_plat_nv_counters.h b/platform/include/tfm_plat_nv_counters.h
index 5d63399..3588929 100644
--- a/platform/include/tfm_plat_nv_counters.h
+++ b/platform/include/tfm_plat_nv_counters.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -34,7 +34,9 @@
     PLAT_NV_COUNTER_3,      /* Used by bootloader */
     PLAT_NV_COUNTER_4,      /* Used by bootloader */
 #endif
-    PLAT_NV_COUNTER_MAX
+    PLAT_NV_COUNTER_MAX,
+    PLAT_NV_COUNTER_BOUNDARY = UINT32_MAX  /* Fix  tfm_nv_counter_t size
+                                              to 4 bytes */
 };
 
 #ifdef __cplusplus
diff --git a/secure_fw/ns_callable/tfm_veneers.c b/secure_fw/ns_callable/tfm_veneers.c
index 697860a..02b0ca4 100644
--- a/secure_fw/ns_callable/tfm_veneers.c
+++ b/secure_fw/ns_callable/tfm_veneers.c
@@ -106,6 +106,8 @@
 /******** TFM_SP_PLATFORM ********/
 psa_status_t platform_sp_system_reset(psa_invec *, size_t, psa_outvec *, size_t);
 psa_status_t platform_sp_ioctl(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t platform_sp_nv_counter_read(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t platform_sp_nv_counter_increment(psa_invec *, size_t, psa_outvec *, size_t);
 #endif /* TFM_PARTITION_PLATFORM */
 
 #ifdef TFM_PARTITION_INITIAL_ATTESTATION
@@ -274,6 +276,8 @@
 /******** TFM_SP_PLATFORM ********/
 TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_system_reset)
 TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_ioctl)
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_nv_counter_read)
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_nv_counter_increment)
 #endif /* TFM_PARTITION_PLATFORM */
 
 #ifdef TFM_PARTITION_INITIAL_ATTESTATION
diff --git a/secure_fw/services/platform/platform_sp.c b/secure_fw/services/platform/platform_sp.c
index b17e62e..9756d5d 100644
--- a/secure_fw/services/platform/platform_sp.c
+++ b/secure_fw/services/platform/platform_sp.c
@@ -8,7 +8,20 @@
 #include "platform_sp.h"
 
 #include "platform/include/tfm_platform_system.h"
+#include "platform/include/tfm_plat_nv_counters.h"
 #include "secure_fw/include/tfm_spm_services_api.h"
+#include "tfm_secure_api.h"
+#include "psa_manifest/pid.h"
+
+#define NV_COUNTER_ID_SIZE  sizeof(enum tfm_nv_counter_t)
+#define NV_COUNTER_MAP_SIZE   3
+
+/* Access map using NVCOUNTER_IDX -> tfm_partition-id key-value pairs */
+static const int32_t nv_counter_access_map[NV_COUNTER_MAP_SIZE] = {
+                                          [PLAT_NV_COUNTER_0] = TFM_SP_STORAGE,
+                                          [PLAT_NV_COUNTER_1] = TFM_SP_STORAGE,
+                                          [PLAT_NV_COUNTER_2] = TFM_SP_STORAGE
+              };
 
 #ifdef TFM_PSA_API
 #include "psa_manifest/tfm_platform.h"
@@ -22,6 +35,36 @@
 typedef enum tfm_platform_err_t (*plat_func_t)(const psa_msg_t *msg);
 #endif
 
+/*
+ * \brief Verifies ownership of a nv_counter resource to a partition id.
+ *
+ * \param[in] nv_counter_no  Number of nv_counter as assigned in platform.
+ *
+ * \return true if the calling partition is allowed to access this counter id
+ */
+
+static bool nv_counter_access_grant(int32_t client_id,
+                                    enum tfm_nv_counter_t nv_counter_no)
+{
+    int32_t req_id;
+
+    /* Boundary check the input argument */
+    if (nv_counter_no >= NV_COUNTER_MAP_SIZE ||
+        nv_counter_no < 0 || nv_counter_no >= PLAT_NV_COUNTER_MAX) {
+        return false;
+    }
+
+    req_id = nv_counter_access_map[nv_counter_no];
+
+    /* NV Counters are indexed from 0 and incremented. A gap in the platform
+     *  counter sequence is assigned a zero( invalid ) partition id
+     */
+    if (client_id == req_id && req_id != 0) {
+       return true;
+    }
+    return false;
+}
+
 enum tfm_platform_err_t platform_sp_system_reset(void)
 {
     /* Check if SPM allows the system reset */
@@ -62,6 +105,70 @@
     return tfm_platform_hal_ioctl(request, input, output);
 }
 
+enum tfm_platform_err_t
+platform_sp_nv_counter_read(psa_invec  *in_vec,  uint32_t num_invec,
+                            psa_outvec *out_vec, uint32_t num_outvec)
+{
+    enum tfm_plat_err_t err;
+    enum tfm_nv_counter_t counter_id;
+    uint32_t counter_size;
+    int32_t status, client_id;
+
+    if (in_vec[0].len != NV_COUNTER_ID_SIZE ||
+        num_invec != 1 || num_outvec != 1) {
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+    counter_id = *((enum tfm_nv_counter_t *)in_vec[0].base);
+    counter_size = out_vec[0].len;
+
+    status = tfm_core_get_caller_client_id(&client_id);
+    if (status != (int32_t)TFM_SUCCESS) {
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+
+    if (!nv_counter_access_grant(client_id, counter_id)) {
+       return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+    err = tfm_plat_read_nv_counter(counter_id, counter_size,
+                                   (uint8_t *)out_vec[0].base);
+    if (err != TFM_PLAT_ERR_SUCCESS) {
+       return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+
+    return TFM_PLATFORM_ERR_SUCCESS;
+}
+
+enum tfm_platform_err_t
+platform_sp_nv_counter_increment(psa_invec  *in_vec,  uint32_t num_invec,
+                                 psa_outvec *out_vec, uint32_t num_outvec)
+{
+    enum tfm_plat_err_t err;
+    enum tfm_nv_counter_t counter_id;
+    int32_t client_id, status;
+
+    if (in_vec[0].len != NV_COUNTER_ID_SIZE ||
+        num_invec != 1 || num_outvec != 0) {
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+
+    status = tfm_core_get_caller_client_id(&client_id);
+    if (status != (int32_t)TFM_SUCCESS) {
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+
+    counter_id = *((enum tfm_nv_counter_t *)in_vec[0].base);
+
+    if (!nv_counter_access_grant(client_id, counter_id)) {
+       return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+    err = tfm_plat_increment_nv_counter(counter_id);
+    if (err != TFM_PLAT_ERR_SUCCESS) {
+       return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+
+    return TFM_PLATFORM_ERR_SUCCESS;
+}
+
 #else /* TFM_PSA_API */
 
 static enum tfm_platform_err_t
@@ -73,6 +180,74 @@
 }
 
 static enum tfm_platform_err_t
+platform_sp_nv_counter_ipc(const psa_msg_t *msg)
+{
+    enum tfm_plat_err_t err = TFM_PLAT_ERR_SYSTEM_ERR;
+    size_t in_len = PSA_MAX_IOVEC, out_len = PSA_MAX_IOVEC, num = 0;
+
+    enum tfm_nv_counter_t counter_id;
+    uint8_t counter_val = 0;
+
+    /* Check the number of in_vec filled */
+    while ((in_len > 0) && (msg->in_size[in_len - 1] == 0)) {
+        in_len--;
+    }
+
+    /* Check the number of out_vec filled */
+    while ((out_len > 0) && (msg->out_size[out_len - 1] == 0)) {
+        out_len--;
+    }
+    switch (msg->type) {
+    case TFM_PLATFORM_API_ID_NV_INCREMENT:
+        if (msg->in_size[0] != NV_COUNTER_ID_SIZE ||
+            in_len != 1 || out_len != 0) {
+            return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+        }
+
+        num = psa_read(msg->handle, 0, &counter_id, msg->in_size[0]);
+
+        if (num != msg->in_size[0]) {
+            return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+        }
+
+        if (!nv_counter_access_grant(msg->client_id, counter_id)) {
+           return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+        }
+
+        err = tfm_plat_increment_nv_counter(counter_id);
+        break;
+    case TFM_PLATFORM_API_ID_NV_READ:
+        num = psa_read(msg->handle, 0, &counter_id, msg->in_size[0]);
+
+        if (msg->in_size[0] != NV_COUNTER_ID_SIZE ||
+            in_len != 1 || out_len != 1) {
+            return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+        }
+
+        if (!nv_counter_access_grant(msg->client_id, counter_id)) {
+           return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+        }
+
+        err = tfm_plat_read_nv_counter(counter_id,  msg->out_size[0],
+                                       &counter_val);
+
+        if (err != TFM_PLAT_ERR_SUCCESS) {
+           return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+        }
+        psa_write(msg->handle, 0, &counter_val, msg->out_size[0]);
+        break;
+    default:
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+        break;
+    }
+
+    if (err != TFM_PLAT_ERR_SUCCESS) {
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+    return TFM_PLATFORM_ERR_SUCCESS;
+}
+
+static enum tfm_platform_err_t
 platform_sp_ioctl_ipc(const psa_msg_t *msg)
 {
     void *input = NULL;
@@ -147,6 +322,8 @@
         psa_reply(msg.handle, PSA_SUCCESS);
         break;
     case PSA_IPC_CALL:
+    case TFM_PLATFORM_API_ID_NV_READ:
+    case TFM_PLATFORM_API_ID_NV_INCREMENT:
         status = (psa_status_t)pfn(&msg);
         psa_reply(msg.handle, status);
         break;
@@ -154,12 +331,7 @@
         psa_reply(msg.handle, PSA_SUCCESS);
         break;
     default:
-        /* FIXME: Should be replaced by a call to psa_panic() when it
-         * becomes available.
-         */
-        while (1) {
-            ;
-        }
+        psa_panic();
     }
 }
 
@@ -167,6 +339,16 @@
 
 enum tfm_platform_err_t platform_sp_init(void)
 {
+    /* Initialise the non-volatile counters */
+    enum tfm_plat_err_t err;
+    err = tfm_plat_init_nv_counter();
+    if (err != TFM_PLAT_ERR_SUCCESS) {
+#ifdef TFM_PSA_API
+        psa_panic();
+#else
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+#endif
+    }
 #ifdef TFM_PSA_API
     psa_signal_t signals = 0;
 
@@ -178,13 +360,11 @@
         } else if (signals & TFM_SP_PLATFORM_IOCTL_SIGNAL) {
             platform_signal_handle(TFM_SP_PLATFORM_IOCTL_SIGNAL,
                                    platform_sp_ioctl_ipc);
+       } else if (signals & TFM_SP_PLATFORM_NV_COUNTER_SIGNAL) {
+            platform_signal_handle(TFM_SP_PLATFORM_NV_COUNTER_SIGNAL,
+                                   platform_sp_nv_counter_ipc);
         } else {
-            /* FIXME: Should be replaced by a call to psa_panic() when it
-             * becomes available.
-             */
-            while (1) {
-               ;
-            }
+            psa_panic();
         }
     }
 
diff --git a/secure_fw/services/platform/psa_manifest/tfm_platform.h b/secure_fw/services/platform/psa_manifest/tfm_platform.h
index a3ea0c6..77fe4ce 100644
--- a/secure_fw/services/platform/psa_manifest/tfm_platform.h
+++ b/secure_fw/services/platform/psa_manifest/tfm_platform.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -16,6 +16,7 @@
 
 #define TFM_SP_PLATFORM_SYSTEM_RESET_SIGNAL                     (1U << (0 + 4))
 #define TFM_SP_PLATFORM_IOCTL_SIGNAL                            (1U << (1 + 4))
+#define TFM_SP_PLATFORM_NV_COUNTER_SIGNAL                       (1U << (2 + 4))
 
 #ifdef __cplusplus
 }
diff --git a/secure_fw/services/platform/tfm_platform.yaml b/secure_fw/services/platform/tfm_platform.yaml
index 726ee16..11fd43d 100644
--- a/secure_fw/services/platform/tfm_platform.yaml
+++ b/secure_fw/services/platform/tfm_platform.yaml
@@ -28,6 +28,14 @@
       "non_secure_clients": true,
       "minor_version": 1,
       "minor_policy": "STRICT"
+     },
+     {
+       "name": "TFM_SP_PLATFORM_NV_COUNTER",
+       "signal": "PLATFORM_SP_NV_COUNTER_SIG",
+       "sid": "0x00000042",
+       "non_secure_clients": false,
+       "version": 1,
+       "version_policy": "STRICT"
      }
   ],
   "secure_functions": [
@@ -46,6 +54,20 @@
       "non_secure_clients": true,
       "version": 1,
       "version_policy": "STRICT"
-     }
+     },
+     {
+       "name": "TFM_SP_PLATFORM_NV_COUNTER_READ",
+       "signal": "PLATFORM_SP_NV_COUNTER_READ",
+       "non_secure_clients": false,
+       "minor_version": 1,
+       "minor_policy": "STRICT"
+      },
+      {
+        "name": "TFM_SP_PLATFORM_NV_COUNTER_INCREMENT",
+        "signal": "PLATFORM_SP_NV_COUNTER_INCREMENT",
+        "non_secure_clients": false,
+        "minor_version": 1,
+        "minor_policy": "STRICT"
+       }
   ]
 }
diff --git a/secure_fw/services/platform/tfm_platform_secure_api.c b/secure_fw/services/platform/tfm_platform_secure_api.c
index 19739fb..5206c5d 100644
--- a/secure_fw/services/platform/tfm_platform_secure_api.c
+++ b/secure_fw/services/platform/tfm_platform_secure_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -90,3 +90,80 @@
 #endif /* TFM_PSA_API */
 }
 
+__attribute__((section("SFN")))
+enum tfm_platform_err_t
+tfm_platform_nv_counter_increment(uint32_t counter_id)
+{
+#ifdef TFM_PSA_API
+    psa_status_t status = PSA_ERROR_CONNECTION_REFUSED;
+    psa_handle_t handle = PSA_NULL_HANDLE;
+#endif
+    struct psa_invec in_vec[1];
+
+    in_vec[0].base = &counter_id;
+    in_vec[0].len = sizeof(counter_id);
+
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_SP_PLATFORM_NV_COUNTER_SID,
+                         TFM_SP_PLATFORM_NV_COUNTER_VERSION);
+    if (handle <= 0) {
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+
+    status = psa_call(handle, TFM_PLATFORM_API_ID_NV_INCREMENT,
+                      in_vec, 1, (psa_outvec *)NULL, 0);
+
+    psa_close(handle);
+
+    if (status < PSA_SUCCESS) {
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    } else {
+        return (enum tfm_platform_err_t) status;
+    }
+#else /* TFM_PSA_API */
+    return
+        (enum tfm_platform_err_t) tfm_platform_sp_nv_counter_increment_veneer(
+                                              in_vec, 1, (psa_outvec *)NULL, 0);
+#endif /* TFM_PSA_API */
+}
+
+__attribute__((section("SFN")))
+enum tfm_platform_err_t
+tfm_platform_nv_counter_read(uint32_t counter_id,
+                             uint32_t size, uint8_t *val)
+{
+#ifdef TFM_PSA_API
+    psa_status_t status = PSA_ERROR_CONNECTION_REFUSED;
+    psa_handle_t handle = PSA_NULL_HANDLE;
+#endif
+    struct psa_invec in_vec[1];
+    struct psa_outvec out_vec[1];
+
+    in_vec[0].base = &counter_id;
+    in_vec[0].len = sizeof(counter_id);
+
+    out_vec[0].base = val;
+    out_vec[0].len = size;
+
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_SP_PLATFORM_NV_COUNTER_SID,
+                         TFM_SP_PLATFORM_NV_COUNTER_VERSION);
+    if (handle <= 0) {
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    }
+
+    status = psa_call(handle, TFM_PLATFORM_API_ID_NV_READ,
+                      in_vec, 1, out_vec, 1);
+
+    psa_close(handle);
+
+    if (status < PSA_SUCCESS) {
+        return TFM_PLATFORM_ERR_SYSTEM_ERROR;
+    } else {
+        return (enum tfm_platform_err_t) status;
+    }
+#else /* TFM_PSA_API */
+    return (enum tfm_platform_err_t) tfm_platform_sp_nv_counter_read_veneer(
+                                                        in_vec, 1, out_vec, 1);
+#endif /* TFM_PSA_API */
+}
diff --git a/secure_fw/services/secure_storage/nv_counters/sst_nv_counters.c b/secure_fw/services/secure_storage/nv_counters/sst_nv_counters.c
index 6d49efa..276a40f 100644
--- a/secure_fw/services/secure_storage/nv_counters/sst_nv_counters.c
+++ b/secure_fw/services/secure_storage/nv_counters/sst_nv_counters.c
@@ -6,27 +6,16 @@
  */
 
 #include "sst_nv_counters.h"
-
-psa_status_t sst_init_nv_counter(void)
-{
-    enum tfm_plat_err_t err;
-
-    err = tfm_plat_init_nv_counter();
-    if (err != TFM_PLAT_ERR_SUCCESS) {
-        return PSA_ERROR_GENERIC_ERROR;
-    }
-
-    return PSA_SUCCESS;
-}
+#include "tfm_platform_api.h"
 
 psa_status_t sst_read_nv_counter(enum tfm_nv_counter_t counter_id,
                                  uint32_t *val)
 {
-    enum tfm_plat_err_t err;
+    enum tfm_platform_err_t err;
 
-    err = tfm_plat_read_nv_counter(counter_id, SST_NV_COUNTER_SIZE,
-                                   (uint8_t *)val);
-    if (err != TFM_PLAT_ERR_SUCCESS) {
+    err = tfm_platform_nv_counter_read(counter_id, SST_NV_COUNTER_SIZE,
+                                       (uint8_t *)val);
+    if (err != TFM_PLATFORM_ERR_SUCCESS) {
         return PSA_ERROR_GENERIC_ERROR;
     }
 
@@ -35,7 +24,7 @@
 
 psa_status_t sst_increment_nv_counter(enum tfm_nv_counter_t counter_id)
 {
-    enum tfm_plat_err_t err;
+    enum tfm_platform_err_t err;
 
     /* NOTE: tfm_plat_increment_nv_counter returns TFM_PLAT_ERR_MAX_VALUE when
      *       the counter reaches its maximum value. The current SST
@@ -43,8 +32,8 @@
      *       moment onwards, the rollback protection can not be achieved based
      *       on the NV counters.
      */
-    err = tfm_plat_increment_nv_counter(counter_id);
-    if (err != TFM_PLAT_ERR_SUCCESS) {
+    err = tfm_platform_nv_counter_increment(counter_id);
+    if (err != TFM_PLATFORM_ERR_SUCCESS) {
         return PSA_ERROR_GENERIC_ERROR;
     }
 
diff --git a/secure_fw/services/secure_storage/nv_counters/sst_nv_counters.h b/secure_fw/services/secure_storage/nv_counters/sst_nv_counters.h
index 3448413..324b471 100644
--- a/secure_fw/services/secure_storage/nv_counters/sst_nv_counters.h
+++ b/secure_fw/services/secure_storage/nv_counters/sst_nv_counters.h
@@ -31,14 +31,6 @@
 #endif
 
 /**
- * \brief Initializes all non-volatile (NV) counters.
- *
- * \return  PSA_SUCCESS if the initialization succeeds, otherwise
- *          PSA_ERROR_GENERIC_ERROR
- */
-psa_status_t sst_init_nv_counter(void);
-
-/**
  * \brief Reads the given non-volatile (NV) counter.
  *
  * \param[in]  counter_id  NV counter ID.
diff --git a/secure_fw/services/secure_storage/sst_object_table.c b/secure_fw/services/secure_storage/sst_object_table.c
index 96a8906..2e37a08 100644
--- a/secure_fw/services/secure_storage/sst_object_table.c
+++ b/secure_fw/services/secure_storage/sst_object_table.c
@@ -810,16 +810,6 @@
 {
     struct sst_obj_table_t *p_table = &sst_obj_table_ctx.obj_table;
 
-#ifdef SST_ROLLBACK_PROTECTION
-    psa_status_t err;
-
-    /* Initialize SST NV counters */
-    err = sst_init_nv_counter();
-    if (err != PSA_SUCCESS) {
-        return err;
-    }
-#endif
-
     /* Initialize object structure */
     (void)tfm_memset(&sst_obj_table_ctx, SST_DEFAULT_EMPTY_BUFF_VAL,
                      sizeof(struct sst_obj_table_ctx_t));
@@ -861,13 +851,6 @@
     }
 
 #ifdef SST_ROLLBACK_PROTECTION
-    /* Initialize SST NV counters */
-    err = sst_init_nv_counter();
-    if (err != PSA_SUCCESS) {
-        (void)sst_crypto_destroykey();
-        return err;
-    }
-
     /* Authenticate table */
     err = sst_object_table_nvc_authenticate(&init_ctx);
     if (err != PSA_SUCCESS) {
diff --git a/secure_fw/services/secure_storage/tfm_secure_storage.yaml b/secure_fw/services/secure_storage/tfm_secure_storage.yaml
index 643f21e..d808686 100644
--- a/secure_fw/services/secure_storage/tfm_secure_storage.yaml
+++ b/secure_fw/services/secure_storage/tfm_secure_storage.yaml
@@ -90,6 +90,7 @@
     "TFM_ITS_SET",
     "TFM_ITS_GET",
     "TFM_ITS_GET_INFO",
-    "TFM_ITS_REMOVE"
+    "TFM_ITS_REMOVE",
+    "TFM_SP_PLATFORM_NV_COUNTER"
   ]
 }
diff --git a/secure_fw/services/tfm_service_list.inc b/secure_fw/services/tfm_service_list.inc
index 35ad61f..0cda109 100644
--- a/secure_fw/services/tfm_service_list.inc
+++ b/secure_fw/services/tfm_service_list.inc
@@ -150,6 +150,15 @@
         .version = 1,
         .version_policy = TFM_VERSION_POLICY_STRICT
     },
+    {
+        .name = "TFM_SP_PLATFORM_NV_COUNTER",
+        .partition_id = TFM_SP_PLATFORM,
+        .signal = TFM_SP_PLATFORM_NV_COUNTER_SIGNAL,
+        .sid = 0x00000042,
+        .non_secure_client = false,
+        .version = 1,
+        .version_policy = TFM_VERSION_POLICY_STRICT
+    },
 #endif /* TFM_PARTITION_PLATFORM */
 
 #ifdef TFM_PARTITION_INITIAL_ATTESTATION
@@ -621,6 +630,13 @@
         .msg_queue = {0},
         .list = {0},
     },
+    {
+        .service_db = NULL,
+        .partition = NULL,
+        .handle_list = {0},
+        .msg_queue = {0},
+        .list = {0},
+    },
 #endif /* TFM_PARTITION_PLATFORM */
 
 #ifdef TFM_PARTITION_INITIAL_ATTESTATION
diff --git a/secure_fw/spm/tfm_spm_db.inc b/secure_fw/spm/tfm_spm_db.inc
index d4c85d5..e9b4012 100644
--- a/secure_fw/spm/tfm_spm_db.inc
+++ b/secure_fw/spm/tfm_spm_db.inc
@@ -565,6 +565,7 @@
     TFM_ITS_GET_SID,
     TFM_ITS_GET_INFO_SID,
     TFM_ITS_REMOVE_SID,
+    TFM_SP_PLATFORM_NV_COUNTER_SID,
 };
 #endif /* TFM_PARTITION_SECURE_STORAGE */
 
@@ -685,7 +686,7 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = tfm_sst_req_mngr_init,
-        .dependencies_num     = 5,
+        .dependencies_num     = 6,
         .p_dependencies       = dependencies_TFM_SP_STORAGE,
     },
 #endif /* TFM_PARTITION_SECURE_STORAGE */
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
index 5a2b4d1..113fb4a 100644
--- a/test/suites/sst/secure/nv_counters/test_sst_nv_counters.c
+++ b/test/suites/sst/secure/nv_counters/test_sst_nv_counters.c
@@ -18,7 +18,11 @@
 #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 test_nv_counters[TOTAL_SST_NV_COUNTERS] = {
+                                                [0] = INIT_NV_COUNTERS_VALUE,
+                                                [1] = INIT_NV_COUNTERS_VALUE,
+                                                [2] = INIT_NV_COUNTERS_VALUE
+                };
 
 static uint32_t get_nv_counter_position(enum tfm_nv_counter_t counter_id)
 {
@@ -34,21 +38,6 @@
     }
 }
 
-/* Implementation of SST NV counter interfaces defined by sst_nv_counters.h */
-psa_status_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_SUCCESS;
-}
-
 psa_status_t sst_read_nv_counter(enum tfm_nv_counter_t counter_id,
                                  uint32_t *val)
 {