mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-23 21:44:15 +00:00
feat(lib/psa): add measured boot API
A secure enclave could provide an alternate backend for measured boot. This API can be used to store measurements in a secure enclave, which provides the measured boot runtime service. Signed-off-by: Tamas Ban <tamas.ban@arm.com> Change-Id: I2448e324e7ece6b318403c5937dfe7abea53d0f3
This commit is contained in:
parent
af26d7d6f0
commit
758c64715b
6 changed files with 370 additions and 0 deletions
include/lib/psa
lib/psa
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 */
|
104
lib/psa/measured_boot.c
Normal file
104
lib/psa/measured_boot.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
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 */
|
Loading…
Add table
Reference in a new issue