Browse Source
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: I2448e324e7ece6b318403c5937dfe7abea53d0f3pull/1985/head
Tamas Ban
3 years ago
committed by
David Vincze
6 changed files with 370 additions and 0 deletions
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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); |
|||
} |
@ -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…
Reference in new issue