Merge changes from topic "rss/mboot-attest" into integration

* changes:
  docs(maintainers): add PSA, MHU, RSS comms code owners
  feat(plat/arm/fvp): enable RSS backend based measured boot
  feat(lib/psa): mock PSA APIs
  feat(drivers/measured_boot): add RSS backend
  feat(drivers/arm/rss): add RSS communication driver
  feat(lib/psa): add initial attestation API
  feat(lib/psa): add measured boot API
  feat(drivers/arm/mhu): add MHU driver
This commit is contained in:
Sandrine Bailleux 2022-05-13 16:15:35 +02:00 committed by TrustedFirmware Code Review
commit 6aed554954
25 changed files with 2186 additions and 10 deletions

View File

@ -1011,6 +1011,7 @@ $(eval $(call assert_booleans,\
NS_TIMER_SWITCH \
OVERRIDE_LIBC \
PL011_GENERIC_UART \
PLAT_RSS_NOT_SUPPORTED \
PROGRAMMABLE_RESET_ADDRESS \
PSCI_EXTENDED_STATE_ID \
RESET_TO_BL31 \
@ -1146,6 +1147,7 @@ $(eval $(call add_defines,\
NS_TIMER_SWITCH \
PL011_GENERIC_UART \
PLAT_${PLAT} \
PLAT_RSS_NOT_SUPPORTED \
PROGRAMMABLE_RESET_ADDRESS \
PSCI_EXTENDED_STATE_ID \
RAS_EXTENSION \

View File

@ -293,6 +293,20 @@ GIC driver
:|G|: `odeprez`_
:|F|: drivers/arm/gic/
Message Handling Unit (MHU) driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:|M|: David Vincze <david.vincze@arm.com>
:|G|: `davidvincze`_
:|F|: include/drivers/arm/mhu.h
:|F|: drivers/arm/mhu
Runtime Security Subsystem (RSS) comms driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:|M|: David Vincze <david.vincze@arm.com>
:|G|: `davidvincze`_
:|F|: include/drivers/arm/rss_comms.h
:|F|: drivers/arm/rss
Libfdt wrappers
^^^^^^^^^^^^^^^
:|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
@ -331,6 +345,13 @@ PSA Firmware Update
:|F|: drivers/fwu
:|F|: include/drivers/fwu
Platform Security Architecture (PSA) APIs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:|M|: Sandrine Bailleux <sandrine.bailleux@arm.com>
:|G|: `sandrine-bailleux-arm`_
:|F|: include/lib/psa
:|F|: lib/psa
System Control and Management Interface (SCMI) Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:|M|: Etienne Carriere <etienne.carriere@st.com>
@ -821,6 +842,7 @@ Conventional Changelog Extensions
.. _b49020: https://github.com/b49020
.. _carlocaione: https://github.com/carlocaione
.. _danh-arm: https://github.com/danh-arm
.. _davidvincze: https://github.com/davidvincze
.. _etienne-lms: https://github.com/etienne-lms
.. _glneo: https://github.com/glneo
.. _grandpaul: https://github.com/grandpaul

View File

@ -994,6 +994,11 @@ Common build options
if FEAT_TRF is implemented. This flag can take the values 0 to 2, to align
with the ``FEATURE_DETECTION`` mechanism. This flag is disabled by default.
- ``PLAT_RSS_NOT_SUPPORTED``: Boolean option to enable the usage of the PSA
APIs on platforms that doesn't support RSS (providing Arm CCA HES
functionalities). When enabled (``1``), a mocked version of the APIs are used.
The default value is 0.
GICv3 driver options
--------------------

379
drivers/arm/mhu/mhu_v2_x.c Normal file
View File

@ -0,0 +1,379 @@
/*
* Copyright (c) 2020-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "mhu_v2_x.h"
#define MHU_V2_X_MAX_CHANNELS 124
#define MHU_V2_1_MAX_CHCOMB_INT 4
#define ENABLE 0x1
#define DISABLE 0x0
#define CLEAR_INTR 0x1
#define CH_PER_CH_COMB 0x20
#define SEND_FRAME(p_mhu) ((struct mhu_v2_x_send_frame_t *)p_mhu)
#define RECV_FRAME(p_mhu) ((struct mhu_v2_x_recv_frame_t *)p_mhu)
#define MHU_MAJOR_REV_V2 0x1u
#define MHU_MINOR_REV_2_0 0x0u
#define MHU_MINOR_REV_2_1 0x1u
struct mhu_v2_x_send_ch_window_t {
/* Offset: 0x00 (R/ ) Channel Status */
volatile uint32_t ch_st;
/* Offset: 0x04 (R/ ) Reserved */
volatile uint32_t reserved_0;
/* Offset: 0x08 (R/ ) Reserved */
volatile uint32_t reserved_1;
/* Offset: 0x0C ( /W) Channel Set */
volatile uint32_t ch_set;
/* Offset: 0x10 (R/ ) Channel Interrupt Status (Reserved in 2.0) */
volatile uint32_t ch_int_st;
/* Offset: 0x14 ( /W) Channel Interrupt Clear (Reserved in 2.0) */
volatile uint32_t ch_int_clr;
/* Offset: 0x18 (R/W) Channel Interrupt Enable (Reserved in 2.0) */
volatile uint32_t ch_int_en;
/* Offset: 0x1C (R/ ) Reserved */
volatile uint32_t reserved_2;
};
struct mhu_v2_x_send_frame_t {
/* Offset: 0x000 ( / ) Sender Channel Window 0 -123 */
struct mhu_v2_x_send_ch_window_t send_ch_window[MHU_V2_X_MAX_CHANNELS];
/* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
volatile uint32_t mhu_cfg;
/* Offset: 0xF84 (R/W) Response Configuration */
volatile uint32_t resp_cfg;
/* Offset: 0xF88 (R/W) Access Request */
volatile uint32_t access_request;
/* Offset: 0xF8C (R/ ) Access Ready */
volatile uint32_t access_ready;
/* Offset: 0xF90 (R/ ) Interrupt Status */
volatile uint32_t int_st;
/* Offset: 0xF94 ( /W) Interrupt Clear */
volatile uint32_t int_clr;
/* Offset: 0xF98 (R/W) Interrupt Enable */
volatile uint32_t int_en;
/* Offset: 0xF9C (R/ ) Reserved */
volatile uint32_t reserved_0;
/* Offset: 0xFA0 (R/W) Channel Combined IRQ Stat (Reserved in 2.0) */
volatile uint32_t ch_comb_int_st[MHU_V2_1_MAX_CHCOMB_INT];
/* Offset: 0xFC4 (R/ ) Reserved */
volatile uint32_t reserved_1[6];
/* Offset: 0xFC8 (R/ ) Implementer Identification Register */
volatile uint32_t iidr;
/* Offset: 0xFCC (R/ ) Architecture Identification Register */
volatile uint32_t aidr;
/* Offset: 0xFD0 (R/ ) */
volatile uint32_t pid_1[4];
/* Offset: 0xFE0 (R/ ) */
volatile uint32_t pid_0[4];
/* Offset: 0xFF0 (R/ ) */
volatile uint32_t cid[4];
};
struct mhu_v2_x_rec_ch_window_t {
/* Offset: 0x00 (R/ ) Channel Status */
volatile uint32_t ch_st;
/* Offset: 0x04 (R/ ) Channel Status Masked */
volatile uint32_t ch_st_msk;
/* Offset: 0x08 ( /W) Channel Clear */
volatile uint32_t ch_clr;
/* Offset: 0x0C (R/ ) Reserved */
volatile uint32_t reserved_0;
/* Offset: 0x10 (R/ ) Channel Mask Status */
volatile uint32_t ch_msk_st;
/* Offset: 0x14 ( /W) Channel Mask Set */
volatile uint32_t ch_msk_set;
/* Offset: 0x18 ( /W) Channel Mask Clear */
volatile uint32_t ch_msk_clr;
/* Offset: 0x1C (R/ ) Reserved */
volatile uint32_t reserved_1;
};
struct mhu_v2_x_recv_frame_t {
/* Offset: 0x000 ( / ) Receiver Channel Window 0 -123 */
struct mhu_v2_x_rec_ch_window_t rec_ch_window[MHU_V2_X_MAX_CHANNELS];
/* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
volatile uint32_t mhu_cfg;
/* Offset: 0xF84 (R/ ) Reserved */
volatile uint32_t reserved_0[3];
/* Offset: 0xF90 (R/ ) Interrupt Status (Reserved in 2.0) */
volatile uint32_t int_st;
/* Offset: 0xF94 (R/ ) Interrupt Clear (Reserved in 2.0) */
volatile uint32_t int_clr;
/* Offset: 0xF98 (R/W) Interrupt Enable (Reserved in 2.0) */
volatile uint32_t int_en;
/* Offset: 0xF9C (R/ ) Reserved */
volatile uint32_t reserved_1;
/* Offset: 0xFA0 (R/ ) Channel Combined IRQ Stat (Reserved in 2.0) */
volatile uint32_t ch_comb_int_st[MHU_V2_1_MAX_CHCOMB_INT];
/* Offset: 0xFB0 (R/ ) Reserved */
volatile uint32_t reserved_2[6];
/* Offset: 0xFC8 (R/ ) Implementer Identification Register */
volatile uint32_t iidr;
/* Offset: 0xFCC (R/ ) Architecture Identification Register */
volatile uint32_t aidr;
/* Offset: 0xFD0 (R/ ) */
volatile uint32_t pid_1[4];
/* Offset: 0xFE0 (R/ ) */
volatile uint32_t pid_0[4];
/* Offset: 0xFF0 (R/ ) */
volatile uint32_t cid[4];
};
union mhu_v2_x_frame {
struct mhu_v2_x_send_frame_t send_frame;
struct mhu_v2_x_recv_frame_t recv_frame;
};
enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
enum mhu_v2_x_supported_revisions rev)
{
uint32_t AIDR = 0;
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (dev->is_initialized) {
return MHU_V_2_X_ERR_ALREADY_INIT;
}
if (rev == MHU_REV_READ_FROM_HW) {
/* Read revision from HW */
if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
AIDR = p_mhu->recv_frame.aidr;
} else {
AIDR = p_mhu->send_frame.aidr;
}
/* Get bits 7:4 to read major revision */
if (((AIDR >> 4) & 0b1111) != MHU_MAJOR_REV_V2) {
/* Unsupported MHU version */
return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
} /* No need to save major version, driver only supports MHUv2 */
/* Get bits 3:0 to read minor revision */
dev->subversion = AIDR & 0b1111;
if (dev->subversion != MHU_MINOR_REV_2_0 &&
dev->subversion != MHU_MINOR_REV_2_1) {
/* Unsupported subversion */
return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
}
} else {
/* Revisions were provided by caller */
if (rev == MHU_REV_2_0) {
dev->subversion = MHU_MINOR_REV_2_0;
} else if (rev == MHU_REV_2_1) {
dev->subversion = MHU_MINOR_REV_2_1;
} else {
/* Unsupported subversion */
return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
} /* No need to save major version, driver only supports MHUv2 */
}
dev->is_initialized = true;
return MHU_V_2_X_ERR_NONE;
}
uint32_t mhu_v2_x_get_num_channel_implemented(const struct mhu_v2_x_dev_t *dev)
{
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (!(dev->is_initialized)) {
return MHU_V_2_X_ERR_NOT_INIT;
}
if (dev->frame == MHU_V2_X_SENDER_FRAME) {
return (SEND_FRAME(p_mhu))->mhu_cfg;
} else {
assert(dev->frame == MHU_V2_X_RECEIVER_FRAME);
return (RECV_FRAME(p_mhu))->mhu_cfg;
}
}
enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
uint32_t channel, uint32_t val)
{
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (!(dev->is_initialized)) {
return MHU_V_2_X_ERR_NOT_INIT;
}
if (dev->frame == MHU_V2_X_SENDER_FRAME) {
(SEND_FRAME(p_mhu))->send_ch_window[channel].ch_set = val;
return MHU_V_2_X_ERR_NONE;
} else {
return MHU_V_2_X_ERR_INVALID_ARG;
}
}
enum mhu_v2_x_error_t mhu_v2_x_channel_poll(const struct mhu_v2_x_dev_t *dev,
uint32_t channel, uint32_t *value)
{
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (!(dev->is_initialized)) {
return MHU_V_2_X_ERR_NOT_INIT;
}
if (dev->frame == MHU_V2_X_SENDER_FRAME) {
*value = (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_st;
return MHU_V_2_X_ERR_NONE;
} else {
return MHU_V_2_X_ERR_INVALID_ARG;
}
}
enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
uint32_t channel)
{
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (!(dev->is_initialized)) {
return MHU_V_2_X_ERR_NOT_INIT;
}
if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
(RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_clr = UINT32_MAX;
return MHU_V_2_X_ERR_NONE;
} else {
return MHU_V_2_X_ERR_INVALID_ARG;
}
}
enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value)
{
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (!(dev->is_initialized)) {
return MHU_V_2_X_ERR_NOT_INIT;
}
if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
*value = (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_st;
return MHU_V_2_X_ERR_NONE;
} else {
return MHU_V_2_X_ERR_INVALID_ARG;
}
}
enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
{
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (!(dev->is_initialized)) {
return MHU_V_2_X_ERR_NOT_INIT;
}
if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
(RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_set = mask;
return MHU_V_2_X_ERR_NONE;
} else {
return MHU_V_2_X_ERR_INVALID_ARG;
}
}
enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
{
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (!(dev->is_initialized)) {
return MHU_V_2_X_ERR_NOT_INIT;
}
if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
(RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_clr = mask;
return MHU_V_2_X_ERR_NONE;
} else {
return MHU_V_2_X_ERR_INVALID_ARG;
}
}
enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
const struct mhu_v2_x_dev_t *dev)
{
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (!(dev->is_initialized)) {
return MHU_V_2_X_ERR_NOT_INIT;
}
if (dev->frame != MHU_V2_X_SENDER_FRAME) {
return MHU_V_2_X_ERR_INVALID_ARG;
}
(SEND_FRAME(p_mhu))->access_request = ENABLE;
while (!((SEND_FRAME(p_mhu))->access_ready)) {
/* Wait in a loop for access ready signal to be high */
;
}
return MHU_V_2_X_ERR_NONE;
}
enum mhu_v2_x_error_t mhu_v2_x_close_transfer(const struct mhu_v2_x_dev_t *dev)
{
union mhu_v2_x_frame *p_mhu;
assert(dev != NULL);
p_mhu = (union mhu_v2_x_frame *)dev->base;
if (!(dev->is_initialized)) {
return MHU_V_2_X_ERR_NOT_INIT;
}
if (dev->frame != MHU_V2_X_SENDER_FRAME) {
return MHU_V_2_X_ERR_INVALID_ARG;
}
(SEND_FRAME(p_mhu))->access_request = DISABLE;
return MHU_V_2_X_ERR_NONE;
}

