• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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