blob: 7d4ea701c6efaea34c3318825933ec44154f1818 [file] [log] [blame]
Soby Mathew294e1cf2022-03-22 16:19:39 +00001/*
Juan Pablo Conde9b94a422024-07-10 14:33:42 -05002 * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
Raghu Krishnamurthyc11b60e2024-06-03 19:02:29 -07003 * Copyright (c) 2024, NVIDIA Corporation. All rights reserved.
Soby Mathew294e1cf2022-03-22 16:19:39 +00004 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
Juan Pablo Conde9b94a422024-07-10 14:33:42 -05007#include <errno.h>
Soby Mathew294e1cf2022-03-22 16:19:39 +00008#include <stdint.h>
9#include <string.h>
Javier Almansa Sobrino4165e842022-04-25 17:18:15 +010010
Soby Mathew294e1cf2022-03-22 16:19:39 +000011#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"
Raghu Krishnamurthyc11b60e2024-06-03 19:02:29 -070016#include <services/rmm_el3_token_sign.h>
17#include <smccc_helpers.h>
Soby Mathew294e1cf2022-03-22 16:19:39 +000018
19static 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
26static 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/*
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010063 * Helper function to validate that the buffer base and length are
64 * within range.
Soby Mathew294e1cf2022-03-22 16:19:39 +000065 */
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010066static int validate_buffer_params(uint64_t buf_pa, uint64_t buf_len)
Soby Mathew294e1cf2022-03-22 16:19:39 +000067{
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010068 unsigned long shared_buf_page;
69 uintptr_t shared_buf_base;
Soby Mathew294e1cf2022-03-22 16:19:39 +000070
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010071 (void)plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base);
Soby Mathew294e1cf2022-03-22 16:19:39 +000072
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010073 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;
Soby Mathew294e1cf2022-03-22 16:19:39 +000079 }
80
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010081 /* 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;
Soby Mathew294e1cf2022-03-22 16:19:39 +000085 }
86
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010087 return 0; /* No error */
88}
89
90int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size,
Juan Pablo Conde9b94a422024-07-10 14:33:42 -050091 uint64_t c_size,
92 uint64_t *remaining_len)
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010093{
94 int err;
95 uint8_t temp_buf[SHA512_DIGEST_SIZE];
Soby Mathew294e1cf2022-03-22 16:19:39 +000096
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010097 err = validate_buffer_params(buf_pa, *buf_size);
Soby Mathew294e1cf2022-03-22 16:19:39 +000098 if (err != 0) {
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010099 return err;
Soby Mathew294e1cf2022-03-22 16:19:39 +0000100 }
101
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100102 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);
Soby Mathew294e1cf2022-03-22 16:19:39 +0000110
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100111 (void)memcpy(temp_buf, (void *)buf_pa, c_size);
112
113 print_challenge((uint8_t *)temp_buf, c_size);
Soby Mathew294e1cf2022-03-22 16:19:39 +0000114
115 /* Get the platform token. */
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100116 err = plat_rmmd_get_cca_attest_token((uintptr_t)buf_pa,
Juan Pablo Conde9b94a422024-07-10 14:33:42 -0500117 buf_size, (uintptr_t)temp_buf, c_size, remaining_len);
Soby Mathew294e1cf2022-03-22 16:19:39 +0000118
Juan Pablo Conde9b94a422024-07-10 14:33:42 -0500119 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:
Soby Mathew294e1cf2022-03-22 16:19:39 +0000130 ERROR("Failed to get platform token: %d.\n", err);
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100131 err = E_RMM_UNK;
Soby Mathew294e1cf2022-03-22 16:19:39 +0000132 }
133
Soby Mathew294e1cf2022-03-22 16:19:39 +0000134 spin_unlock(&lock);
135
136 return err;
137}
138
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100139int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size,
Soby Mathewf05d93a2022-03-22 16:21:19 +0000140 uint64_t ecc_curve)
141{
142 int err;
Soby Mathewf05d93a2022-03-22 16:21:19 +0000143
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100144 err = validate_buffer_params(buf_pa, *buf_size);
145 if (err != 0) {
146 return err;
Soby Mathewf05d93a2022-03-22 16:21:19 +0000147 }
148
149 if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) {
150 ERROR("Invalid ECC curve specified\n");
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100151 return E_RMM_INVAL;
Soby Mathewf05d93a2022-03-22 16:21:19 +0000152 }
153
154 spin_lock(&lock);
155
Soby Mathewf05d93a2022-03-22 16:21:19 +0000156 /* Get the Realm attestation key. */
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100157 err = plat_rmmd_get_cca_realm_attest_key((uintptr_t)buf_pa, buf_size,
158 (unsigned int)ecc_curve);
Soby Mathewf05d93a2022-03-22 16:21:19 +0000159 if (err != 0) {
160 ERROR("Failed to get attestation key: %d.\n", err);
Raghu Krishnamurthyc11b60e2024-06-03 19:02:29 -0700161 err = E_RMM_UNK;
Soby Mathewf05d93a2022-03-22 16:21:19 +0000162 }
163
Soby Mathewf05d93a2022-03-22 16:21:19 +0000164 spin_unlock(&lock);
165
166 return err;
167}
Raghu Krishnamurthyc11b60e2024-06-03 19:02:29 -0700168
169static 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
192static 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
217static 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
249uint64_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}