xref: /aosp_15_r20/external/gsc-utils/boot_param/boot_param_platform_host.c (revision 4f2df630800bdcf1d4f0decf95d8a1cb87344f5f)
1 /*
2  * Copyright 2024 The ChromiumOS Authors
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 #include "boot_param_platform.h"
8 
9 #include <openssl/core_names.h>
10 #include <openssl/err.h>
11 #include <openssl/ec.h>
12 #include <openssl/evp.h>
13 #include <openssl/kdf.h>
14 #include <openssl/params.h>
15 #include <openssl/sha.h>
16 
17 #include <stdio.h>
18 #include <string.h>
19 
print_openssl_error(const char * func_name,const char * prefix_err)20 static void print_openssl_error(const char *func_name, const char *prefix_err)
21 {
22 	unsigned long err = ERR_get_error();
23 	char *err_str = ERR_error_string(err, NULL);
24 
25 	printf("%s: %s\n", func_name, prefix_err);
26 	if (err_str)
27 		__platform_log_str(err_str);
28 }
29 
30 /* Perform HKDF-SHA256(ikm, salt, info) */
__platform_hkdf_sha256(const struct slice_ref_s ikm,const struct slice_ref_s salt,const struct slice_ref_s info,const struct slice_mut_s result)31 bool __platform_hkdf_sha256(
32 	/* [IN] input key material */
33 	const struct slice_ref_s ikm,
34 	/* [IN] salt */
35 	const struct slice_ref_s salt,
36 	/* [IN] info */
37 	const struct slice_ref_s info,
38 	/* [IN/OUT] .size sets length for hkdf,
39 	 * .data is where the digest will be placed
40 	 */
41 	const struct slice_mut_s result
42 )
43 {
44 	EVP_KDF *kdf;
45 	EVP_KDF_CTX *kctx;
46 	OSSL_PARAM params[5], *p = params;
47 	int res;
48 
49 	kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
50 	if (kdf == NULL) {
51 		print_openssl_error(__func__, "Can't find HKDF");
52 		return false;
53 	}
54 	kctx = EVP_KDF_CTX_new(kdf);
55 	EVP_KDF_free(kdf);
56 	if (kctx == NULL) {
57 		print_openssl_error(__func__, "Can't create HKDF context");
58 		return false;
59 	}
60 
61 	*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
62 						SN_sha256, strlen(SN_sha256));
63 	*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
64 						 (void *)ikm.data, ikm.size);
65 	*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
66 						 (void *)info.data, info.size);
67 	*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
68 						 (void *)salt.data, salt.size);
69 	*p = OSSL_PARAM_construct_end();
70 
71 	res = EVP_KDF_derive(kctx, result.data, result.size, params);
72 	if (res <= 0)
73 		print_openssl_error(__func__, "Can't perform HKDF");
74 
75 	EVP_KDF_CTX_free(kctx);
76 	return (res > 0);
77 }
78 
79 /* Calculate SH256 for the provided buffer */
__platform_sha256(const struct slice_ref_s data,uint8_t digest[DIGEST_BYTES])80 bool __platform_sha256(
81 	/* [IN] data to hash */
82 	const struct slice_ref_s data,
83 	/* [OUT] resulting digest */
84 	uint8_t digest[DIGEST_BYTES]
85 )
86 {
87 	return SHA256(data.data, data.size, digest) == digest;
88 }
89 
90 struct dice_config_s g_dice_config = {
91 	.aprov_status = 0x20,
92 	.sec_ver = 1,
93 	.uds = {
94 		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
95 		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
96 		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
97 		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
98 	},
99 	.hidden_digest = {
100 		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
101 		0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
102 		0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
103 		0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
104 	},
105 	.code_digest = {
106 		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
107 		0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
108 		0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
109 		0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
110 	},
111 	.pcr0 = {
112 		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
113 		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
114 		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
115 		0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
116 	},
117 	.pcr10 = {
118 		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
119 		0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
120 		0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
121 		0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
122 	},
123 };
124 
125 /* Get DICE config */
__platform_get_dice_config(struct dice_config_s * cfg)126 bool __platform_get_dice_config(
127 	/* [OUT] DICE config */
128 	struct dice_config_s *cfg
129 )
130 {
131 	memcpy(cfg, &g_dice_config, sizeof(struct dice_config_s));
132 	return true;
133 }
134 
135 uint8_t g_early_entropy[EARLY_ENTROPY_BYTES] = {
136 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
137 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
138 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
139 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
140 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
141 	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
142 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
143 	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
144 };
145 
146 uint8_t g_session_key_seed[KEY_SEED_BYTES] = {
147 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
148 	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
149 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
150 	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
151 };
152 
153 uint8_t g_auth_token_key_seed[KEY_SEED_BYTES] = {
154 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
155 	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
156 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
157 	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
158 };
159 
160 /* Get GSC boot parameters */
__platform_get_gsc_boot_param(uint8_t early_entropy[EARLY_ENTROPY_BYTES],uint8_t session_key_seed[KEY_SEED_BYTES],uint8_t auth_token_key_seed[KEY_SEED_BYTES])161 bool __platform_get_gsc_boot_param(
162 	/* [OUT] early entropy */
163 	uint8_t early_entropy[EARLY_ENTROPY_BYTES],
164 	/* [OUT] SessionKeySeed */
165 	uint8_t session_key_seed[KEY_SEED_BYTES],
166 	/* [OUT] AuthTokenKeySeed */
167 	uint8_t auth_token_key_seed[KEY_SEED_BYTES]
168 )
169 {
170 	memcpy(early_entropy, g_early_entropy, EARLY_ENTROPY_BYTES);
171 	memcpy(session_key_seed, g_session_key_seed, KEY_SEED_BYTES);
172 	memcpy(auth_token_key_seed, g_auth_token_key_seed, KEY_SEED_BYTES);
173 	return true;
174 }
175 
176 /* Generate ECDSA P-256 key using HMAC-DRBG initialized by the seed */
__platform_ecdsa_p256_keygen_hmac_drbg(const uint8_t seed[DIGEST_BYTES],const void ** key)177 bool __platform_ecdsa_p256_keygen_hmac_drbg(
178 	/* [IN] key seed */
179 	const uint8_t seed[DIGEST_BYTES],
180 	/* [OUT] ECDSA key handle */
181 	const void **key
182 )
183 {
184 	/* NOTE: for testing we don't do the actual KDF based on HMAC_DRBG.
185 	 * We could use EVP_KDF-HMAC-DRBG or EVP_RAND-HMAC-DRBG, but there's
186 	 * no easy way to generate EC key from a seed we'd get from DRBG.
187 	 * Instead, we just generate a random EC key ignoring the seed.
188 	 */
189 	*key = EVP_EC_gen("P-256");
190 
191 	if (*key == NULL) {
192 		print_openssl_error(__func__, "Can't generate EC");
193 		return false;
194 	}
195 	return true;
196 }
197 
198 /* Generate ECDSA P-256 signature: 64 bytes (R | S) */
__platform_ecdsa_p256_sign(const void * key,const struct slice_ref_s data,uint8_t signature[ECDSA_SIG_BYTES])199 bool __platform_ecdsa_p256_sign(
200 	/* [IN] ECDSA key handle */
201 	const void *key,
202 	/* [IN] data to sign */
203 	const struct slice_ref_s data,
204 	/* [OUT] resulting signature */
205 	uint8_t signature[ECDSA_SIG_BYTES]
206 )
207 {
208 	const BIGNUM *r;
209 	const BIGNUM *s;
210 	EVP_PKEY_CTX *ctx;
211 	EVP_SIGNATURE *alg;
212 	uint8_t digest[DIGEST_BYTES];
213 	uint8_t output[128];
214 	int res;
215 	size_t siglen;
216 	ECDSA_SIG *sig_obj;
217 	const uint8_t *sig_ptr = output;
218 
219 	if (!__platform_sha256(data, digest)) {
220 		printf("%s: SHA failed\n", __func__);
221 		return false;
222 	}
223 
224 	ctx = EVP_PKEY_CTX_new((EVP_PKEY *)key, NULL /* no engine */);
225 	if (ctx == NULL) {
226 		print_openssl_error(__func__, "Can't create context");
227 		return false;
228 	}
229 	if (EVP_PKEY_sign_init(ctx) <= 0) {
230 		print_openssl_error(__func__, "Can't init sign");
231 		EVP_PKEY_CTX_free(ctx);
232 		return false;
233 	}
234 
235 	alg = EVP_SIGNATURE_fetch(NULL, "ECDSA", NULL);
236 	if (alg == NULL) {
237 		print_openssl_error(__func__, "Can't fetch signature alg");
238 		EVP_PKEY_CTX_free(ctx);
239 		return false;
240 	}
241 
242 	res = EVP_PKEY_sign(ctx, NULL, &siglen, digest, DIGEST_BYTES);
243 	if (res <= 0)
244 		print_openssl_error(__func__, "Can't detect signature size");
245 
246 	if (siglen <= sizeof(output)) {
247 		res = EVP_PKEY_sign(ctx, output, &siglen, digest, DIGEST_BYTES);
248 		if (res <= 0)
249 			print_openssl_error(__func__, "Can't sign");
250 	} else {
251 		printf("%s: unexpected sigsize %zu > %zu\n",
252 		       __func__, siglen, sizeof(output));
253 		res = 0;
254 	}
255 
256 	EVP_PKEY_CTX_free(ctx);
257 	EVP_SIGNATURE_free(alg);
258 
259 	if (res <= 0)
260 		return false;
261 
262 	sig_obj = d2i_ECDSA_SIG(NULL, &sig_ptr, siglen);
263 	if (sig_obj == NULL) {
264 		print_openssl_error(__func__, "Can't convert signature");
265 		return false;
266 	}
267 
268 	r = ECDSA_SIG_get0_r(sig_obj);
269 	s = ECDSA_SIG_get0_s(sig_obj);
270 
271 	if (BN_num_bytes(r) > ECDSA_POINT_BYTES) {
272 		printf("%s: unexpected r size %d > %u\n",
273 		       __func__, BN_num_bytes(r), ECDSA_POINT_BYTES);
274 		ECDSA_SIG_free(sig_obj);
275 		return false;
276 	}
277 	if (BN_num_bytes(s) > ECDSA_POINT_BYTES) {
278 		printf("%s: unexpected s size %d > %u\n",
279 		       __func__, BN_num_bytes(s), ECDSA_POINT_BYTES);
280 		ECDSA_SIG_free(sig_obj);
281 		return false;
282 	}
283 	memset(signature, 0, ECDSA_SIG_BYTES);
284 	BN_bn2bin(r, signature + (ECDSA_POINT_BYTES - BN_num_bytes(r)));
285 	BN_bn2bin(s, signature + (ECDSA_SIG_BYTES - BN_num_bytes(s)));
286 
287 	ECDSA_SIG_free(sig_obj);
288 	return true;
289 }
290 
291 /* Get ECDSA public key X, Y */
__platform_ecdsa_p256_get_pub_key(const void * key,struct ecdsa_public_s * pub_key)292 bool __platform_ecdsa_p256_get_pub_key(
293 	/* [IN] ECDSA key handle */
294 	const void *key,
295 	/* [OUT] public key structure */
296 	struct ecdsa_public_s *pub_key
297 )
298 {
299 	BIGNUM *x = NULL;
300 	BIGNUM *y = NULL;
301 	bool res = true;
302 
303 	if (!EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_X, &x)) {
304 		print_openssl_error(__func__, "Can't get X");
305 		res = false;
306 	}
307 
308 	if (!EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_Y, &y)) {
309 		print_openssl_error(__func__, "Can't get Y");
310 		res = false;
311 	}
312 
313 	if (res && (BN_num_bytes(x) > ECDSA_POINT_BYTES)) {
314 		printf("%s: unexpected X size %d > %u\n",
315 		       __func__, BN_num_bytes(x), ECDSA_POINT_BYTES);
316 		res = false;
317 	}
318 	if (res && (BN_num_bytes(y) > ECDSA_POINT_BYTES)) {
319 		printf("%s: unexpected Y size %d > %u\n",
320 		       __func__, BN_num_bytes(y), ECDSA_POINT_BYTES);
321 		res = false;
322 	}
323 
324 	if (res) {
325 		memset(pub_key->x, 0, ECDSA_POINT_BYTES);
326 		BN_bn2bin(x,
327 			pub_key->x + (ECDSA_POINT_BYTES - BN_num_bytes(x)));
328 		memset(pub_key->y, 0, ECDSA_POINT_BYTES);
329 		BN_bn2bin(y,
330 			pub_key->y + (ECDSA_POINT_BYTES - BN_num_bytes(y)));
331 	}
332 
333 	BN_free(x);
334 	BN_free(y);
335 	return res;
336 }
337 
338 /* Free ECDSA key handle */
__platform_ecdsa_p256_free(const void * key)339 void __platform_ecdsa_p256_free(
340 	/* [IN] ECDSA key handle */
341 	const void *key
342 )
343 {
344 	EVP_PKEY_free((EVP_PKEY *)key);
345 }
346 
347 /* Check if APROV status allows making 'normal' boot mode decision */
__platform_aprov_status_allows_normal(uint32_t aprov_status)348 bool __platform_aprov_status_allows_normal(
349 	/* [IN] APROV status */
350 	uint32_t aprov_status
351 )
352 {
353 	return true;
354 }
355 
356 /* Print error string to log */
__platform_log_str(const char * str)357 void __platform_log_str(
358 	/* [IN] string to print */
359 	const char *str
360 )
361 {
362 	puts(str);
363 }
364 
365 /* memcpy */
__platform_memcpy(void * dest,const void * src,size_t size)366 void __platform_memcpy(void *dest, const void *src, size_t size)
367 {
368 	memcpy(dest, src, size);
369 }
370 
371 /* memset */
__platform_memset(void * dest,uint8_t fill,size_t size)372 void __platform_memset(void *dest, uint8_t fill, size_t size)
373 {
374 	memset(dest, fill, size);
375 }
376 
377 /* memcmp */
__platform_memcmp(const void * str1,const void * str2,size_t size)378 int __platform_memcmp(const void *str1, const void *str2, size_t size)
379 {
380 	return memcmp(str1, str2, size);
381 }
382