210
drivers/arm/mhu/mhu_v2_x.h Normal file
View File

@ -0,0 +1,210 @@
/*
* Copyright (c) 2020-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MHU_V2_X_H
#define MHU_V2_X_H
#include <stdbool.h>
#include <stdint.h>
#define MHU_2_X_INTR_NR2R_OFF (0x0u)
#define MHU_2_X_INTR_R2NR_OFF (0x1u)
#define MHU_2_1_INTR_CHCOMB_OFF (0x2u)
#define MHU_2_X_INTR_NR2R_MASK (0x1u << MHU_2_X_INTR_NR2R_OFF)
#define MHU_2_X_INTR_R2NR_MASK (0x1u << MHU_2_X_INTR_R2NR_OFF)
#define MHU_2_1_INTR_CHCOMB_MASK (0x1u << MHU_2_1_INTR_CHCOMB_OFF)
enum mhu_v2_x_frame_t {
MHU_V2_X_SENDER_FRAME = 0x0u,
MHU_V2_X_RECEIVER_FRAME = 0x1u,
};
enum mhu_v2_x_supported_revisions {
MHU_REV_READ_FROM_HW = 0,
MHU_REV_2_0,
MHU_REV_2_1,
};
struct mhu_v2_x_dev_t {
uintptr_t base;
enum mhu_v2_x_frame_t frame;
uint32_t subversion; /*!< Hardware subversion: v2.X */
bool is_initialized; /*!< Indicates if the MHU driver
* is initialized and enabled
*/
};
/**
* MHU v2 error enumeration types.
*/
enum mhu_v2_x_error_t {
MHU_V_2_X_ERR_NONE = 0,
MHU_V_2_X_ERR_NOT_INIT = -1,
MHU_V_2_X_ERR_ALREADY_INIT = -2,
MHU_V_2_X_ERR_UNSUPPORTED_VERSION = -3,
MHU_V_2_X_ERR_INVALID_ARG = -4,
MHU_V_2_X_ERR_GENERAL = -5
};
/**
* Initializes the driver.
*
* dev MHU device struct mhu_v2_x_dev_t.
* rev MHU revision (if can't be identified from HW).
*
* Reads the MHU hardware version.
*
* Returns mhu_v2_x_error_t error code.
*
* MHU revision only has to be specified when versions can't be read
* from HW (ARCH_MAJOR_REV reg reads as 0x0).
*
* This function doesn't check if dev is NULL.
*/
enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
enum mhu_v2_x_supported_revisions rev);
/**
* Returns the number of channels implemented.
*
* dev MHU device struct mhu_v2_x_dev_t.
*
* This function doesn't check if dev is NULL.
*/
uint32_t mhu_v2_x_get_num_channel_implemented(
const struct mhu_v2_x_dev_t *dev);
/**
* Sends the value over a channel.
*
* dev MHU device struct mhu_v2_x_dev_t.
* channel Channel to send the value over.
* val Value to send.
*
* Sends the value over a channel.
*
* Returns mhu_v2_x_error_t error code.
*
* This function doesn't check if dev is NULL.
* This function doesn't check if channel is implemented.
*/
enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
uint32_t channel, uint32_t val);
/**
* Polls sender channel status.
*
* dev MHU device struct mhu_v2_x_dev_t.
* channel Channel to poll the status of.
* value Pointer to variable that will store the value.
*
* Polls sender channel status.
*
* Returns mhu_v2_x_error_t error code.
*
* This function doesn't check if dev is NULL.
* This function doesn't check if channel is implemented.
*/
enum mhu_v2_x_error_t mhu_v2_x_channel_poll(const struct mhu_v2_x_dev_t *dev,
uint32_t channel, uint32_t *value);
/**
* Clears the channel after the value is send over it.
*
* dev MHU device struct mhu_v2_x_dev_t.
* channel Channel to clear.
*
* Clears the channel after the value is send over it.
*
* Returns mhu_v2_x_error_t error code..
*
* This function doesn't check if dev is NULL.
* This function doesn't check if channel is implemented.
*/
enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
uint32_t channel);
/**
* Receives the value over a channel.
*
* dev MHU device struct mhu_v2_x_dev_t.
* channel Channel to receive the value from.
* value Pointer to variable that will store the value.
*
* Receives the value over a channel.
*
* Returns mhu_v2_x_error_t error code.
*
* This function doesn't check if dev is NULL.
* This function doesn't check if channel is implemented.
*/
enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value);
/**
* Sets bits in the Channel Mask.
*
* dev MHU device struct mhu_v2_x_dev_t.
* channel Which channel's mask to set.
* mask Mask to be set over a receiver frame.
*
* Sets bits in the Channel Mask.
*
* Returns mhu_v2_x_error_t error code..
*
* This function doesn't check if dev is NULL.
* This function doesn't check if channel is implemented.
*/
enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
/**
* Clears bits in the Channel Mask.
*
* dev MHU device struct mhu_v2_x_dev_t.
* channel Which channel's mask to clear.
* mask Mask to be clear over a receiver frame.
*
* Clears bits in the Channel Mask.
*
* Returns mhu_v2_x_error_t error code.
*
* This function doesn't check if dev is NULL.
* This function doesn't check if channel is implemented.
*/
enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
/**
* Initiates a MHU transfer with the handshake signals.
*
* dev MHU device struct mhu_v2_x_dev_t.
*
* Initiates a MHU transfer with the handshake signals in a blocking mode.
*
* Returns mhu_v2_x_error_t error code.
*
* This function doesn't check if dev is NULL.
*/
enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
const struct mhu_v2_x_dev_t *dev);
/**
* Closes a MHU transfer with the handshake signals.
*
* dev MHU device struct mhu_v2_x_dev_t.
*
* Closes a MHU transfer with the handshake signals in a blocking mode.
*
* Returns mhu_v2_x_error_t error code.
*
* This function doesn't check if dev is NULL.
*/
enum mhu_v2_x_error_t mhu_v2_x_close_transfer(
const struct mhu_v2_x_dev_t *dev);
#endif /* MHU_V2_X_H */

