mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-26 14:55:16 +00:00
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:
commit
6aed554954
25 changed files with 2186 additions and 10 deletions
2
Makefile
2
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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
379
drivers/arm/mhu/mhu_v2_x.c
Normal 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
210
drivers/arm/mhu/mhu_v2_x.h
Normal 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 */
|
302
drivers/arm/mhu/mhu_wrapper_v2_x.c
Normal file
302
drivers/arm/mhu/mhu_wrapper_v2_x.c
Normal 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
225
drivers/arm/rss/rss_comms.c
Normal 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;
|
||||
}
|
125
drivers/measured_boot/rss/rss_measured_boot.c
Normal file
125
drivers/measured_boot/rss/rss_measured_boot.c
Normal 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;
|
||||
}
|
35
drivers/measured_boot/rss/rss_measured_boot.mk
Normal file
35
drivers/measured_boot/rss/rss_measured_boot.mk
Normal 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
79
include/drivers/arm/mhu.h
Normal 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 */
|
15
include/drivers/arm/rss_comms.h
Normal file
15
include/drivers/arm/rss_comms.h
Normal 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 */
|
55
include/drivers/measured_boot/rss/rss_measured_boot.h
Normal file
55
include/drivers/measured_boot/rss/rss_measured_boot.h
Normal 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 */
|
54
include/lib/psa/initial_attestation.h
Normal file
54
include/lib/psa/initial_attestation.h
Normal 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 */
|
77
include/lib/psa/measured_boot.h
Normal file
77
include/lib/psa/measured_boot.h
Normal 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 */
|
102
include/lib/psa/psa/client.h
Normal file
102
include/lib/psa/psa/client.h
Normal 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 */
|
42
include/lib/psa/psa/error.h
Normal file
42
include/lib/psa/psa/error.h
Normal 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 */
|
21
include/lib/psa/psa_manifest/sid.h
Normal file
21
include/lib/psa/psa_manifest/sid.h
Normal 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 */
|
163
lib/psa/initial_attestation.c
Normal file
163
lib/psa/initial_attestation.c
Normal 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
129
lib/psa/measured_boot.c
Normal 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 */
|
24
lib/psa/measured_boot_private.h
Normal file
24
lib/psa/measured_boot_private.h
Normal 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 */
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue