diff --git a/Makefile b/Makefile index 16c85bcd2..b42bdc537 100644 --- a/Makefile +++ b/Makefile @@ -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 \ diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst index b9b58782c..c62a6beb2 100644 --- a/docs/about/maintainers.rst +++ b/docs/about/maintainers.rst @@ -293,6 +293,20 @@ GIC driver :|G|: `odeprez`_ :|F|: drivers/arm/gic/ +Message Handling Unit (MHU) driver +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: David Vincze +:|G|: `davidvincze`_ +:|F|: include/drivers/arm/mhu.h +:|F|: drivers/arm/mhu + +Runtime Security Subsystem (RSS) comms driver +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: David Vincze +:|G|: `davidvincze`_ +:|F|: include/drivers/arm/rss_comms.h +:|F|: drivers/arm/rss + Libfdt wrappers ^^^^^^^^^^^^^^^ :|M|: Madhukar Pappireddy @@ -331,6 +345,13 @@ PSA Firmware Update :|F|: drivers/fwu :|F|: include/drivers/fwu +Platform Security Architecture (PSA) APIs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Sandrine Bailleux +:|G|: `sandrine-bailleux-arm`_ +:|F|: include/lib/psa +:|F|: lib/psa + System Control and Management Interface (SCMI) Server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :|M|: Etienne Carriere @@ -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 diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index d2cda4dcc..742b6b589 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -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 -------------------- diff --git a/drivers/arm/mhu/mhu_v2_x.c b/drivers/arm/mhu/mhu_v2_x.c new file mode 100644 index 000000000..3103b9243 --- /dev/null +++ b/drivers/arm/mhu/mhu_v2_x.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#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; +} diff --git a/drivers/arm/mhu/mhu_v2_x.h b/drivers/arm/mhu/mhu_v2_x.h new file mode 100644 index 000000000..10247d24f --- /dev/null +++ b/drivers/arm/mhu/mhu_v2_x.h @@ -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 +#include + +#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 */ diff --git a/drivers/arm/mhu/mhu_wrapper_v2_x.c b/drivers/arm/mhu/mhu_wrapper_v2_x.c new file mode 100644 index 000000000..d8b7cfdab --- /dev/null +++ b/drivers/arm/mhu/mhu_wrapper_v2_x.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#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; +} diff --git a/drivers/arm/rss/rss_comms.c b/drivers/arm/rss/rss_comms.c new file mode 100644 index 000000000..28a492567 --- /dev/null +++ b/drivers/arm/rss/rss_comms.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#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; +} diff --git a/drivers/measured_boot/rss/rss_measured_boot.c b/drivers/measured_boot/rss/rss_measured_boot.c new file mode 100644 index 000000000..fe2baf055 --- /dev/null +++ b/drivers/measured_boot/rss/rss_measured_boot.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/drivers/measured_boot/rss/rss_measured_boot.mk b/drivers/measured_boot/rss/rss_measured_boot.mk new file mode 100644 index 000000000..01545afeb --- /dev/null +++ b/drivers/measured_boot/rss/rss_measured_boot.mk @@ -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 diff --git a/include/drivers/arm/mhu.h b/include/drivers/arm/mhu.h new file mode 100644 index 000000000..7745bd9d8 --- /dev/null +++ b/include/drivers/arm/mhu.h @@ -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 +#include + +/** + * 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 */ diff --git a/include/drivers/arm/rss_comms.h b/include/drivers/arm/rss_comms.h new file mode 100644 index 000000000..b96c79f7c --- /dev/null +++ b/include/drivers/arm/rss_comms.h @@ -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 + +int rss_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base); + +#endif /* RSS_COMMS_H */ diff --git a/include/drivers/measured_boot/rss/rss_measured_boot.h b/include/drivers/measured_boot/rss/rss_measured_boot.h new file mode 100644 index 000000000..fe885765c --- /dev/null +++ b/include/drivers/measured_boot/rss/rss_measured_boot.h @@ -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 + +#include +#include + +#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 */ diff --git a/include/lib/psa/initial_attestation.h b/include/lib/psa/initial_attestation.h new file mode 100644 index 000000000..93169f018 --- /dev/null +++ b/include/lib/psa/initial_attestation.h @@ -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 +#include +#include + +#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 */ diff --git a/include/lib/psa/measured_boot.h b/include/lib/psa/measured_boot.h new file mode 100644 index 000000000..bdb79d5d6 --- /dev/null +++ b/include/lib/psa/measured_boot.h @@ -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 +#include +#include + +#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 */ diff --git a/include/lib/psa/psa/client.h b/include/lib/psa/psa/client.h new file mode 100644 index 000000000..56fe0288f --- /dev/null +++ b/include/lib/psa/psa/client.h @@ -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 +#include + +#include + +#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 */ diff --git a/include/lib/psa/psa/error.h b/include/lib/psa/psa/error.h new file mode 100644 index 000000000..8a6eb7be7 --- /dev/null +++ b/include/lib/psa/psa/error.h @@ -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 + +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 */ diff --git a/include/lib/psa/psa_manifest/sid.h b/include/lib/psa/psa_manifest/sid.h new file mode 100644 index 000000000..947e58f09 --- /dev/null +++ b/include/lib/psa/psa_manifest/sid.h @@ -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 */ diff --git a/lib/psa/initial_attestation.c b/lib/psa/initial_attestation.c new file mode 100644 index 000000000..44498a857 --- /dev/null +++ b/lib/psa/initial_attestation.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2018-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#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 + +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 */ diff --git a/lib/psa/measured_boot.c b/lib/psa/measured_boot.c new file mode 100644 index 000000000..5d3ca8ed2 --- /dev/null +++ b/lib/psa/measured_boot.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include + +#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 */ diff --git a/lib/psa/measured_boot_private.h b/lib/psa/measured_boot_private.h new file mode 100644 index 000000000..649c3f6a4 --- /dev/null +++ b/lib/psa/measured_boot_private.h @@ -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 + +/* 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 */ diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 6e572377b..d5383a10f 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -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 diff --git a/plat/arm/board/fvp/fvp_bl1_measured_boot.c b/plat/arm/board/fvp/fvp_bl1_measured_boot.c index 546855527..76cd91824 100644 --- a/plat/arm/board/fvp/fvp_bl1_measured_boot.c +++ b/plat/arm/board/fvp/fvp_bl1_measured_boot.c @@ -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 #include +#include #include /* 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) diff --git a/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/plat/arm/board/fvp/fvp_bl2_measured_boot.c index 1f3827831..fd15b70d3 100644 --- a/plat/arm/board/fvp/fvp_bl2_measured_boot.c +++ b/plat/arm/board/fvp/fvp_bl2_measured_boot.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -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, diff --git a/plat/arm/board/fvp/fvp_common_measured_boot.c b/plat/arm/board/fvp/fvp_common_measured_boot.c index 6a403d945..93aa0558c 100644 --- a/plat/arm/board/fvp/fvp_common_measured_boot.c +++ b/plat/arm/board/fvp/fvp_common_measured_boot.c @@ -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 #include +#include #include #include 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; } diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index d89e91f71..89ca18540 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -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)