View File

@ -0,0 +1,302 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <drivers/arm/mhu.h>
#include "mhu_v2_x.h"
#define MHU_NOTIFY_VALUE (1234u)
/*
* MHU devices for host:
* HSE: Host to Secure Enclave (sender device)
* SEH: Secure Enclave to Host (receiver device)
*/
struct mhu_v2_x_dev_t MHU1_HSE_DEV = {0, MHU_V2_X_SENDER_FRAME};
struct mhu_v2_x_dev_t MHU1_SEH_DEV = {0, MHU_V2_X_RECEIVER_FRAME};
static enum mhu_error_t error_mapping_to_mhu_error_t(enum mhu_v2_x_error_t err)
{
switch (err) {
case MHU_V_2_X_ERR_NONE:
return MHU_ERR_NONE;
case MHU_V_2_X_ERR_NOT_INIT:
return MHU_ERR_NOT_INIT;
case MHU_V_2_X_ERR_ALREADY_INIT:
return MHU_ERR_ALREADY_INIT;
case MHU_V_2_X_ERR_UNSUPPORTED_VERSION:
return MHU_ERR_UNSUPPORTED_VERSION;
case MHU_V_2_X_ERR_INVALID_ARG:
return MHU_ERR_INVALID_ARG;
case MHU_V_2_X_ERR_GENERAL:
return MHU_ERR_GENERAL;
default:
return MHU_ERR_GENERAL;
}
}
static enum mhu_v2_x_error_t signal_and_wait_for_clear(void)
{
enum mhu_v2_x_error_t err;
struct mhu_v2_x_dev_t *dev = &MHU1_HSE_DEV;
uint32_t val = MHU_NOTIFY_VALUE;
/* Using the last channel for notifications */
uint32_t channel_notify = mhu_v2_x_get_num_channel_implemented(dev) - 1;
err = mhu_v2_x_channel_send(dev, channel_notify, val);
if (err != MHU_V_2_X_ERR_NONE) {
return err;
}
do {
err = mhu_v2_x_channel_poll(dev, channel_notify, &val);
if (err != MHU_V_2_X_ERR_NONE) {
break;
}
} while (val != 0);
return err;
}
static enum mhu_v2_x_error_t wait_for_signal(void)
{
enum mhu_v2_x_error_t err;
struct mhu_v2_x_dev_t *dev = &MHU1_SEH_DEV;
uint32_t val = 0;
/* Using the last channel for notifications */
uint32_t channel_notify = mhu_v2_x_get_num_channel_implemented(dev) - 1;
do {
err = mhu_v2_x_channel_receive(dev, channel_notify, &val);
if (err != MHU_V_2_X_ERR_NONE) {
break;
}
} while (val != MHU_NOTIFY_VALUE);
return err;
}
static enum mhu_v2_x_error_t clear_and_wait_for_next_signal(void)
{
enum mhu_v2_x_error_t err;
struct mhu_v2_x_dev_t *dev = &MHU1_SEH_DEV;
uint32_t num_channels = mhu_v2_x_get_num_channel_implemented(dev);
uint32_t i;
/* Clear all channels */
for (i = 0; i < num_channels; ++i) {
err = mhu_v2_x_channel_clear(dev, i);
if (err != MHU_V_2_X_ERR_NONE) {
return err;
}
}
return wait_for_signal();
}
enum mhu_error_t mhu_init_sender(uintptr_t mhu_sender_base)
{
enum mhu_v2_x_error_t err;
assert(mhu_sender_base != (uintptr_t)NULL);
MHU1_HSE_DEV.base = mhu_sender_base;
err = mhu_v2_x_driver_init(&MHU1_HSE_DEV, MHU_REV_READ_FROM_HW);
return error_mapping_to_mhu_error_t(err);
}
enum mhu_error_t mhu_init_receiver(uintptr_t mhu_receiver_base)
{
enum mhu_v2_x_error_t err;
uint32_t num_channels, i;
assert(mhu_receiver_base != (uintptr_t)NULL);
MHU1_SEH_DEV.base = mhu_receiver_base;
err = mhu_v2_x_driver_init(&MHU1_SEH_DEV, MHU_REV_READ_FROM_HW);
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
num_channels = mhu_v2_x_get_num_channel_implemented(&MHU1_SEH_DEV);
/* Mask all channels except the notifying channel */
for (i = 0; i < (num_channels - 1); ++i) {
err = mhu_v2_x_channel_mask_set(&MHU1_SEH_DEV, i, UINT32_MAX);
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
}
/* The last channel is used for notifications */
err = mhu_v2_x_channel_mask_clear(
&MHU1_SEH_DEV, (num_channels - 1), UINT32_MAX);
return error_mapping_to_mhu_error_t(err);
}
/*
* Public function. See mhu.h
*
* The basic steps of transferring a message:
* 1. Initiate MHU transfer.
* 2. Send over the size of the payload on Channel 1. It is the very first
* 4 Bytes of the transfer. Continue with Channel 2.
* 3. Send over the payload, writing the channels one after the other
* (4 Bytes each). The last available channel is reserved for controlling
* the transfer.
* When the last channel is reached or no more data is left, STOP.
* 4. Notify the receiver using the last channel and wait for acknowledge.
* If there is still data to transfer, jump to step 3. Otherwise, proceed.
* 5. Close MHU transfer.
*
*/
enum mhu_error_t mhu_send_data(const uint8_t *send_buffer, size_t size)
{
enum mhu_v2_x_error_t err;
struct mhu_v2_x_dev_t *dev = &MHU1_HSE_DEV;
uint32_t num_channels = mhu_v2_x_get_num_channel_implemented(dev);
uint32_t chan = 0;
uint32_t i;
uint32_t *p;
/* For simplicity, require the send_buffer to be 4-byte aligned */
if ((uintptr_t)send_buffer & 0x3U) {
return MHU_ERR_INVALID_ARG;
}
err = mhu_v2_x_initiate_transfer(dev);
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
/* First send over the size of the actual message */
err = mhu_v2_x_channel_send(dev, chan, (uint32_t)size);
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
chan++;
p = (uint32_t *)send_buffer;
for (i = 0; i < size; i += 4) {
err = mhu_v2_x_channel_send(dev, chan, *p++);
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
if (++chan == (num_channels - 1)) {
err = signal_and_wait_for_clear();
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
chan = 0;
}
}
/* Signal the end of transfer.
* It's not required to send a signal when the message was
* perfectly-aligned (num_channels - 1 channels were used in the last
* round) preventing it from signaling twice at the end of transfer.
*/
if (chan != 0) {
err = signal_and_wait_for_clear();
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
}
err = mhu_v2_x_close_transfer(dev);
return error_mapping_to_mhu_error_t(err);
}
/*
* Public function. See mhu.h
*
* The basic steps of receiving a message:
* 1. Read the size of the payload from Channel 1. It is the very first
* 4 Bytes of the transfer. Continue with Channel 2.
* 2. Receive the payload, read the channels one after the other
* (4 Bytes each). The last available channel is reserved for controlling
* the transfer.
* When the last channel is reached clear all the channels
* (also sending an acknowledge on the last channel).
* 3. If there is still data to receive wait for a notification on the last
* channel and jump to step 2 as soon as it arrived. Otherwise, proceed.
* 4. End of transfer.
*
*/
enum mhu_error_t mhu_receive_data(uint8_t *receive_buffer, size_t *size)
{
enum mhu_v2_x_error_t err;
struct mhu_v2_x_dev_t *dev = &MHU1_SEH_DEV;
uint32_t num_channels = mhu_v2_x_get_num_channel_implemented(dev);
uint32_t chan = 0;
uint32_t message_len;
uint32_t i;
uint32_t *p;
/* For simplicity, require:
* - the receive_buffer to be 4-byte aligned,
* - the buffer size to be a multiple of 4.
*/
if (((uintptr_t)receive_buffer & 0x3U) || (*size & 0x3U)) {
return MHU_ERR_INVALID_ARG;
}
/* Busy wait for incoming reply */
err = wait_for_signal();
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
/* The first word is the length of the actual message */
err = mhu_v2_x_channel_receive(dev, chan, &message_len);
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
chan++;
if (message_len > *size) {
/* Message buffer too small */
*size = message_len;
return MHU_ERR_BUFFER_TOO_SMALL;
}
p = (uint32_t *)receive_buffer;
for (i = 0; i < message_len; i += 4) {
err = mhu_v2_x_channel_receive(dev, chan, p++);
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
/* Only wait for next transfer if there is still missing data */
if (++chan == (num_channels - 1) && (message_len - i) > 4) {
/* Busy wait for next transfer */
err = clear_and_wait_for_next_signal();
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
chan = 0;
}
}
/* Clear all channels */
for (i = 0; i < num_channels; ++i) {
err = mhu_v2_x_channel_clear(dev, i);
if (err != MHU_V_2_X_ERR_NONE) {
return error_mapping_to_mhu_error_t(err);
}
}
*size = message_len;
return MHU_ERR_NONE;
}

