1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #include <assert.h>
7 #include <attestation.h>
8 #include <attestation_priv.h>
9 #include <debug.h>
10 #include <errno.h>
11 #include <fpu_helpers.h>
12 #include <mbedtls/sha256.h>
13 #include <measurement.h>
14 #include <psa/crypto.h>
15 #include <rmm_el3_ifc.h>
16 #include <sizes.h>
17 
18 #define ECC_P384_PUBLIC_KEY_SIZE	(97U)
19 #define SHA256_DIGEST_SIZE		(32U)
20 
21 /*
22  * The size of X and Y coordinate in 2 parameter style EC public key. Format is
23  * as defined in [COSE (RFC 8152)] (https://tools.ietf.org/html/rfc8152) and
24  * [SEC 1: Elliptic Curve Cryptography](http://www.secg.org/sec1-v2.pdf).
25  *
26  * This size is well-known and documented in public standards.
27  */
28 #define ECC_P384_COORD_SIZE		(48U) /* 384 bits -> 48 bytes */
29 #define BIT_SIZE_OF_P384		(384U)
30 
31 /* ECC Curve type define for querying attestation key from monitor */
32 #define ATTEST_KEY_CURVE_ECC_SECP384R1	0
33 
34 /*
35  * The platform token which will be needed during attestation.
36  */
37 static unsigned char rmm_platform_token_buf[SZ_4K];
38 static struct q_useful_buf rmm_platform_token;
39 
40 /*
41  * The public key is kept loaded as it is both not required to be secret (and
42  * hence can be kept in attestation memory) and immutable.
43  */
44 static uint8_t realm_attest_public_key[ECC_P384_PUBLIC_KEY_SIZE];
45 static size_t realm_attest_public_key_len;
46 
47 /*
48  * The hash of the realm attestation public key is included in the Platform
49  * attestation token as the challenge claim.
50  */
51 static uint8_t realm_attest_public_key_hash[SHA256_DIGEST_SIZE];
52 static size_t realm_attest_public_key_hash_len;
53 
54 /*
55  * The keypair for the sign operation
56  */
57 static mbedtls_ecp_keypair realm_attest_keypair = {0};
58 
59 /* Specify the hash algorithm to use for computing the hash of the
60  * realm public key.
61  */
62 static enum hash_algo public_key_hash_algo_id = HASH_ALGO_SHA256;
63 
64 /*
65  * TODO: review panic usage and try to gracefully exit on error. Also
66  * improve documentation of usage of MbedTLS APIs
67  */
attest_init_realm_attestation_key(void)68 int attest_init_realm_attestation_key(void)
69 {
70 	int ret;
71 	struct q_useful_buf realm_attest_private_key;
72 	uintptr_t buf;
73 	size_t attest_key_size = 0UL;
74 
75 	struct attest_rng_context rng_ctx;
76 
77 	assert(IS_FPU_ALLOWED());
78 
79 	attest_get_cpu_rng_context(&rng_ctx);
80 
81 	/*
82 	 * The realm attestation key is requested from the root world in the
83 	 * boot phase only once. Then the same key is used in the entire power
84 	 * cycle to sign the realm attestation tokens.
85 	 */
86 	if (realm_attest_keypair.MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(p) != NULL) {
87 		ERROR("Realm attestation key already loaded.\n");
88 		return -EINVAL;
89 	}
90 
91 	/*
92 	 * Get the realm attestation key. The key is retrieved in raw format.
93 	 */
94 	buf = rmm_el3_ifc_get_shared_buf_locked();
95 
96 	if (rmm_el3_ifc_get_realm_attest_key(buf,
97 				rmm_el3_ifc_get_shared_buf_size(),
98 				&attest_key_size,
99 				ATTEST_KEY_CURVE_ECC_SECP384R1) != 0) {
100 		rmm_el3_ifc_release_shared_buf();
101 		return -EINVAL;
102 	}
103 
104 	realm_attest_private_key.len = attest_key_size;
105 	realm_attest_private_key.ptr = (void *)buf;
106 
107 	/*
108 	 * Setup ECC key.
109 	 * The memory for the keypair is allocated from MbedTLS Heap.
110 	 */
111 	mbedtls_ecp_keypair_init(&realm_attest_keypair);
112 	ret = mbedtls_ecp_group_load(&realm_attest_keypair.MBEDTLS_PRIVATE(grp),
113 				     MBEDTLS_ECP_DP_SECP384R1);
114 	if (ret != 0) {
115 		ERROR("mbedtls_ecp_group_load has failed\n");
116 		rmm_el3_ifc_release_shared_buf();
117 		return -EINVAL;
118 	}
119 
120 	ret = mbedtls_mpi_read_binary(&realm_attest_keypair.MBEDTLS_PRIVATE(d),
121 				      realm_attest_private_key.ptr,
122 				      realm_attest_private_key.len);
123 	if (ret != 0) {
124 		ERROR("mbedtls_mpi_read_binary has failed\n");
125 		rmm_el3_ifc_release_shared_buf();
126 		return -EINVAL;
127 	}
128 
129 	ret = mbedtls_ecp_check_privkey(&realm_attest_keypair.MBEDTLS_PRIVATE(grp),
130 					&realm_attest_keypair.MBEDTLS_PRIVATE(d));
131 	if (ret != 0) {
132 		ERROR("mbedtls_ecp_check_privkey has failed: %d\n", ret);
133 		rmm_el3_ifc_release_shared_buf();
134 		return -EINVAL;
135 	}
136 
137 	ret = mbedtls_ecp_mul(&realm_attest_keypair.MBEDTLS_PRIVATE(grp),
138 			      &realm_attest_keypair.MBEDTLS_PRIVATE(Q),
139 			      &realm_attest_keypair.MBEDTLS_PRIVATE(d),
140 			      &realm_attest_keypair.MBEDTLS_PRIVATE(grp).G,
141 			      rng_ctx.f_rng,
142 			      rng_ctx.p_rng);
143 	if (ret != 0) {
144 		ERROR("mbedtls_ecp_mul priv has failed: %d\n", ret);
145 		rmm_el3_ifc_release_shared_buf();
146 		return -EINVAL;
147 	}
148 
149 	ret = mbedtls_ecp_point_write_binary(&realm_attest_keypair.MBEDTLS_PRIVATE(grp),
150 					     &realm_attest_keypair.MBEDTLS_PRIVATE(Q),
151 					     MBEDTLS_ECP_PF_UNCOMPRESSED,
152 					     &realm_attest_public_key_len,
153 					     realm_attest_public_key,
154 					     sizeof(realm_attest_public_key));
155 	if (ret != 0) {
156 		ERROR("mbedtls_ecp_point_write_binary pub has failed\n");
157 		rmm_el3_ifc_release_shared_buf();
158 		return -EINVAL;
159 	}
160 
161 	/* Compute the hash of the realm attestation public key */
162 	ret = mbedtls_sha256(realm_attest_public_key,
163 			     realm_attest_public_key_len,
164 			     realm_attest_public_key_hash,
165 			     false);
166 	if (ret != 0) {
167 		ERROR("mbedtls_sha256 has failed\n");
168 		rmm_el3_ifc_release_shared_buf();
169 		return -EINVAL;
170 	}
171 
172 	realm_attest_public_key_hash_len = sizeof(realm_attest_public_key_hash);
173 
174 	/* Clear the private key from the buffer */
175 	(void)memset(realm_attest_private_key.ptr, 0,
176 			realm_attest_private_key.len);
177 
178 	rmm_el3_ifc_release_shared_buf();
179 
180 	return 0;
181 }
182 
attest_get_realm_signing_key(const void ** keypair)183 int attest_get_realm_signing_key(const void **keypair)
184 {
185 	if (realm_attest_keypair.MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(p) == NULL) {
186 		ERROR("Realm attestation key not initialized\n");
187 		return -EINVAL;
188 	}
189 
190 	*keypair = &realm_attest_keypair;
191 	return 0;
192 }
193 
attest_get_realm_public_key_hash(struct q_useful_buf_c * public_key_hash)194 int attest_get_realm_public_key_hash(struct q_useful_buf_c *public_key_hash)
195 {
196 	if (realm_attest_keypair.MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(p) == NULL) {
197 		ERROR("Realm attestation key not initialized\n");
198 		return -EINVAL;
199 	}
200 
201 	public_key_hash->ptr = realm_attest_public_key_hash;
202 	public_key_hash->len = realm_attest_public_key_hash_len;
203 	return 0;
204 }
205 
attest_get_realm_public_key(struct q_useful_buf_c * public_key)206 int attest_get_realm_public_key(struct q_useful_buf_c *public_key)
207 {
208 	if (realm_attest_keypair.MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(p) == NULL) {
209 		ERROR("Realm attestation key not initialized\n");
210 		return -EINVAL;
211 	}
212 
213 	public_key->ptr = realm_attest_public_key;
214 	public_key->len = realm_attest_public_key_len;
215 	return 0;
216 }
217 
attest_setup_platform_token(void)218 int attest_setup_platform_token(void)
219 {
220 	int ret;
221 	uintptr_t shared_buf;
222 	size_t platform_token_len = 0;
223 	struct q_useful_buf_c rmm_pub_key_hash;
224 
225 	/*
226 	 * Copy the RAK public hash value to the token buffer. This is
227 	 * used as the challenge input for the token generation
228 	 * thus creating a binding between the two.
229 	 */
230 	ret = attest_get_realm_public_key_hash(&rmm_pub_key_hash);
231 	if (ret != 0) {
232 		ERROR("Realm attestation key not initialized\n");
233 		return ret;
234 	}
235 
236 	shared_buf = rmm_el3_ifc_get_shared_buf_locked();
237 
238 	(void)memcpy((void *)shared_buf, rmm_pub_key_hash.ptr,
239 					 rmm_pub_key_hash.len);
240 
241 	ret = rmm_el3_ifc_get_platform_token(shared_buf,
242 					     rmm_el3_ifc_get_shared_buf_size(),
243 					     &platform_token_len,
244 					     SHA256_DIGEST_SIZE);
245 
246 	if (ret != 0) {
247 		rmm_el3_ifc_release_shared_buf();
248 		return -EINVAL;
249 	}
250 
251 	(void)memcpy(rmm_platform_token_buf,
252 		     (void *)shared_buf,
253 		     platform_token_len);
254 
255 	rmm_el3_ifc_release_shared_buf();
256 
257 	rmm_platform_token.ptr = rmm_platform_token_buf;
258 	rmm_platform_token.len = platform_token_len;
259 
260 	return 0;
261 }
262 
attest_get_platform_token(struct q_useful_buf_c ** buf)263 int attest_get_platform_token(struct q_useful_buf_c **buf)
264 {
265 	assert(buf != NULL);
266 
267 	if (rmm_platform_token.ptr == NULL) {
268 		return -EINVAL;
269 	}
270 
271 	*buf = (struct q_useful_buf_c *)&rmm_platform_token;
272 	return 0;
273 }
274 
attest_get_realm_public_key_hash_algo_id(void)275 enum hash_algo attest_get_realm_public_key_hash_algo_id(void)
276 {
277 	return public_key_hash_algo_id;
278 }
279