Extend storage components for PSA PS
The secure-storage access protocol and storage backend interface are
extended to support additional API operations for PSA Protected
Storage. A new psa ps storage front end is added that allows
clients to use the standard ps API to access secure storage.
Component test cases are extended to cover the extra API
operations. Tests are now applied to different frontend/
backend combinations, including an intermediate proxy.
Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: Ic29f74274baceb73fb7b88a636f319c0980de6a7
diff --git a/components/service/common/psa/protected_storage.h b/components/service/common/psa/protected_storage.h
new file mode 100644
index 0000000..ff827b1
--- /dev/null
+++ b/components/service/common/psa/protected_storage.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* This file describes the PSA Protected Storage API */
+
+#ifndef PROTECTED_STORAGE_H
+#define PROTECTED_STORAGE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "psa/error.h"
+#include "psa/storage_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PSA_PS_API_VERSION version
+ *
+ * Major and minor PSA_PS_API_VERSION numbers
+ */
+#define PSA_PS_API_VERSION_MAJOR 1
+#define PSA_PS_API_VERSION_MINOR 0
+
+// This version of the header file is associated with 1.0 final release
+
+/**
+ * \brief Create a new, or modify an existing, uid/value pair
+ *
+ * Stores data in the protected storage.
+ *
+ * \param[in] uid The identifier for the data
+ * \param[in] data_length The size in bytes of the data in `p_data`
+ * \param[in] p_data A buffer containing the data
+ * \param[in] create_flags The flags that the data will be stored with
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS The operation completed successfully
+ * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the
+ * provided `uid` value was already
+ * created with
+ * PSA_STORAGE_FLAG_WRITE_ONCE
+ * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one
+ * of the provided pointers(`p_data`)
+ * is invalid, for example is `NULL` or
+ * references memory the caller cannot
+ * access
+ * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or
+ * more of the flags provided in
+ * `create_flags` is not supported or is
+ * not valid
+ * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there
+ * was insufficient space on the
+ * storage medium
+ * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the
+ * physical storage has failed (Fatal
+ * error)
+ * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an
+ * unspecified internal failure
+ */
+psa_status_t psa_ps_set(psa_storage_uid_t uid,
+ size_t data_length,
+ const void *p_data,
+ psa_storage_create_flags_t create_flags);
+
+/**
+ * \brief Retrieve data associated with a provided uid
+ *
+ * Retrieves up to `data_size` bytes of the data associated with `uid`, starting
+ * at `data_offset` bytes from the beginning of the data. Upon successful
+ * completion, the data will be placed in the `p_data` buffer, which must be at
+ * least `data_size` bytes in size. The length of the data returned will be in
+ * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will
+ * be set to zero.
+ *
+ * \param[in] uid The uid value
+ * \param[in] data_offset The starting offset of the data requested
+ * \param[in] data_size The amount of data requested
+ * \param[out] p_data On success, the buffer where the data will
+ * be placed
+ * \param[out] p_data_length On success, this will contain size of the data
+ * placed in `p_data`
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS The operation completed successfully
+ * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the
+ * provided arguments (`p_data`,
+ * `p_data_length`) is invalid, for example
+ * is `NULL` or references memory the
+ * caller cannot access. In addition, this
+ * can also happen if `data_offset` is
+ * larger than the size of the data
+ * associated with `uid`
+ * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the
+ * provided `uid` value was not found in
+ * the storage
+ * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the
+ * physical storage has failed (Fatal
+ * error)
+ * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an
+ * unspecified internal failure
+ * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data
+ * associated with the UID was corrupt
+ * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data
+ * associated with the UID failed
+ * authentication
+ */
+psa_status_t psa_ps_get(psa_storage_uid_t uid,
+ size_t data_offset,
+ size_t data_size,
+ void *p_data,
+ size_t *p_data_length);
+
+/**
+ * \brief Retrieve the metadata about the provided uid
+ *
+ * Retrieves the metadata stored for a given `uid`
+ *
+ * \param[in] uid The `uid` value
+ * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will
+ * be populated with the metadata
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS The operation completed successfully
+ * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the
+ * provided pointers(`p_info`)
+ * is invalid, for example is `NULL` or
+ * references memory the caller cannot
+ * access
+ * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided
+ * uid value was not found in the storage
+ * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical
+ * storage has failed (Fatal error)
+ * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an
+ * unspecified internal failure
+ * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the data
+ * associated with the UID was corrupt
+ */
+psa_status_t psa_ps_get_info(psa_storage_uid_t uid,
+ struct psa_storage_info_t *p_info);
+
+/**
+ * \brief Remove the provided uid and its associated data from the storage
+ *
+ * Removes previously stored data and any associated metadata,
+ * including rollback protection data.
+ *
+ * \param[in] uid The `uid` value
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS The operation completed successfully
+ * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more
+ * of the given arguments were invalid (null
+ * pointer, wrong flags and so on)
+ * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided
+ * uid value was not found in the storage
+ * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided
+ * uid value was created with
+ * PSA_STORAGE_FLAG_WRITE_ONCE
+ * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical
+ * storage has failed (Fatal error)
+ * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an
+ * unspecified internal failure
+ */
+psa_status_t psa_ps_remove(psa_storage_uid_t uid);
+
+/**
+ * \brief Reserves storage for the specified uid
+ *
+ * Upon success, the capacity of the storage will be capacity, and the size
+ * will be 0. It is only necessary to call this function for assets that will
+ * be written with the psa_ps_set_extended function. If only the psa_ps_set
+ * function is needed, calls to this function are redundant.
+ *
+ * \param[in] uid The `uid` value
+ * \param[in] capacity The capacity to be allocated in bytes
+ * \param[in] create_flags Flags indicating properties of storage
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS The operation completed successfully
+ * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the
+ * physical storage has failed
+ * (Fatal error)
+ * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because the
+ * capacity is bigger than the current
+ * available space
+ * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because the
+ * function is not implemented or one
+ * or more create_flags are not
+ * supported.
+ * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because uid was
+ * 0 or create_flags specified flags
+ * that are not defined in the API.
+ * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an
+ * unspecified error
+ * \retval PSA_ERROR_ALREADY_EXISTS Storage for the specified uid
+ * already exists
+ */
+psa_status_t psa_ps_create(psa_storage_uid_t uid,
+ size_t capacity,
+ psa_storage_create_flags_t create_flags);
+
+/**
+ * \brief Sets partial data into an asset
+ *
+ * Before calling this function, the storage must have been reserved with a call
+ * to psa_ps_create. It can also be used to overwrite data in an asset that was
+ * created with a call to psa_ps_set. Calling this function with data_length = 0
+ * is permitted, which will make no change to the stored data.This function can
+ * overwrite existing data and/or extend it up to the capacity for the uid
+ * specified in psa_ps_create, but cannot create gaps.
+ *
+ * That is, it has preconditions:
+ * - data_offset <= size
+ * - data_offset + data_length <= capacity
+ * and postconditions:
+ * - size = max(size, data_offset + data_length)
+ * - capacity unchanged.
+ *
+ * \param[in] uid The `uid` value
+ * \param[in] data_offset Offset within the asset to start the write
+ * \param[in] data_length The size in bytes of the data in p_data to write
+ * \param[in] p_data Pointer to a buffer which contains the data to write
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS The asset exists, the input parameters
+ * are correct and the data is correctly
+ * written in the physical storage.
+ * \retval PSA_ERROR_STORAGE_FAILURE The data was not written correctly in
+ * the physical storage
+ * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more
+ * of the preconditions listed above
+ * regarding data_offset, size, or
+ * data_length was violated.
+ * \retval PSA_ERROR_DOES_NOT_EXIST The specified uid was not found
+ * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not
+ * support this function
+ * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an
+ * unspecified error
+ * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the
+ * existing data has been corrupted.
+ * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the
+ * existing data failed authentication
+ * (MAC check failed).
+ * \retval PSA_ERROR_NOT_PERMITTED The operation failed because it was
+ * attempted on an asset which was written
+ * with the flag
+ * PSA_STORAGE_FLAG_WRITE_ONCE
+ */
+psa_status_t psa_ps_set_extended(psa_storage_uid_t uid,
+ size_t data_offset,
+ size_t data_length,
+ const void *p_data);
+
+/**
+ * \brief Lists optional features.
+ *
+ * \return A bitmask with flags set for all of
+ * the optional features supported by the
+ * implementation.Currently defined flags
+ * are limited to
+ * PSA_STORAGE_SUPPORT_SET_EXTENDED
+ */
+uint32_t psa_ps_get_support(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PROTECTED_STORAGE_H */