1*0f9159b7SSoby Mathew /* 2*0f9159b7SSoby Mathew * Copyright (c) 2022, Arm Limited. All rights reserved. 3*0f9159b7SSoby Mathew * 4*0f9159b7SSoby Mathew * SPDX-License-Identifier: BSD-3-Clause 5*0f9159b7SSoby Mathew */ 6*0f9159b7SSoby Mathew #include <stdint.h> 7*0f9159b7SSoby Mathew #include <string.h> 8*0f9159b7SSoby Mathew #include <common/debug.h> 9*0f9159b7SSoby Mathew #include <lib/spinlock.h> 10*0f9159b7SSoby Mathew #include <lib/xlat_tables/xlat_tables_v2.h> 11*0f9159b7SSoby Mathew #include <plat/common/platform.h> 12*0f9159b7SSoby Mathew #include "rmmd_private.h" 13*0f9159b7SSoby Mathew #include <services/rmmd_svc.h> 14*0f9159b7SSoby Mathew 15*0f9159b7SSoby Mathew static spinlock_t lock; 16*0f9159b7SSoby Mathew 17*0f9159b7SSoby Mathew /* For printing Realm attestation token hash */ 18*0f9159b7SSoby Mathew #define DIGITS_PER_BYTE 2UL 19*0f9159b7SSoby Mathew #define LENGTH_OF_TERMINATING_ZERO_IN_BYTES 1UL 20*0f9159b7SSoby Mathew #define BYTES_PER_LINE_BASE 4UL 21*0f9159b7SSoby Mathew 22*0f9159b7SSoby Mathew static void print_challenge(uint8_t *hash, size_t hash_size) 23*0f9159b7SSoby Mathew { 24*0f9159b7SSoby Mathew size_t leftover; 25*0f9159b7SSoby Mathew /* 26*0f9159b7SSoby Mathew * bytes_per_line is always a power of two, so it can be used to 27*0f9159b7SSoby Mathew * construct mask with it when it is necessary to count remainder. 28*0f9159b7SSoby Mathew * 29*0f9159b7SSoby Mathew */ 30*0f9159b7SSoby Mathew const size_t bytes_per_line = 1 << BYTES_PER_LINE_BASE; 31*0f9159b7SSoby Mathew char hash_text[(1 << BYTES_PER_LINE_BASE) * DIGITS_PER_BYTE + 32*0f9159b7SSoby Mathew LENGTH_OF_TERMINATING_ZERO_IN_BYTES]; 33*0f9159b7SSoby Mathew const char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', 34*0f9159b7SSoby Mathew '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 35*0f9159b7SSoby Mathew unsigned int i; 36*0f9159b7SSoby Mathew 37*0f9159b7SSoby Mathew for (i = 0U; i < hash_size; ++i) { 38*0f9159b7SSoby Mathew hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE] = 39*0f9159b7SSoby Mathew hex_chars[hash[i] >> 4]; 40*0f9159b7SSoby Mathew hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE + 1] = 41*0f9159b7SSoby Mathew hex_chars[hash[i] & 0x0f]; 42*0f9159b7SSoby Mathew if (((i + 1) & (bytes_per_line - 1)) == 0U) { 43*0f9159b7SSoby Mathew hash_text[bytes_per_line * DIGITS_PER_BYTE] = '\0'; 44*0f9159b7SSoby Mathew VERBOSE("hash part %u = %s\n", 45*0f9159b7SSoby Mathew (i >> BYTES_PER_LINE_BASE) + 1, hash_text); 46*0f9159b7SSoby Mathew } 47*0f9159b7SSoby Mathew } 48*0f9159b7SSoby Mathew 49*0f9159b7SSoby Mathew leftover = (size_t)i & (bytes_per_line - 1); 50*0f9159b7SSoby Mathew 51*0f9159b7SSoby Mathew if (leftover != 0UL) { 52*0f9159b7SSoby Mathew hash_text[leftover * DIGITS_PER_BYTE] = '\0'; 53*0f9159b7SSoby Mathew VERBOSE("hash part %u = %s\n", (i >> BYTES_PER_LINE_BASE) + 1, 54*0f9159b7SSoby Mathew hash_text); 55*0f9159b7SSoby Mathew } 56*0f9159b7SSoby Mathew } 57*0f9159b7SSoby Mathew 58*0f9159b7SSoby Mathew /* 59*0f9159b7SSoby Mathew * TODO: Have different error codes for different errors so that the caller can 60*0f9159b7SSoby Mathew * differentiate various error cases. 61*0f9159b7SSoby Mathew */ 62*0f9159b7SSoby Mathew int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_len, uint64_t challenge_hash_len) 63*0f9159b7SSoby Mathew { 64*0f9159b7SSoby Mathew int err; 65*0f9159b7SSoby Mathew uintptr_t va; 66*0f9159b7SSoby Mathew uint8_t temp_buf[SHA512_DIGEST_SIZE]; 67*0f9159b7SSoby Mathew 68*0f9159b7SSoby Mathew /* 69*0f9159b7SSoby Mathew * TODO: Currently we don't validate incoming buf_pa. This is a 70*0f9159b7SSoby Mathew * prototype and we will need to allocate static buffer for EL3-RMM 71*0f9159b7SSoby Mathew * communication. 72*0f9159b7SSoby Mathew */ 73*0f9159b7SSoby Mathew 74*0f9159b7SSoby Mathew /* We need a page of buffer to pass data */ 75*0f9159b7SSoby Mathew if (*buf_len != PAGE_SIZE) { 76*0f9159b7SSoby Mathew ERROR("Invalid buffer length\n"); 77*0f9159b7SSoby Mathew return RMMD_ERR_INVAL; 78*0f9159b7SSoby Mathew } 79*0f9159b7SSoby Mathew 80*0f9159b7SSoby Mathew if ((challenge_hash_len != SHA256_DIGEST_SIZE) && 81*0f9159b7SSoby Mathew (challenge_hash_len != SHA384_DIGEST_SIZE) && 82*0f9159b7SSoby Mathew (challenge_hash_len != SHA512_DIGEST_SIZE)) { 83*0f9159b7SSoby Mathew ERROR("Invalid hash size: %lu\n", challenge_hash_len); 84*0f9159b7SSoby Mathew return RMMD_ERR_INVAL; 85*0f9159b7SSoby Mathew } 86*0f9159b7SSoby Mathew 87*0f9159b7SSoby Mathew spin_lock(&lock); 88*0f9159b7SSoby Mathew 89*0f9159b7SSoby Mathew /* Map the buffer that was provided by the RMM. */ 90*0f9159b7SSoby Mathew err = mmap_add_dynamic_region_alloc_va(buf_pa, &va, PAGE_SIZE, 91*0f9159b7SSoby Mathew MT_RW_DATA | MT_REALM); 92*0f9159b7SSoby Mathew if (err != 0) { 93*0f9159b7SSoby Mathew ERROR("mmap_add_dynamic_region_alloc_va failed: %d (%p).\n" 94*0f9159b7SSoby Mathew , err, (void *)buf_pa); 95*0f9159b7SSoby Mathew spin_unlock(&lock); 96*0f9159b7SSoby Mathew return RMMD_ERR_NOMEM; 97*0f9159b7SSoby Mathew } 98*0f9159b7SSoby Mathew 99*0f9159b7SSoby Mathew (void)memcpy(temp_buf, (void *)va, challenge_hash_len); 100*0f9159b7SSoby Mathew 101*0f9159b7SSoby Mathew print_challenge((uint8_t *)temp_buf, challenge_hash_len); 102*0f9159b7SSoby Mathew 103*0f9159b7SSoby Mathew /* Get the platform token. */ 104*0f9159b7SSoby Mathew err = plat_get_cca_attest_token(va, 105*0f9159b7SSoby Mathew buf_len, (uintptr_t)temp_buf, challenge_hash_len); 106*0f9159b7SSoby Mathew 107*0f9159b7SSoby Mathew if (err != 0) { 108*0f9159b7SSoby Mathew ERROR("Failed to get platform token: %d.\n", err); 109*0f9159b7SSoby Mathew err = RMMD_ERR_UNK; 110*0f9159b7SSoby Mathew } 111*0f9159b7SSoby Mathew 112*0f9159b7SSoby Mathew /* Unmap RMM memory. */ 113*0f9159b7SSoby Mathew (void)mmap_remove_dynamic_region(va, PAGE_SIZE); 114*0f9159b7SSoby Mathew spin_unlock(&lock); 115*0f9159b7SSoby Mathew 116*0f9159b7SSoby Mathew return err; 117*0f9159b7SSoby Mathew } 118*0f9159b7SSoby Mathew 119