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