From 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:13:47 +0200 Subject: Adding upstream version 2.8.0+dfsg. Signed-off-by: Daniel Baumann --- services/std_svc/rmmd/rmmd_attest.c | 153 ++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 services/std_svc/rmmd/rmmd_attest.c (limited to 'services/std_svc/rmmd/rmmd_attest.c') diff --git a/services/std_svc/rmmd/rmmd_attest.c b/services/std_svc/rmmd/rmmd_attest.c new file mode 100644 index 0000000..25adf50 --- /dev/null +++ b/services/std_svc/rmmd/rmmd_attest.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + +#include +#include +#include +#include +#include "rmmd_private.h" +#include + +static spinlock_t lock; + +/* For printing Realm attestation token hash */ +#define DIGITS_PER_BYTE 2UL +#define LENGTH_OF_TERMINATING_ZERO_IN_BYTES 1UL +#define BYTES_PER_LINE_BASE 4UL + +static void print_challenge(uint8_t *hash, size_t hash_size) +{ + size_t leftover; + /* + * bytes_per_line is always a power of two, so it can be used to + * construct mask with it when it is necessary to count remainder. + * + */ + const size_t bytes_per_line = 1 << BYTES_PER_LINE_BASE; + char hash_text[(1 << BYTES_PER_LINE_BASE) * DIGITS_PER_BYTE + + LENGTH_OF_TERMINATING_ZERO_IN_BYTES]; + const char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + unsigned int i; + + for (i = 0U; i < hash_size; ++i) { + hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE] = + hex_chars[hash[i] >> 4]; + hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE + 1] = + hex_chars[hash[i] & 0x0f]; + if (((i + 1) & (bytes_per_line - 1)) == 0U) { + hash_text[bytes_per_line * DIGITS_PER_BYTE] = '\0'; + VERBOSE("hash part %u = %s\n", + (i >> BYTES_PER_LINE_BASE) + 1, hash_text); + } + } + + leftover = (size_t)i & (bytes_per_line - 1); + + if (leftover != 0UL) { + hash_text[leftover * DIGITS_PER_BYTE] = '\0'; + VERBOSE("hash part %u = %s\n", (i >> BYTES_PER_LINE_BASE) + 1, + hash_text); + } +} + +/* + * Helper function to validate that the buffer base and length are + * within range. + */ +static int validate_buffer_params(uint64_t buf_pa, uint64_t buf_len) +{ + unsigned long shared_buf_page; + uintptr_t shared_buf_base; + + (void)plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base); + + shared_buf_page = shared_buf_base & ~PAGE_SIZE_MASK; + + /* Validate the buffer pointer */ + if ((buf_pa & ~PAGE_SIZE_MASK) != shared_buf_page) { + ERROR("Buffer PA out of range\n"); + return E_RMM_BAD_ADDR; + } + + /* Validate the size of the shared area */ + if (((buf_pa + buf_len - 1UL) & ~PAGE_SIZE_MASK) != shared_buf_page) { + ERROR("Invalid buffer length\n"); + return E_RMM_INVAL; + } + + return 0; /* No error */ +} + +int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size, + uint64_t c_size) +{ + int err; + uint8_t temp_buf[SHA512_DIGEST_SIZE]; + + err = validate_buffer_params(buf_pa, *buf_size); + if (err != 0) { + return err; + } + + if ((c_size != SHA256_DIGEST_SIZE) && + (c_size != SHA384_DIGEST_SIZE) && + (c_size != SHA512_DIGEST_SIZE)) { + ERROR("Invalid hash size: %lu\n", c_size); + return E_RMM_INVAL; + } + + spin_lock(&lock); + + (void)memcpy(temp_buf, (void *)buf_pa, c_size); + + print_challenge((uint8_t *)temp_buf, c_size); + + /* Get the platform token. */ + err = plat_rmmd_get_cca_attest_token((uintptr_t)buf_pa, + buf_size, (uintptr_t)temp_buf, c_size); + + if (err != 0) { + ERROR("Failed to get platform token: %d.\n", err); + err = E_RMM_UNK; + } + + spin_unlock(&lock); + + return err; +} + +int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size, + uint64_t ecc_curve) +{ + int err; + + err = validate_buffer_params(buf_pa, *buf_size); + if (err != 0) { + return err; + } + + if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) { + ERROR("Invalid ECC curve specified\n"); + return E_RMM_INVAL; + } + + spin_lock(&lock); + + /* Get the Realm attestation key. */ + err = plat_rmmd_get_cca_realm_attest_key((uintptr_t)buf_pa, buf_size, + (unsigned int)ecc_curve); + if (err != 0) { + ERROR("Failed to get attestation key: %d.\n", err); + err = E_RMM_UNK; + } + + spin_unlock(&lock); + + return err; +} -- cgit v1.2.3