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
print_challenge(uint8_t * hash,size_t hash_size)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 */
validate_buffer_params(uint64_t buf_pa,uint64_t buf_len)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
rmmd_attest_get_platform_token(uint64_t buf_pa,uint64_t * buf_size,uint64_t c_size,uint64_t * remaining_len)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
rmmd_attest_get_signing_key(uint64_t buf_pa,uint64_t * buf_size,uint64_t ecc_curve)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
rmmd_el3_token_sign_push_req(uint64_t buf_pa,uint64_t buf_size)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
rmmd_el3_token_sign_pull_resp(uint64_t buf_pa,uint64_t buf_size)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
rmmd_attest_get_attest_pub_key(uint64_t buf_pa,uint64_t * buf_size,uint64_t ecc_curve)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
rmmd_el3_token_sign(void * handle,uint64_t opcode,uint64_t x2,uint64_t x3,uint64_t x4)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