225
drivers/arm/rss/rss_comms.c Normal file
View File

@ -0,0 +1,225 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <string.h>
#include <common/debug.h>
#include <drivers/arm/mhu.h>
#include <drivers/arm/rss_comms.h>
#include <initial_attestation.h>
#include <psa/client.h>
#include <platform_def.h>
#define TYPE_OFFSET U(16)
#define TYPE_MASK (0xFFFFUL << TYPE_OFFSET)
#define IN_LEN_OFFSET U(8)
#define IN_LEN_MASK (0xFFUL << IN_LEN_OFFSET)
#define OUT_LEN_OFFSET U(0)
#define OUT_LEN_MASK (0xFFUL << OUT_LEN_OFFSET)
#define PARAM_PACK(type, in_len, out_len) \
(((((uint32_t)type) << TYPE_OFFSET) & TYPE_MASK) | \
((((uint32_t)in_len) << IN_LEN_OFFSET) & IN_LEN_MASK) | \
((((uint32_t)out_len) << OUT_LEN_OFFSET) & OUT_LEN_MASK))
#define PARAM_UNPACK_IN_LEN(ctrl_param) \
((size_t)(((ctrl_param) & IN_LEN_MASK) >> IN_LEN_OFFSET))
/* Message types */
struct __packed packed_psa_call_t {
uint8_t protocol_ver;
uint8_t seq_num;
uint16_t client_id;
psa_handle_t handle;
uint32_t ctrl_param; /* type, in_len, out_len */
uint16_t io_size[4];
};
struct __packed packed_psa_reply_t {
uint8_t protocol_ver;
uint8_t seq_num;
uint16_t client_id;
int32_t return_val;
uint16_t out_size[4];
};
/*
* In the current implementation the RoT Service request that requires the
* biggest message buffer is the RSS_ATTEST_GET_TOKEN. The maximum required
* buffer size is calculated based on the platform-specific needs of
* this request.
*/
#define MAX_REQUEST_PAYLOAD_SIZE (PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 \
+ PLAT_ATTEST_TOKEN_MAX_SIZE)
/* Buffer to store the messages to be sent/received. */
static uint8_t message_buf[MAX_REQUEST_PAYLOAD_SIZE] __aligned(4);
static int32_t pack_params(const psa_invec *invecs,
size_t in_len,
uint8_t *buf,
size_t *buf_len)
{
uint32_t i;
size_t payload_size = 0U;
for (i = 0U; i < in_len; ++i) {
if (invecs[i].len > *buf_len - payload_size) {
return -1;
}
memcpy(buf + payload_size, invecs[i].base, invecs[i].len);
payload_size += invecs[i].len;
}
*buf_len = payload_size;
return 0;
}
static int serialise_message(const struct packed_psa_call_t *msg,
const psa_invec *invecs,
uint8_t *payload_buf,
size_t *payload_len)
{
size_t message_len = 0U;
size_t len;
/* Copy the message header into the payload buffer. */
len = sizeof(*msg);
if (len > *payload_len) {
ERROR("[RSS-COMMS] Message buffer too small.\n");
return -1;
}
memcpy(payload_buf, (const void *)msg, len);
message_len += len;
/* The input data will follow the message header in the payload buffer. */
len = *payload_len - message_len;
if (pack_params(invecs, PARAM_UNPACK_IN_LEN(msg->ctrl_param),
payload_buf + message_len, &len) != 0) {
ERROR("[RSS-COMMS] Message buffer too small.\n");
return -1;
}
message_len += len;
*payload_len = message_len;
return 0;
}
static void unpack_params(const uint8_t *buf,
psa_outvec *outvecs,
size_t out_len)
{
size_t i;
for (i = 0U; i < out_len; ++i) {
memcpy(outvecs[i].base, buf, outvecs[i].len);
buf += outvecs[i].len;
}
}
static void deserialise_reply(struct packed_psa_reply_t *reply,
psa_outvec *outvecs,
size_t outlen,
const uint8_t *message,
size_t message_len)
{
uint32_t i;
memcpy(reply, message, sizeof(*reply));
/* Outvecs */
for (i = 0U; i < outlen; ++i) {
outvecs[i].len = reply->out_size[i];
}
unpack_params(message + sizeof(*reply), outvecs, outlen);
}
psa_status_t psa_call(psa_handle_t handle, int32_t type,
const psa_invec *in_vec, size_t in_len,
psa_outvec *out_vec, size_t out_len)
{
enum mhu_error_t err;
static uint32_t seq_num = 1U;
struct packed_psa_call_t msg = {
.protocol_ver = 0U,
.seq_num = seq_num,
/* No need to distinguish callers (currently concurrent calls are not supported). */
.client_id = 1U,
.handle = handle,
.ctrl_param = PARAM_PACK(type, in_len, out_len),
};
struct packed_psa_reply_t reply = {0};
size_t message_size;
uint32_t i;
/* Fill msg iovec lengths */
for (i = 0U; i < in_len; ++i) {
msg.io_size[i] = in_vec[i].len;
}
for (i = 0U; i < out_len; ++i) {
msg.io_size[in_len + i] = out_vec[i].len;
}
message_size = sizeof(message_buf);
if (serialise_message(&msg, in_vec, message_buf, &message_size)) {
/* Local buffer is probably too small. */
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
err = mhu_send_data(message_buf, message_size);
if (err != MHU_ERR_NONE) {
return PSA_ERROR_COMMUNICATION_FAILURE;
}
message_size = sizeof(message_buf);
#if DEBUG
/*
* Poisoning the message buffer (with a known pattern).
* Helps in detecting hypothetical RSS communication bugs.
*/
memset(message_buf, 0xA5, message_size);
#endif
err = mhu_receive_data(message_buf, &message_size);
if (err != MHU_ERR_NONE) {
return PSA_ERROR_COMMUNICATION_FAILURE;
}
deserialise_reply(&reply, out_vec, out_len, message_buf, message_size);
seq_num++;
VERBOSE("[RSS-COMMS] Received reply\n");
VERBOSE("protocol_ver=%d\n", reply.protocol_ver);
VERBOSE("seq_num=%d\n", reply.seq_num);
VERBOSE("client_id=%d\n", reply.client_id);
VERBOSE("return_val=%d\n", reply.return_val);
VERBOSE("out_size[0]=%d\n", reply.out_size[0]);
return reply.return_val;
}
int rss_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base)
{
enum mhu_error_t err;
err = mhu_init_sender(mhu_sender_base);
if (err != MHU_ERR_NONE) {
ERROR("[RSS-COMMS] Host to RSS MHU driver initialization failed: %d\n", err);
return -1;
}
err = mhu_init_receiver(mhu_receiver_base);
if (err != MHU_ERR_NONE) {
ERROR("[RSS-COMMS] RSS to Host MHU driver initialization failed: %d\n", err);
return -1;
}
return 0;
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdint.h>
#include <common/debug.h>
#include <drivers/auth/crypto_mod.h>
#include <drivers/measured_boot/rss/rss_measured_boot.h>
#include <lib/psa/measured_boot.h>
#include <psa/crypto_types.h>
#include <psa/crypto_values.h>
#include <psa/error.h>
#define MBOOT_ALG_SHA512 0
#define MBOOT_ALG_SHA384 1
#define MBOOT_ALG_SHA256 2
#if MBOOT_ALG_ID == MBOOT_ALG_SHA512
#define CRYPTO_MD_ID CRYPTO_MD_SHA512
#define PSA_CRYPTO_MD_ID PSA_ALG_SHA_512
#elif MBOOT_ALG_ID == MBOOT_ALG_SHA384
#define CRYPTO_MD_ID CRYPTO_MD_SHA384
#define PSA_CRYPTO_MD_ID PSA_ALG_SHA_384
#elif MBOOT_ALG_ID == MBOOT_ALG_SHA256
#define CRYPTO_MD_ID CRYPTO_MD_SHA256
#define PSA_CRYPTO_MD_ID PSA_ALG_SHA_256
#else
# error Invalid Measured Boot algorithm.
#endif /* MBOOT_ALG_ID */
/* Pointer to struct rss_mboot_metadata */
static struct rss_mboot_metadata *plat_metadata_ptr;
/* Functions' declarations */
void rss_measured_boot_init(void)
{
/* At this point it is expected that communication channel over MHU
* is already initialised by platform init.
*/
/* Get pointer to platform's struct rss_mboot_metadata structure */
plat_metadata_ptr = plat_rss_mboot_get_metadata();
assert(plat_metadata_ptr != NULL);
}
int rss_mboot_measure_and_record(uintptr_t data_base, uint32_t data_size,
uint32_t data_id)
{
unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
int rc;
psa_status_t ret;
const struct rss_mboot_metadata *metadata_ptr = plat_metadata_ptr;
/* Get the metadata associated with this image. */
while ((metadata_ptr->id != RSS_MBOOT_INVALID_ID) &&
(metadata_ptr->id != data_id)) {
metadata_ptr++;
}
/* If image is not present in metadata array then skip */
if (metadata_ptr->id == RSS_MBOOT_INVALID_ID) {
return 0;
}
/* Calculate hash */
rc = crypto_mod_calc_hash(CRYPTO_MD_ID,
(void *)data_base, data_size, hash_data);
if (rc != 0) {
return rc;
}
ret = rss_measured_boot_extend_measurement(
metadata_ptr->slot,
metadata_ptr->signer_id,
metadata_ptr->signer_id_size,
metadata_ptr->version,
metadata_ptr->version_size,
PSA_CRYPTO_MD_ID,
metadata_ptr->sw_type,
metadata_ptr->sw_type_size,
hash_data,
MBOOT_DIGEST_SIZE,
metadata_ptr->lock_measurement);
if (ret != PSA_SUCCESS) {
return ret;
}
return 0;
}
int rss_mboot_set_signer_id(unsigned int img_id,
const void *pk_ptr,
size_t pk_len)
{
unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
struct rss_mboot_metadata *metadata_ptr = plat_metadata_ptr;
int rc;
/* Get the metadata associated with this image. */
while ((metadata_ptr->id != RSS_MBOOT_INVALID_ID) &&
(metadata_ptr->id != img_id)) {
metadata_ptr++;
}
/* If image is not present in metadata array then skip */
if (metadata_ptr->id == RSS_MBOOT_INVALID_ID) {
return 0;
}
/* Calculate public key hash */
rc = crypto_mod_calc_hash(CRYPTO_MD_ID, (void *)pk_ptr,
pk_len, hash_data);
if (rc != 0) {
return rc;
}
/* Update metadata struct with the received signer_id */
(void)memcpy(metadata_ptr->signer_id, hash_data, MBOOT_DIGEST_SIZE);
metadata_ptr->signer_id_size = MBOOT_DIGEST_SIZE;
return 0;
}

View File

@ -0,0 +1,35 @@
#
# Copyright (c) 2022, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Hash algorithm for measured boot
# SHA-256 (or stronger) is required.
# TODO: The measurement algorithm incorrectly suggests that the TPM backend
# is used which may not be the case. It is currently being worked on and
# soon TPM_HASH_ALG will be replaced by a more generic name.
TPM_HASH_ALG := sha256
ifeq (${TPM_HASH_ALG}, sha512)
MBOOT_ALG_ID := MBOOT_ALG_SHA512
MBOOT_DIGEST_SIZE := 64U
else ifeq (${TPM_HASH_ALG}, sha384)
MBOOT_ALG_ID := MBOOT_ALG_SHA384
MBOOT_DIGEST_SIZE := 48U
else
MBOOT_ALG_ID := MBOOT_ALG_SHA256
MBOOT_DIGEST_SIZE := 32U
endif #TPM_HASH_ALG
# Set definitions for Measured Boot driver.
$(eval $(call add_defines,\
$(sort \
MBOOT_ALG_ID \
MBOOT_DIGEST_SIZE \
MBOOT_RSS_BACKEND \
)))
MEASURED_BOOT_SRC_DIR := drivers/measured_boot/rss/
MEASURED_BOOT_SOURCES += ${MEASURED_BOOT_SRC_DIR}rss_measured_boot.c

79
include/drivers/arm/mhu.h Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MHU_H
#define MHU_H
#include <stddef.h>
#include <stdint.h>
/**
* Generic MHU error enumeration types.
*/
enum mhu_error_t {
MHU_ERR_NONE = 0,
MHU_ERR_NOT_INIT = -1,
MHU_ERR_ALREADY_INIT = -2,
MHU_ERR_UNSUPPORTED_VERSION = -3,
MHU_ERR_UNSUPPORTED = -4,
MHU_ERR_INVALID_ARG = -5,
MHU_ERR_BUFFER_TOO_SMALL = -6,
MHU_ERR_GENERAL = -7,
};
/**
* Initializes sender MHU.
*
* mhu_sender_base Base address of sender MHU.
*
* Returns mhu_error_t error code.
*
* This function must be called before mhu_send_data().
*/
enum mhu_error_t mhu_init_sender(uintptr_t mhu_sender_base);
/**
* Initializes receiver MHU.
*
* mhu_receiver_base Base address of receiver MHU.
*
* Returns mhu_error_t error code.
*
* This function must be called before mhu_receive_data().
*/
enum mhu_error_t mhu_init_receiver(uintptr_t mhu_receiver_base);
/**
* Sends data over MHU.
*
* send_buffer Pointer to buffer containing the data to be transmitted.
* size Size of the data to be transmitted in bytes.
*
* Returns mhu_error_t error code.
*
* The send_buffer must be 4-byte aligned and its length must be at least
* (4 - (size % 4)) bytes bigger than the data size to prevent buffer
* over-reading.
*/
enum mhu_error_t mhu_send_data(const uint8_t *send_buffer, size_t size);
/**
* Receives data from MHU.
*
* receive_buffer Pointer the buffer where to store the received data.
* size As input the size of the receive_buffer, as output the
* number of bytes received. As a limitation,
* the size of the buffer must be a multiple of 4.
*
* Returns mhu_error_t error code.
*
* The receive_buffer must be 4-byte aligned and its length must be a
* multiple of 4.
*/
enum mhu_error_t mhu_receive_data(uint8_t *receive_buffer, size_t *size);
#endif /* MHU_H */

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef RSS_COMMS_H
#define RSS_COMMS_H
#include <stdint.h>
int rss_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base);
#endif /* RSS_COMMS_H */

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RSS_MEASURED_BOOT_H
#define RSS_MEASURED_BOOT_H
#include <stdint.h>
#include <common/debug.h>
#include <measured_boot.h>
#define RSS_MBOOT_INVALID_ID UINT32_MAX
/*
* Each boot measurement has some metadata (i.e. a string) that identifies
* what was measured and how. The sw_type field of the rss_mboot_metadata
* structure represents the role of the software component that was measured.
* The below macros define strings suitable for the sw_type.
* The key thing is to choose meaningful strings so that when the attestation
* token is verified, then the different components can be identified.
*/
#define RSS_MBOOT_BL2_STRING "BL_2"
#define RSS_MBOOT_BL31_STRING "SECURE_RT_EL3"
#define RSS_MBOOT_HW_CONFIG_STRING "HW_CONFIG"
#define RSS_MBOOT_FW_CONFIG_STRING "FW_CONFIG"
#define RSS_MBOOT_TB_FW_CONFIG_STRING "TB_FW_CONFIG"
#define RSS_MBOOT_SOC_FW_CONFIG_STRING "SOC_FW_CONFIG"
#define RSS_MBOOT_RMM_STRING "RMM"
struct rss_mboot_metadata {
unsigned int id;
uint8_t slot;
uint8_t signer_id[SIGNER_ID_MAX_SIZE];
size_t signer_id_size;
uint8_t version[VERSION_MAX_SIZE];
size_t version_size;
uint8_t sw_type[SW_TYPE_MAX_SIZE];
size_t sw_type_size;
bool lock_measurement;
};
/* Functions' declarations */
void rss_measured_boot_init(void);
struct rss_mboot_metadata *plat_rss_mboot_get_metadata(void);
int rss_mboot_measure_and_record(uintptr_t data_base, uint32_t data_size,
uint32_t data_id);
/* TODO: These metadata are currently not available during TF-A boot */
int rss_mboot_set_signer_id(unsigned int img_id, const void *pk_ptr, size_t pk_len);
#endif /* RSS_MEASURED_BOOT_H */

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2018-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef PSA_INITIAL_ATTESTATION_H
#define PSA_INITIAL_ATTESTATION_H
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include "psa/error.h"
/*
* Initial attestation API version is: 1.0.0
*/
#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (1)
#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (0)
/* The allowed size of input challenge in bytes. */
#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 32U
#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 48U
#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 64U
/* Initial Attestation message types that distinguish Attest services. */
#define RSS_ATTEST_GET_TOKEN 1001U
#define RSS_ATTEST_GET_TOKEN_SIZE 1002U
#define RSS_ATTEST_GET_DELEGATED_KEY 1003U
/**
* Get the platform attestation token.
*
* auth_challenge Pointer to buffer where challenge input is stored. This
* must be the hash of the public part of the delegated
* attestation key.
* challenge_size Size of challenge object in bytes.
* token_buf Pointer to the buffer where attestation token will be
* stored.
* token_buf_size Size of allocated buffer for token, in bytes.
* token_size Size of the token that has been returned, in bytes.
*
* Returns error code as specified in psa_status_t.
*/
psa_status_t
psa_initial_attest_get_token(const uint8_t *auth_challenge,
size_t challenge_size,
uint8_t *token_buf,
size_t token_buf_size,
size_t *token_size);
#endif /* PSA_INITIAL_ATTESTATION_H */

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef PSA_MEASURED_BOOT_H
#define PSA_MEASURED_BOOT_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "psa/error.h"
/* Minimum measurement value size that can be requested to store */
#define MEASUREMENT_VALUE_MIN_SIZE 32U
/* Maximum measurement value size that can be requested to store */
#define MEASUREMENT_VALUE_MAX_SIZE 64U
/* Minimum signer id size that can be requested to store */
#define SIGNER_ID_MIN_SIZE MEASUREMENT_VALUE_MIN_SIZE
/* Maximum signer id size that can be requested to store */
#define SIGNER_ID_MAX_SIZE MEASUREMENT_VALUE_MAX_SIZE
/* The theoretical maximum image version is: "255.255.65535\0" */
#define VERSION_MAX_SIZE 14U
/* Example sw_type: "BL_2, BL_33, etc." */
#define SW_TYPE_MAX_SIZE 20U
#define NUM_OF_MEASUREMENT_SLOTS 32U
/**
* Extends and stores a measurement to the requested slot.
*
* index Slot number in which measurement is to be stored
* signer_id Pointer to signer_id buffer.
* signer_id_size Size of the signer_id buffer in bytes.
* version Pointer to version buffer.
* version_size Size of the version buffer in bytes.
* measurement_algo Algorithm identifier used for measurement.
* sw_type Pointer to sw_type buffer.
* sw_type_size Size of the sw_type buffer in bytes.
* measurement_value Pointer to measurement_value buffer.
* measurement_value_size Size of the measurement_value buffer in bytes.
* lock_measurement Boolean flag requesting whether the measurement
* is to be locked.
*
* PSA_SUCCESS:
* - Success.
* PSA_ERROR_INVALID_ARGUMENT:
* - The size of any argument is invalid OR
* - Input Measurement value is NULL OR
* - Input Signer ID is NULL OR
* - Requested slot index is invalid.
* PSA_ERROR_BAD_STATE:
* - Request to lock, when slot is already locked.
* PSA_ERROR_NOT_PERMITTED:
* - When the requested slot is not accessible to the caller.
*/
/* Not a standard PSA API, just an extension therefore use the 'rss_' prefix
* rather than the usual 'psa_'.
*/
psa_status_t
rss_measured_boot_extend_measurement(uint8_t index,
const uint8_t *signer_id,
size_t signer_id_size,
const uint8_t *version,
size_t version_size,
uint32_t measurement_algo,
const uint8_t *sw_type,
size_t sw_type_size,
const uint8_t *measurement_value,
size_t measurement_value_size,
bool lock_measurement);
#endif /* PSA_MEASURED_BOOT_H */

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2018-2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef PSA_CLIENT_H
#define PSA_CLIENT_H
#include <stddef.h>
#include <stdint.h>
#include <psa/error.h>
#ifndef IOVEC_LEN
#define IOVEC_LEN(arr) ((uint32_t)(sizeof(arr)/sizeof(arr[0])))
#endif
/*********************** PSA Client Macros and Types *************************/
/**
* The version of the PSA Framework API that is being used to build the calling
* firmware. Only part of features of FF-M v1.1 have been implemented. FF-M v1.1
* is compatible with v1.0.
*/
#define PSA_FRAMEWORK_VERSION (0x0101u)
/**
* Return value from psa_version() if the requested RoT Service is not present
* in the system.
*/
#define PSA_VERSION_NONE (0u)
/**
* The zero-value null handle can be assigned to variables used in clients and
* RoT Services, indicating that there is no current connection or message.
*/
#define PSA_NULL_HANDLE ((psa_handle_t)0)
/**
* Tests whether a handle value returned by psa_connect() is valid.
*/
#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0)
/**
* Converts the handle value returned from a failed call psa_connect() into
* an error code.
*/
#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle))
/**
* Maximum number of input and output vectors for a request to psa_call().
*/
#define PSA_MAX_IOVEC (4u)
/**
* An IPC message type that indicates a generic client request.
*/
#define PSA_IPC_CALL (0)
typedef int32_t psa_handle_t;
/**
* A read-only input memory region provided to an RoT Service.
*/
typedef struct psa_invec {
const void *base; /*!< the start address of the memory buffer */
size_t len; /*!< the size in bytes */
} psa_invec;
/**
* A writable output memory region provided to an RoT Service.
*/
typedef struct psa_outvec {
void *base; /*!< the start address of the memory buffer */
size_t len; /*!< the size in bytes */
} psa_outvec;
/**
* Call an RoT Service on an established connection.
*
* handle A handle to an established connection.
* type The request type. Must be zero(PSA_IPC_CALL) or positive.
* in_vec Array of input psa_invec structures.
* in_len Number of input psa_invec structures.
* out_vec Array of output psa_outvec structures.
* out_len Number of output psa_outvec structures.
*
* Return value >=0 RoT Service-specific status value.
* Return value <0 RoT Service-specific error code.
*
* PSA_ERROR_PROGRAMMER_ERROR:
* - The connection has been terminated by the RoT Service.
*
* The call is a PROGRAMMER ERROR if one or more of the following are true:
* - An invalid handle was passed.
* - The connection is already handling a request.
* - type < 0.
* - An invalid memory reference was provided.
* - in_len + out_len > PSA_MAX_IOVEC.
* - The message is unrecognized by the RoT.
* - Service or incorrectly formatted.
*/
psa_status_t psa_call(psa_handle_t handle,
int32_t type,
const psa_invec *in_vec,
size_t in_len,
psa_outvec *out_vec,
size_t out_len);
#endif /* PSA_CLIENT_H */

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2019-2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef PSA_ERROR_H
#define PSA_ERROR_H
#include <stdint.h>
typedef int32_t psa_status_t;
#define PSA_SUCCESS ((psa_status_t)0)
#define PSA_SUCCESS_REBOOT ((psa_status_t)1)
#define PSA_SUCCESS_RESTART ((psa_status_t)2)
#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129)
#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130)
#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131)
#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132)
#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133)
#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134)
#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135)
#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136)
#define PSA_ERROR_BAD_STATE ((psa_status_t)-137)
#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138)
#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139)
#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140)
#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141)
#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142)
#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143)
#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144)
#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145)
#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146)
#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147)
#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149)
#define PSA_ERROR_DEPENDENCY_NEEDED ((psa_status_t)-156)
#define PSA_ERROR_CURRENTLY_INSTALLING ((psa_status_t)-157)
#endif /* PSA_ERROR_H */

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2019-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef PSA_MANIFEST_SID_H
#define PSA_MANIFEST_SID_H
/******** PSA_SP_INITIAL_ATTESTATION ********/
#define RSS_ATTESTATION_SERVICE_SID (0x00000020U)
#define RSS_ATTESTATION_SERVICE_VERSION (1U)
#define RSS_ATTESTATION_SERVICE_HANDLE (0x40000103U)
/******** PSA_SP_MEASURED_BOOT ********/
#define RSS_MEASURED_BOOT_SID (0x000000E0U)
#define RSS_MEASURED_BOOT_VERSION (1U)
#define RSS_MEASURED_BOOT_HANDLE (0x40000104U)
#endif /* PSA_MANIFEST_SID_H */

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2018-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <initial_attestation.h>
#include <psa/client.h>
#include <psa_manifest/sid.h>
#if !PLAT_RSS_NOT_SUPPORTED
psa_status_t
psa_initial_attest_get_token(const uint8_t *auth_challenge,
size_t challenge_size,
uint8_t *token_buf,
size_t token_buf_size,
size_t *token_size)
{
psa_status_t status;
psa_invec in_vec[] = {
{auth_challenge, challenge_size}
};
psa_outvec out_vec[] = {
{token_buf, token_buf_size},
};
status = psa_call(RSS_ATTESTATION_SERVICE_HANDLE, RSS_ATTEST_GET_TOKEN,
in_vec, IOVEC_LEN(in_vec),
out_vec, IOVEC_LEN(out_vec));
if (status == PSA_SUCCESS) {
*token_size = out_vec[0].len;
}
return status;
}
#else /* !PLAT_RSS_NOT_SUPPORTED */
#include <string.h>
static const uint8_t platform_token[] = {
0xD2, 0x84, 0x43, 0xA1, 0x01, 0x26, 0xA0, 0x59,
0x02, 0xBE, 0xAA, 0x3A, 0x00, 0x01, 0x24, 0xFF,
0x58, 0x20, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
0xAB, 0xAB, 0x3A, 0x00, 0x01, 0x24, 0xFB, 0x58,
0x20, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE,
0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
0xBF, 0x3A, 0x00, 0x01, 0x25, 0x00, 0x58, 0x21,
0x01, 0xFA, 0x58, 0x75, 0x5F, 0x65, 0x86, 0x27,
0xCE, 0x54, 0x60, 0xF2, 0x9B, 0x75, 0x29, 0x67,
0x13, 0x24, 0x8C, 0xAE, 0x7A, 0xD9, 0xE2, 0x98,
0x4B, 0x90, 0x28, 0x0E, 0xFC, 0xBC, 0xB5, 0x02,
0x48, 0x3A, 0x00, 0x01, 0x24, 0xFA, 0x58, 0x20,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
0x3A, 0x00, 0x01, 0x24, 0xF8, 0x20, 0x3A, 0x00,
0x01, 0x24, 0xF9, 0x00, 0x3A, 0x00, 0x01, 0x24,
0xFD, 0x85, 0xA5, 0x05, 0x58, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x60,
0x01, 0x65, 0x42, 0x4C, 0x31, 0x5F, 0x32, 0x06,
0x66, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x02,
0x58, 0x20, 0xF8, 0xB7, 0xCE, 0xAD, 0x9B, 0xE4,
0x5A, 0x8F, 0x5C, 0x52, 0x6F, 0x0C, 0x05, 0x25,
0x8F, 0xF3, 0xE9, 0x81, 0xDC, 0xBC, 0xF2, 0x05,
0x7F, 0x33, 0xF6, 0xBB, 0xDC, 0xD9, 0x4D, 0xA2,
0x34, 0x3A, 0xA5, 0x05, 0x58, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x67,
0x31, 0x2E, 0x37, 0x2E, 0x32, 0x2B, 0x30, 0x01,
0x63, 0x42, 0x4C, 0x32, 0x06, 0x66, 0x53, 0x48,
0x41, 0x32, 0x35, 0x36, 0x02, 0x58, 0x20, 0x3A,
0xE5, 0x9E, 0x40, 0xA9, 0x6B, 0xD5, 0x29, 0x1C,
0xAB, 0x7A, 0x5F, 0xBD, 0x1F, 0x9A, 0xA6, 0x52,
0xFB, 0x77, 0x7D, 0xA3, 0xEC, 0x9C, 0x29, 0xBC,
0xE6, 0x5B, 0x3B, 0x43, 0xFC, 0x9D, 0x26, 0xA5,
0x05, 0x58, 0x20, 0xBF, 0xE6, 0xD8, 0x6F, 0x88,
0x26, 0xF4, 0xFF, 0x97, 0xFB, 0x96, 0xC4, 0xE6,
0xFB, 0xC4, 0x99, 0x3E, 0x46, 0x19, 0xFC, 0x56,
0x5D, 0xA2, 0x6A, 0xDF, 0x34, 0xC3, 0x29, 0x48,
0x9A, 0xDC, 0x38, 0x04, 0x67, 0x31, 0x2E, 0x35,
0x2E, 0x30, 0x2B, 0x30, 0x01, 0x64, 0x52, 0x54,
0x5F, 0x30, 0x06, 0x66, 0x53, 0x48, 0x41, 0x32,
0x35, 0x36, 0x02, 0x58, 0x20, 0x47, 0x94, 0x9D,
0x27, 0x33, 0x82, 0x45, 0x1A, 0xDD, 0x25, 0xF4,
0x9A, 0x89, 0x6F, 0x5F, 0xD9, 0xB0, 0xE8, 0x14,
0xD3, 0xA4, 0x9B, 0x53, 0xB0, 0x44, 0x0B, 0xCF,
0x32, 0x1A, 0xC4, 0xD2, 0x65, 0xA5, 0x05, 0x58,
0x20, 0xB3, 0x60, 0xCA, 0xF5, 0xC9, 0x8C, 0x6B,
0x94, 0x2A, 0x48, 0x82, 0xFA, 0x9D, 0x48, 0x23,
0xEF, 0xB1, 0x66, 0xA9, 0xEF, 0x6A, 0x6E, 0x4A,
0xA3, 0x7C, 0x19, 0x19, 0xED, 0x1F, 0xCC, 0xC0,
0x49, 0x04, 0x67, 0x30, 0x2E, 0x30, 0x2E, 0x37,
0x2B, 0x30, 0x01, 0x64, 0x52, 0x54, 0x5F, 0x31,
0x06, 0x66, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36,
0x02, 0x58, 0x20, 0xCD, 0x38, 0xBE, 0xC8, 0xB7,
0xC0, 0x9E, 0xD5, 0x24, 0x30, 0xFE, 0xC8, 0xD0,
0x19, 0x12, 0x56, 0xB2, 0x7A, 0xA5, 0x53, 0x6F,
0xBC, 0x7D, 0x09, 0xCA, 0x11, 0xDD, 0x90, 0xD7,
0xD6, 0x70, 0xFD, 0xA5, 0x05, 0x58, 0x20, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x04,
0x60, 0x01, 0x60, 0x06, 0x66, 0x53, 0x48, 0x41,
0x32, 0x35, 0x36, 0x02, 0x58, 0x20, 0x28, 0x3D,
0x0C, 0x25, 0x22, 0x0C, 0x87, 0x46, 0xA0, 0x58,
0x64, 0x6C, 0x0B, 0x14, 0x37, 0x39, 0x40, 0x9D,
0x2D, 0x11, 0xD1, 0xCC, 0x54, 0x51, 0xB4, 0x29,
0x22, 0xCD, 0x70, 0x92, 0x71, 0xC3, 0x3A, 0x00,
0x01, 0x25, 0x01, 0x77, 0x77, 0x77, 0x77, 0x2E,
0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x66,
0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x2E,
0x6F, 0x72, 0x67, 0x3A, 0x00, 0x01, 0x24, 0xF7,
0x71, 0x50, 0x53, 0x41, 0x5F, 0x49, 0x4F, 0x54,
0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45,
0x5F, 0x31, 0x3A, 0x00, 0x01, 0x24, 0xFC, 0x70,
0x30, 0x36, 0x30, 0x34, 0x35, 0x36, 0x35, 0x32,
0x37, 0x32, 0x38, 0x32, 0x39, 0x31, 0x30, 0x30,
0x58, 0x40, 0x1E, 0x0D, 0x2B, 0xD8, 0x7A, 0xC9,
0x2D, 0xCB, 0x73, 0xD1, 0x42, 0x2F, 0xBF, 0xDA,
0x24, 0x71, 0xE2, 0xAF, 0xEA, 0x48, 0x60, 0x17,
0x23, 0x75, 0x64, 0xAC, 0xCC, 0x23, 0xA2, 0x67,
0xC4, 0xE7, 0x8F, 0x1C, 0x7C, 0x68, 0x49, 0x42,
0x4D, 0xDA, 0xC6, 0xD6, 0x21, 0x1C, 0xAA, 0x00,
0xDA, 0x1E, 0x68, 0x56, 0xA3, 0x48, 0xEE, 0xA7,
0x92, 0xA9, 0x09, 0x83, 0x42, 0x04, 0x06, 0x9E,
0x62, 0xBB
};
psa_status_t
psa_initial_attest_get_token(const uint8_t *auth_challenge,
size_t challenge_size,
uint8_t *token_buf,
size_t token_buf_size,
size_t *token_size)
{
(void)auth_challenge;
(void)challenge_size;
if (token_buf_size < sizeof(platform_token)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
(void)memcpy(token_buf, platform_token, sizeof(platform_token));
*token_size = sizeof(platform_token);
return PSA_SUCCESS;
}
#endif /* !PLAT_RSS_NOT_SUPPORTED */

129
lib/psa/measured_boot.c Normal file
View File

@ -0,0 +1,129 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <string.h>
#include <common/debug.h>
#include <measured_boot.h>
#include <psa/client.h>
#include <psa_manifest/sid.h>
#include "measured_boot_private.h"
static void print_byte_array(const uint8_t *array, size_t len)
{
unsigned int i;
if (array == NULL || len == 0U) {
(void)printf("\n");
}
for (i = 0U; i < len; ++i) {
(void)printf(" %02x", array[i]);
if ((i & U(0xF)) == U(0xF)) {
(void)printf("\n");
if (i < (len - 1U)) {
INFO("\t\t:");
}
}
}
}
static void log_measurement(uint8_t index,
const uint8_t *signer_id,
size_t signer_id_size,
const uint8_t *version, /* string */
uint32_t measurement_algo,
const uint8_t *sw_type, /* string */
const uint8_t *measurement_value,
size_t measurement_value_size,
bool lock_measurement)
{
INFO("Measured boot extend measurement:\n");
INFO(" - slot : %u\n", index);
INFO(" - signer_id :");
print_byte_array(signer_id, signer_id_size);
INFO(" - version : %s\n", version);
INFO(" - algorithm : %x\n", measurement_algo);
INFO(" - sw_type : %s\n", sw_type);
INFO(" - measurement :");
print_byte_array(measurement_value, measurement_value_size);
INFO(" - locking : %s\n", lock_measurement ? "true" : "false");
}
#if !PLAT_RSS_NOT_SUPPORTED
psa_status_t
rss_measured_boot_extend_measurement(uint8_t index,
const uint8_t *signer_id,
size_t signer_id_size,
const uint8_t *version,
size_t version_size,
uint32_t measurement_algo,
const uint8_t *sw_type,
size_t sw_type_size,
const uint8_t *measurement_value,
size_t measurement_value_size,
bool lock_measurement)
{
struct measured_boot_extend_iovec_t extend_iov = {
.index = index,
.lock_measurement = lock_measurement,
.measurement_algo = measurement_algo,
.sw_type = {0},
.sw_type_size = sw_type_size,
};
psa_invec in_vec[] = {
{.base = &extend_iov,
.len = sizeof(struct measured_boot_extend_iovec_t)},
{.base = signer_id, .len = signer_id_size},
{.base = version, .len = version_size},
{.base = measurement_value, .len = measurement_value_size}
};
uint32_t sw_type_size_limited;
if (sw_type != NULL) {
sw_type_size_limited = (sw_type_size < SW_TYPE_MAX_SIZE) ?
sw_type_size : SW_TYPE_MAX_SIZE;
memcpy(extend_iov.sw_type, sw_type, sw_type_size_limited);
}
log_measurement(index, signer_id, signer_id_size,
version, measurement_algo, sw_type,
measurement_value, measurement_value_size,
lock_measurement);
return psa_call(RSS_MEASURED_BOOT_HANDLE,
RSS_MEASURED_BOOT_EXTEND,
in_vec, IOVEC_LEN(in_vec),
NULL, 0);
}
#else /* !PLAT_RSS_NOT_SUPPORTED */
psa_status_t
rss_measured_boot_extend_measurement(uint8_t index,
const uint8_t *signer_id,
size_t signer_id_size,
const uint8_t *version,
size_t version_size,
uint32_t measurement_algo,
const uint8_t *sw_type,
size_t sw_type_size,
const uint8_t *measurement_value,
size_t measurement_value_size,
bool lock_measurement)
{
log_measurement(index, signer_id, signer_id_size,
version, measurement_algo, sw_type,
measurement_value, measurement_value_size,
lock_measurement);
return PSA_SUCCESS;
}
#endif /* !PLAT_RSS_NOT_SUPPORTED */

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef PSA_MEASURED_BOOT_PRIVATE_H
#define PSA_MEASURED_BOOT_PRIVATE_H
#include <stdint.h>
/* Measured boot message types that distinguish its services */
#define RSS_MEASURED_BOOT_EXTEND 1002U
struct measured_boot_extend_iovec_t {
uint8_t index;
uint8_t lock_measurement;
uint32_t measurement_algo;
uint8_t sw_type[SW_TYPE_MAX_SIZE];
uint8_t sw_type_size;
};
#endif /* PSA_MEASURED_BOOT_PRIVATE_H */

View File

@ -460,3 +460,6 @@ ENABLE_TRF_FOR_NS := 0
# SCR_EL3.TWEDEL(4bit) field, when FEAT_TWED is implemented.
# By default it takes 0, and need to be updated by the platforms.
TWED_DELAY := 0
# By default, disable the mocking of RSS provided services
PLAT_RSS_NOT_SUPPORTED := 0

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
* Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -7,6 +7,7 @@
#include <stdint.h>
#include <drivers/measured_boot/event_log/event_log.h>
#include <drivers/measured_boot/rss/rss_measured_boot.h>
#include <plat/arm/common/plat_arm.h>
/* Event Log data */
@ -21,10 +22,39 @@ const event_log_metadata_t fvp_event_log_metadata[] = {
{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
};
/* FVP table with platform specific image IDs and metadata. Intentionally not a
* const struct, some members might set by bootloaders during trusted boot.
*/
struct rss_mboot_metadata fvp_rss_mboot_metadata[] = {
{
.id = FW_CONFIG_ID,
.slot = U(6),
.signer_id_size = SIGNER_ID_MIN_SIZE,
.sw_type = RSS_MBOOT_FW_CONFIG_STRING,
.lock_measurement = true },
{
.id = TB_FW_CONFIG_ID,
.slot = U(7),
.signer_id_size = SIGNER_ID_MIN_SIZE,
.sw_type = RSS_MBOOT_TB_FW_CONFIG_STRING,
.lock_measurement = true },
{
.id = BL2_IMAGE_ID,
.slot = U(8),
.signer_id_size = SIGNER_ID_MIN_SIZE,
.sw_type = RSS_MBOOT_BL2_STRING,
.lock_measurement = true },
{
.id = RSS_MBOOT_INVALID_ID }
};
void bl1_plat_mboot_init(void)
{
event_log_init(event_log, event_log + sizeof(event_log));
event_log_write_header();
rss_measured_boot_init();
}
void bl1_plat_mboot_finish(void)

View File

@ -7,6 +7,7 @@
#include <stdint.h>
#include <drivers/measured_boot/event_log/event_log.h>
#include <drivers/measured_boot/rss/rss_measured_boot.h>
#include <tools_share/tbbr_oid.h>
#include <fvp_critical_data.h>
@ -35,6 +36,38 @@ const event_log_metadata_t fvp_event_log_metadata[] = {
{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
};
/* FVP table with platform specific image IDs and metadata. Intentionally not a
* const struct, some members might set by bootloaders during trusted boot.
*/
struct rss_mboot_metadata fvp_rss_mboot_metadata[] = {
{
.id = BL31_IMAGE_ID,
.slot = U(9),
.signer_id_size = SIGNER_ID_MIN_SIZE,
.sw_type = RSS_MBOOT_BL31_STRING,
.lock_measurement = true },
{
.id = HW_CONFIG_ID,
.slot = U(10),
.signer_id_size = SIGNER_ID_MIN_SIZE,
.sw_type = RSS_MBOOT_HW_CONFIG_STRING,
.lock_measurement = true },
{
.id = SOC_FW_CONFIG_ID,
.slot = U(11),
.signer_id_size = SIGNER_ID_MIN_SIZE,
.sw_type = RSS_MBOOT_SOC_FW_CONFIG_STRING,
.lock_measurement = true },
{
.id = RMM_IMAGE_ID,
.slot = U(12),
.signer_id_size = SIGNER_ID_MIN_SIZE,
.sw_type = RSS_MBOOT_RMM_STRING,
.lock_measurement = true },
{
.id = RSS_MBOOT_INVALID_ID }
};
void bl2_plat_mboot_init(void)
{
uint8_t *event_log_start;
@ -64,6 +97,8 @@ void bl2_plat_mboot_init(void)
PLAT_ARM_EVENT_LOG_MAX_SIZE);
event_log_init((uint8_t *)event_log_start, event_log_finish);
rss_measured_boot_init();
}
int plat_mboot_measure_critical_data(unsigned int critical_data_id,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
* Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -9,27 +9,47 @@
#include <common/desc_image_load.h>
#include <drivers/measured_boot/event_log/event_log.h>
#include <drivers/measured_boot/rss/rss_measured_boot.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
extern event_log_metadata_t fvp_event_log_metadata[];
extern struct rss_mboot_metadata fvp_rss_mboot_metadata[];
const event_log_metadata_t *plat_event_log_get_metadata(void)
{
return fvp_event_log_metadata;
}
struct rss_mboot_metadata *plat_rss_mboot_get_metadata(void)
{
return fvp_rss_mboot_metadata;
}
int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
{
int err;
int rc = 0;
/* Calculate image hash and record data in Event Log */
int err = event_log_measure_and_record(image_data->image_base,
image_data->image_size,
image_id);
err = event_log_measure_and_record(image_data->image_base,
image_data->image_size,
image_id);
if (err != 0) {
ERROR("%s%s image id %u (%i)\n",
"Failed to ", "record", image_id, err);
return err;
"Failed to ", "record in event log", image_id, err);
rc = err;
}
return 0;
/* Calculate image hash and record data in RSS */
err = rss_mboot_measure_and_record(image_data->image_base,
image_data->image_size,
image_id);
if (err != 0) {
ERROR("%s%s image id %u (%i)\n",
"Failed to ", "record in RSS", image_id, err);
rc = (rc == 0) ? err : -1;
}
return rc;
}

View File

@ -367,14 +367,36 @@ ifneq (${BL2_AT_EL3}, 0)
override BL1_SOURCES =
endif
# Include Measured Boot makefile before any Crypto library makefile.
# Crypto library makefile may need default definitions of Measured Boot build
# flags present in Measured Boot makefile.
ifeq (${MEASURED_BOOT},1)
RSS_MEASURED_BOOT_MK := drivers/measured_boot/rss/rss_measured_boot.mk
$(info Including ${RSS_MEASURED_BOOT_MK})
include ${RSS_MEASURED_BOOT_MK}
BL1_SOURCES += ${MEASURED_BOOT_SOURCES}
BL2_SOURCES += ${MEASURED_BOOT_SOURCES}
endif
include plat/arm/board/common/board_common.mk
include plat/arm/common/arm_common.mk
ifeq (${MEASURED_BOOT},1)
BL1_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \
plat/arm/board/fvp/fvp_bl1_measured_boot.c
plat/arm/board/fvp/fvp_bl1_measured_boot.c \
lib/psa/measured_boot.c
BL2_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \
plat/arm/board/fvp/fvp_bl2_measured_boot.c
plat/arm/board/fvp/fvp_bl2_measured_boot.c \
lib/psa/measured_boot.c
PLAT_INCLUDES += -Iinclude/lib/psa
# RSS is not supported on FVP right now. Thus, we use the mocked version
# of PSA Measured Boot APIs. They return with success and hard-coded data.
PLAT_RSS_NOT_SUPPORTED := 1
endif
ifeq (${TRUSTED_BOARD_BOOT}, 1)