1 /* 2 * Copyright (c) 2022-2024, Arm Limited. All rights reserved. 3 * Copyright (c) 2024, NVIDIA Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 #include <errno.h> 8 #include <stdint.h> 9 #include <string.h> 10 11 #include <common/debug.h> 12 #include <lib/spinlock.h> 13 #include <lib/xlat_tables/xlat_tables_v2.h> 14 #include <plat/common/platform.h> 15 #include "rmmd_private.h" 16 #include <services/rmm_el3_token_sign.h> 17 #include <smccc_helpers.h> 18 19 static spinlock_t lock; 20 21 /* For printing Realm attestation token hash */ 22 #define DIGITS_PER_BYTE 2UL 23 #define LENGTH_OF_TERMINATING_ZERO_IN_BYTES 1UL 24 #define BYTES_PER_LINE_BASE 4UL 25 26 static void print_challenge(uint8_t *hash, size_t hash_size) 27 { 28 size_t leftover; 29 /* 30 * bytes_per_line is always a power of two, so it can be used to 31 * construct mask with it when it is necessary to count remainder. 32 * 33 */ 34 const size_t bytes_per_line = 1 << BYTES_PER_LINE_BASE; 35 char hash_text[(1 << BYTES_PER_LINE_BASE) * DIGITS_PER_BYTE + 36 LENGTH_OF_TERMINATING_ZERO_IN_BYTES]; 37 const char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', 38 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 39 unsigned int i; 40 41 for (i = 0U; i < hash_size; ++i) { 42 hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE] = 43 hex_chars[hash[i] >> 4]; 44 hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE + 1] = 45 hex_chars[hash[i] & 0x0f]; 46 if (((i + 1) & (bytes_per_line - 1)) == 0U) { 47 hash_text[bytes_per_line * DIGITS_PER_BYTE] = '\0'; 48 VERBOSE("hash part %u = %s\n", 49 (i >> BYTES_PER_LINE_BASE) + 1, hash_text); 50 } 51 } 52 53 leftover = (size_t)i & (bytes_per_line - 1); 54 55 if (leftover != 0UL) { 56 hash_text[leftover * DIGITS_PER_BYTE] = '\0'; 57 VERBOSE("hash part %u = %s\n", (i >> BYTES_PER_LINE_BASE) + 1, 58 hash_text); 59 } 60 } 61 62 /* 63 * Helper function to validate that the buffer base and length are 64 * within range. 65 */ 66 static int validate_buffer_params(uint64_t buf_pa, uint64_t buf_len) 67 { 68 unsigned long shared_buf_page; 69 uintptr_t shared_buf_base; 70 71 (void)plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base); 72 73 shared_buf_page = shared_buf_base & ~PAGE_SIZE_MASK; 74 75 /* Validate the buffer pointer */ 76 if ((buf_pa & ~PAGE_SIZE_MASK) != shared_buf_page) { 77 ERROR("Buffer PA out of range\n"); 78 return E_RMM_BAD_ADDR; 79 } 80 81 /* Validate the size of the shared area */ 82 if (((buf_pa + buf_len - 1UL) & ~PAGE_SIZE_MASK) != shared_buf_page) { 83 ERROR("Invalid buffer length\n"); 84 return E_RMM_INVAL; 85 } 86 87 return 0; /* No error */ 88 } 89 90 int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size, 91 uint64_t c_size, 92 uint64_t *remaining_len) 93 { 94 int err; 95 uint8_t temp_buf[SHA512_DIGEST_SIZE]; 96 97 err = validate_buffer_params(buf_pa, *buf_size); 98 if (err != 0) { 99 return err; 100 } 101 102 if ((c_size != SHA256_DIGEST_SIZE) && 103 (c_size != SHA384_DIGEST_SIZE) && 104 (c_size != SHA512_DIGEST_SIZE)) { 105 ERROR("Invalid hash size: %lu\n", c_size); 106 return E_RMM_INVAL; 107 } 108 109 spin_lock(&lock); 110 111 (void)memcpy(temp_buf, (void *)buf_pa, c_size); 112 113 print_challenge((uint8_t *)temp_buf, c_size); 114 115 /* Get the platform token. */ 116 err = plat_rmmd_get_cca_attest_token((uintptr_t)buf_pa, 117 buf_size, (uintptr_t)temp_buf, c_size, remaining_len); 118 119 switch (err) { 120 case 0: 121 err = E_RMM_OK; 122 break; 123 case -EAGAIN: 124 err = E_RMM_AGAIN; 125 break; 126 case -EINVAL: 127 err = E_RMM_INVAL; 128 break; 129 default: 130 ERROR("Failed to get platform token: %d.\n", err); 131 err = E_RMM_UNK; 132 } 133 134 spin_unlock(&lock); 135 136 return err; 137 } 138 139 int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size, 140 uint64_t ecc_curve) 141 { 142 int err; 143 144 err = validate_buffer_params(buf_pa, *buf_size); 145 if (err != 0) { 146 return err; 147 } 148 149 if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) { 150 ERROR("Invalid ECC curve specified\n"); 151 return E_RMM_INVAL; 152 } 153 154 spin_lock(&lock); 155 156 /* Get the Realm attestation key. */ 157 err = plat_rmmd_get_cca_realm_attest_key((uintptr_t)buf_pa, buf_size, 158 (unsigned int)ecc_curve); 159 if (err != 0) { 160 ERROR("Failed to get attestation key: %d.\n", err); 161 err = E_RMM_UNK; 162 } 163 164 spin_unlock(&lock); 165 166 return err; 167 } 168 169 static int rmmd_el3_token_sign_push_req(uint64_t buf_pa, uint64_t buf_size) 170 { 171 int err; 172 173 err = validate_buffer_params(buf_pa, buf_size); 174 if (err != 0) { 175 return err; 176 } 177 178 if (buf_size < sizeof(struct el3_token_sign_request)) { 179 return E_RMM_INVAL; 180 } 181 182 spin_lock(&lock); 183 184 /* Call platform port to handle attestation toekn signing request. */ 185 err = plat_rmmd_el3_token_sign_push_req((struct el3_token_sign_request *)buf_pa); 186 187 spin_unlock(&lock); 188 189 return err; 190 } 191 192 static int rmmd_el3_token_sign_pull_resp(uint64_t buf_pa, uint64_t buf_size) 193 { 194 int err; 195 196 err = validate_buffer_params(buf_pa, buf_size); 197 if (err != 0) { 198 return err; 199 } 200 201 202 if (buf_size < sizeof(struct el3_token_sign_response)) { 203 return E_RMM_INVAL; 204 } 205 206 spin_lock(&lock); 207 208 /* Pull attestation signing response from HES. */ 209 err = plat_rmmd_el3_token_sign_pull_resp( 210 (struct el3_token_sign_response *)buf_pa); 211 212 spin_unlock(&lock); 213 214 return err; 215 } 216 217 static int rmmd_attest_get_attest_pub_key(uint64_t buf_pa, uint64_t *buf_size, 218 uint64_t ecc_curve) 219 { 220 int err; 221 222 err = validate_buffer_params(buf_pa, *buf_size); 223 if (err != 0) { 224 return err; 225 } 226 227 if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) { 228 ERROR("Invalid ECC curve specified\n"); 229 return E_RMM_INVAL; 230 } 231 232 spin_lock(&lock); 233 234 /* Get the Realm attestation public key from platform port. */ 235 err = plat_rmmd_el3_token_sign_get_rak_pub( 236 (uintptr_t)buf_pa, buf_size, (unsigned int)ecc_curve); 237 238 spin_unlock(&lock); 239 if (err != 0) { 240 ERROR("Failed to get attestation public key from HES: %d.\n", 241 err); 242 err = E_RMM_UNK; 243 } 244 245 246 return err; 247 } 248 249 uint64_t rmmd_el3_token_sign(void *handle, uint64_t opcode, uint64_t x2, 250 uint64_t x3, uint64_t x4) 251 { 252 int ret; 253 254 switch (opcode) { 255 case RMM_EL3_TOKEN_SIGN_PUSH_REQ_OP: 256 ret = rmmd_el3_token_sign_push_req(x2, x3); 257 SMC_RET1(handle, ret); 258 case RMM_EL3_TOKEN_SIGN_PULL_RESP_OP: 259 ret = rmmd_el3_token_sign_pull_resp(x2, x3); 260 SMC_RET1(handle, ret); 261 case RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP: 262 ret = rmmd_attest_get_attest_pub_key(x2, &x3, x4); 263 SMC_RET2(handle, ret, x3); 264 default: 265 SMC_RET1(handle, SMC_UNK); 266 } 267 } 268