1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2022, Arm Limited. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu #include <stdint.h> 7*91f16700Schasinglulu #include <string.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #include <lib/spinlock.h> 11*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h> 12*91f16700Schasinglulu #include <plat/common/platform.h> 13*91f16700Schasinglulu #include "rmmd_private.h" 14*91f16700Schasinglulu #include <services/rmmd_svc.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu static spinlock_t lock; 17*91f16700Schasinglulu 18*91f16700Schasinglulu /* For printing Realm attestation token hash */ 19*91f16700Schasinglulu #define DIGITS_PER_BYTE 2UL 20*91f16700Schasinglulu #define LENGTH_OF_TERMINATING_ZERO_IN_BYTES 1UL 21*91f16700Schasinglulu #define BYTES_PER_LINE_BASE 4UL 22*91f16700Schasinglulu 23*91f16700Schasinglulu static void print_challenge(uint8_t *hash, size_t hash_size) 24*91f16700Schasinglulu { 25*91f16700Schasinglulu size_t leftover; 26*91f16700Schasinglulu /* 27*91f16700Schasinglulu * bytes_per_line is always a power of two, so it can be used to 28*91f16700Schasinglulu * construct mask with it when it is necessary to count remainder. 29*91f16700Schasinglulu * 30*91f16700Schasinglulu */ 31*91f16700Schasinglulu const size_t bytes_per_line = 1 << BYTES_PER_LINE_BASE; 32*91f16700Schasinglulu char hash_text[(1 << BYTES_PER_LINE_BASE) * DIGITS_PER_BYTE + 33*91f16700Schasinglulu LENGTH_OF_TERMINATING_ZERO_IN_BYTES]; 34*91f16700Schasinglulu const char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', 35*91f16700Schasinglulu '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 36*91f16700Schasinglulu unsigned int i; 37*91f16700Schasinglulu 38*91f16700Schasinglulu for (i = 0U; i < hash_size; ++i) { 39*91f16700Schasinglulu hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE] = 40*91f16700Schasinglulu hex_chars[hash[i] >> 4]; 41*91f16700Schasinglulu hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE + 1] = 42*91f16700Schasinglulu hex_chars[hash[i] & 0x0f]; 43*91f16700Schasinglulu if (((i + 1) & (bytes_per_line - 1)) == 0U) { 44*91f16700Schasinglulu hash_text[bytes_per_line * DIGITS_PER_BYTE] = '\0'; 45*91f16700Schasinglulu VERBOSE("hash part %u = %s\n", 46*91f16700Schasinglulu (i >> BYTES_PER_LINE_BASE) + 1, hash_text); 47*91f16700Schasinglulu } 48*91f16700Schasinglulu } 49*91f16700Schasinglulu 50*91f16700Schasinglulu leftover = (size_t)i & (bytes_per_line - 1); 51*91f16700Schasinglulu 52*91f16700Schasinglulu if (leftover != 0UL) { 53*91f16700Schasinglulu hash_text[leftover * DIGITS_PER_BYTE] = '\0'; 54*91f16700Schasinglulu VERBOSE("hash part %u = %s\n", (i >> BYTES_PER_LINE_BASE) + 1, 55*91f16700Schasinglulu hash_text); 56*91f16700Schasinglulu } 57*91f16700Schasinglulu } 58*91f16700Schasinglulu 59*91f16700Schasinglulu /* 60*91f16700Schasinglulu * Helper function to validate that the buffer base and length are 61*91f16700Schasinglulu * within range. 62*91f16700Schasinglulu */ 63*91f16700Schasinglulu static int validate_buffer_params(uint64_t buf_pa, uint64_t buf_len) 64*91f16700Schasinglulu { 65*91f16700Schasinglulu unsigned long shared_buf_page; 66*91f16700Schasinglulu uintptr_t shared_buf_base; 67*91f16700Schasinglulu 68*91f16700Schasinglulu (void)plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base); 69*91f16700Schasinglulu 70*91f16700Schasinglulu shared_buf_page = shared_buf_base & ~PAGE_SIZE_MASK; 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* Validate the buffer pointer */ 73*91f16700Schasinglulu if ((buf_pa & ~PAGE_SIZE_MASK) != shared_buf_page) { 74*91f16700Schasinglulu ERROR("Buffer PA out of range\n"); 75*91f16700Schasinglulu return E_RMM_BAD_ADDR; 76*91f16700Schasinglulu } 77*91f16700Schasinglulu 78*91f16700Schasinglulu /* Validate the size of the shared area */ 79*91f16700Schasinglulu if (((buf_pa + buf_len - 1UL) & ~PAGE_SIZE_MASK) != shared_buf_page) { 80*91f16700Schasinglulu ERROR("Invalid buffer length\n"); 81*91f16700Schasinglulu return E_RMM_INVAL; 82*91f16700Schasinglulu } 83*91f16700Schasinglulu 84*91f16700Schasinglulu return 0; /* No error */ 85*91f16700Schasinglulu } 86*91f16700Schasinglulu 87*91f16700Schasinglulu int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size, 88*91f16700Schasinglulu uint64_t c_size) 89*91f16700Schasinglulu { 90*91f16700Schasinglulu int err; 91*91f16700Schasinglulu uint8_t temp_buf[SHA512_DIGEST_SIZE]; 92*91f16700Schasinglulu 93*91f16700Schasinglulu err = validate_buffer_params(buf_pa, *buf_size); 94*91f16700Schasinglulu if (err != 0) { 95*91f16700Schasinglulu return err; 96*91f16700Schasinglulu } 97*91f16700Schasinglulu 98*91f16700Schasinglulu if ((c_size != SHA256_DIGEST_SIZE) && 99*91f16700Schasinglulu (c_size != SHA384_DIGEST_SIZE) && 100*91f16700Schasinglulu (c_size != SHA512_DIGEST_SIZE)) { 101*91f16700Schasinglulu ERROR("Invalid hash size: %lu\n", c_size); 102*91f16700Schasinglulu return E_RMM_INVAL; 103*91f16700Schasinglulu } 104*91f16700Schasinglulu 105*91f16700Schasinglulu spin_lock(&lock); 106*91f16700Schasinglulu 107*91f16700Schasinglulu (void)memcpy(temp_buf, (void *)buf_pa, c_size); 108*91f16700Schasinglulu 109*91f16700Schasinglulu print_challenge((uint8_t *)temp_buf, c_size); 110*91f16700Schasinglulu 111*91f16700Schasinglulu /* Get the platform token. */ 112*91f16700Schasinglulu err = plat_rmmd_get_cca_attest_token((uintptr_t)buf_pa, 113*91f16700Schasinglulu buf_size, (uintptr_t)temp_buf, c_size); 114*91f16700Schasinglulu 115*91f16700Schasinglulu if (err != 0) { 116*91f16700Schasinglulu ERROR("Failed to get platform token: %d.\n", err); 117*91f16700Schasinglulu err = E_RMM_UNK; 118*91f16700Schasinglulu } 119*91f16700Schasinglulu 120*91f16700Schasinglulu spin_unlock(&lock); 121*91f16700Schasinglulu 122*91f16700Schasinglulu return err; 123*91f16700Schasinglulu } 124*91f16700Schasinglulu 125*91f16700Schasinglulu int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size, 126*91f16700Schasinglulu uint64_t ecc_curve) 127*91f16700Schasinglulu { 128*91f16700Schasinglulu int err; 129*91f16700Schasinglulu 130*91f16700Schasinglulu err = validate_buffer_params(buf_pa, *buf_size); 131*91f16700Schasinglulu if (err != 0) { 132*91f16700Schasinglulu return err; 133*91f16700Schasinglulu } 134*91f16700Schasinglulu 135*91f16700Schasinglulu if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) { 136*91f16700Schasinglulu ERROR("Invalid ECC curve specified\n"); 137*91f16700Schasinglulu return E_RMM_INVAL; 138*91f16700Schasinglulu } 139*91f16700Schasinglulu 140*91f16700Schasinglulu spin_lock(&lock); 141*91f16700Schasinglulu 142*91f16700Schasinglulu /* Get the Realm attestation key. */ 143*91f16700Schasinglulu err = plat_rmmd_get_cca_realm_attest_key((uintptr_t)buf_pa, buf_size, 144*91f16700Schasinglulu (unsigned int)ecc_curve); 145*91f16700Schasinglulu if (err != 0) { 146*91f16700Schasinglulu ERROR("Failed to get attestation key: %d.\n", err); 147*91f16700Schasinglulu err = E_RMM_UNK; 148*91f16700Schasinglulu } 149*91f16700Schasinglulu 150*91f16700Schasinglulu spin_unlock(&lock); 151*91f16700Schasinglulu 152*91f16700Schasinglulu return err; 153*91f16700Schasinglulu } 154