Implement RPMB frontend

The RPMB frontend provides a high level read/write interface for
accessing the RPMB device and it does calls to the RPMB backend. This
component contains the main RPMB logic, including:

* Writing authentication key
* Handling the write counter
* Building and verifying RPMB data frames

Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I2bd2589f4f99370381e1594beb4e04921c3fba36
diff --git a/components/service/rpmb/frontend/rpmb_frontend.h b/components/service/rpmb/frontend/rpmb_frontend.h
new file mode 100644
index 0000000..e4eb8ce
--- /dev/null
+++ b/components/service/rpmb/frontend/rpmb_frontend.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPMB_FRONTEND_H_
+#define RPMB_FRONTEND_H_
+
+#include "components/service/rpmb/backend/rpmb_backend.h"
+#include "components/rpc/common/caller/rpc_caller_session.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief RPMB platform interface
+ *
+ * It the interface for the necessary platform dependent functions:
+ * * deriving RPMB key from hardware unique key
+ * * get random nonce value
+ * * calculate RPMB MAC value
+ */
+struct rpmb_platform_interface {
+	/**
+	 * \brief Device key from hardware unique key for creating the RPMB authentication key
+	 *
+	 * \param context[in]		Platform context
+	 * \param data[in]		Key derivation data (i.e. salt)
+	 * \param data_length[in]	Key derivation data length
+	 * \param key[out]		Derived authentication key
+	 * \param key_length[in]	Required authentication key length
+	 * \return psa_status_t
+	 */
+	psa_status_t (*derive_key)(void *context, const uint8_t *data, size_t data_length,
+				   uint8_t *key, size_t key_length);
+
+	/**
+	 * \brief Get random nonce value
+	 *
+	 * \param context[in]		Platform context
+	 * \param nonce[out]		Generated nonce value
+	 * \param nonce_length[in]	Nonce length
+	 * \return psa_status_t
+	 */
+	psa_status_t (*get_nonce)(void *context, uint8_t *nonce, size_t nonce_length);
+
+	/**
+	 * \brief Calculate MAC field value
+	 *
+	 * \param context[in]		Platform context
+	 * \param key[in]		Authentication key
+	 * \param key_length[in]	Authentication key length
+	 * \param frames[in]		Data frames
+	 * \param frame_count[in]	Data frame count
+	 * \param mac[out]		Calculated MAC value
+	 * \param mac_length[in]	MAC value length
+	 * \return psa_status_t
+	 */
+	psa_status_t (*calculate_mac)(void *context, const uint8_t *key, size_t key_length,
+				      const struct rpmb_data_frame *frames, size_t frame_count,
+				      uint8_t *mac, size_t mac_length);
+};
+
+/**
+ * \brief RPMB platform
+ *
+ * Generic object for storing the RPMB platform interface and the implementation specific context.
+ */
+struct rpmb_platform {
+	void *context;
+	struct rpmb_platform_interface *interface;
+};
+
+/**
+ * \brief RPMB frontend
+ *
+ * The RPMB frontend provides a high level read/write interface for accessing
+ * the RPMB device and it does calls to the RPMB backend. This component
+ * contains the main RPMB logic, including:
+ * * Writing authentication key
+ * * Handling the write counter
+ * * Building and verifying RPMB data frames
+ */
+struct rpmb_frontend {
+	struct rpmb_platform *platform;
+	struct rpmb_backend *backend;
+	uint32_t dev_id;
+	bool initialized;
+	size_t block_count;
+	uint8_t key[RPMB_KEY_MAC_SIZE];
+	uint32_t write_counter;
+};
+
+/**
+ * \brief Create RPMB frontend
+ *
+ * This function only initializes the internal objects. It doesn't require the backend to be able
+ * to access the RPMB hardware.
+ *
+ * \param context[in]	RPMB frontend context
+ * \param platform[in]	RPMB platform
+ * \param backend[in]	RPMB backend
+ * \param dev_id[in]	Device ID
+ * \return psa_status_t
+ */
+psa_status_t rpmb_frontend_create(struct rpmb_frontend *context, struct rpmb_platform *platform,
+				  struct rpmb_backend *backend, uint32_t dev_id);
+
+/**
+ * \brief Init RPMB frontend
+ *
+ * This function requires access to the RPMB hardware via the backend. It reads derives the
+ * authentication key, reads the write counter and possibly writes the authentication key.
+ *
+ * \param context[in]	RPMB frontend context
+ * \return psa_status_t
+ */
+psa_status_t rpmb_frontend_init(struct rpmb_frontend *context);
+
+/**
+ * \brief Destroy RPMB frontend
+ *
+ * \param context[in]	RPMB frontend context
+ */
+void rpmb_frontend_destroy(struct rpmb_frontend *context);
+
+/**
+ * \brief Query RPMB block size
+ *
+ * \param context[in]		RPMB frontend context
+ * \param block_size[out]	Block size in bytes
+ * \return psa_status_t
+ */
+psa_status_t rpmb_frontend_block_size(struct rpmb_frontend *context, size_t *block_size);
+
+/**
+ * \brief Query RPMB block count
+ *
+ * \param context[in]		RPMB frontend context
+ * \param block_count[out]	Block count
+ * \return psa_status_t
+ */
+psa_status_t rpmb_frontend_block_count(struct rpmb_frontend *context, size_t *block_count);
+
+/**
+ * \brief Write complete blocks to RPMB
+ *
+ * \param context[in]		RPMB frontend context
+ * \param block_index[in]	Block index
+ * \param data[in]		Data, its size must be [block count] * [block size]
+ * \param block_count[in]	Block count
+ * \return psa_status_t
+ */
+psa_status_t rpmb_frontend_write(struct rpmb_frontend *context, uint16_t block_index,
+				 const uint8_t *data, size_t block_count);
+
+/**
+ * \brief Read complete blocks from RPMB
+ *
+ * \param context[in]		RPMB frontend context
+ * \param block_index[in]	Block index
+ * \param data[out]		Data, its size must be [block count] * [block size]
+ * \param block_count[in]	Block count
+ * \return psa_status_t
+ */
+psa_status_t rpmb_frontend_read(struct rpmb_frontend *context, uint16_t block_index,
+				uint8_t *data, size_t block_count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RPMB_CLIENT_H_ */