xref: /aosp_15_r20/external/vboot_reference/host/lib21/host_key.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2014 The ChromiumOS Authors
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Host functions for keys.
6  */
7 
8 #include <stdio.h>
9 
10 #include <openssl/pem.h>
11 
12 #include "2common.h"
13 #include "2rsa.h"
14 #include "2sha.h"
15 #include "2sysincludes.h"
16 #include "host_common.h"
17 #include "host_common21.h"
18 #include "host_key21.h"
19 #include "host_misc.h"
20 #include "host_p11.h"
21 #include "openssl_compat.h"
22 #include "util_misc.h"
23 
vb21_private_key_unpack_raw(const uint8_t * buf,uint32_t size,struct vb2_private_key * key)24 vb2_error_t vb21_private_key_unpack_raw(const uint8_t *buf, uint32_t size,
25 					       struct vb2_private_key *key)
26 {
27 	const struct vb21_packed_private_key *pkey =
28 		(const struct vb21_packed_private_key *)buf;
29 	const unsigned char *start;
30 	uint32_t min_offset = 0;
31 
32 	/*
33 	 * Check magic number.
34 	 *
35 	 * TODO: If it doesn't match, pass through to the old packed key format.
36 	 */
37 	if (pkey->c.magic != VB21_MAGIC_PACKED_PRIVATE_KEY)
38 		return VB2_ERROR_UNPACK_PRIVATE_KEY_MAGIC;
39 
40 	if (vb21_verify_common_header(buf, size))
41 		return VB2_ERROR_UNPACK_PRIVATE_KEY_HEADER;
42 
43 	/* Make sure key data is inside */
44 	if (vb21_verify_common_member(pkey, &min_offset,
45 				     pkey->key_offset, pkey->key_size))
46 		return VB2_ERROR_UNPACK_PRIVATE_KEY_DATA;
47 
48 	/*
49 	 * Check for compatible version.  No need to check minor version, since
50 	 * that's compatible across readers matching the major version, and we
51 	 * haven't added any new fields.
52 	 */
53 	if (pkey->c.struct_version_major !=
54 	    VB21_PACKED_PRIVATE_KEY_VERSION_MAJOR)
55 		return VB2_ERROR_UNPACK_PRIVATE_KEY_STRUCT_VERSION;
56 
57 	/* Copy key algorithms and ID */
58 	key->key_location = PRIVATE_KEY_LOCAL;
59 	key->sig_alg = pkey->sig_alg;
60 	key->hash_alg = pkey->hash_alg;
61 	key->id = pkey->id;
62 
63 	/* Unpack RSA key */
64 	if (pkey->sig_alg == VB2_SIG_NONE) {
65 		if (pkey->key_size != 0)
66 			return VB2_ERROR_UNPACK_PRIVATE_KEY_HASH;
67 	} else {
68 		start = (const unsigned char *)(buf + pkey->key_offset);
69 		key->rsa_private_key = d2i_RSAPrivateKey(0, &start,
70 							 pkey->key_size);
71 		if (!key->rsa_private_key)
72 			return VB2_ERROR_UNPACK_PRIVATE_KEY_RSA;
73 	}
74 
75 	/* Key description */
76 	if (pkey->c.desc_size) {
77 		if (vb2_private_key_set_desc(key, (const char *)(buf + pkey->c.fixed_size)))
78 			return VB2_ERROR_UNPACK_PRIVATE_KEY_DESC;
79 	}
80 
81 	return VB2_SUCCESS;
82 }
83 
vb21_private_key_unpack(struct vb2_private_key ** key_ptr,const uint8_t * buf,uint32_t size)84 vb2_error_t vb21_private_key_unpack(struct vb2_private_key **key_ptr, const uint8_t *buf,
85 				    uint32_t size)
86 {
87 	*key_ptr = NULL;
88 	struct vb2_private_key *key = (struct vb2_private_key *)calloc(sizeof(*key), 1);
89 	if (!key)
90 		return VB2_ERROR_UNPACK_PRIVATE_KEY_ALLOC;
91 
92 	vb2_error_t rv = vb21_private_key_unpack_raw(buf, size, key);
93 	if (rv != VB2_SUCCESS) {
94 		vb2_free_private_key(key);
95 		return rv;
96 	}
97 	*key_ptr = key;
98 	return VB2_SUCCESS;
99 }
100 
vb2_private_key_read_pem(struct vb2_private_key ** key_ptr,const char * filename)101 vb2_error_t vb2_private_key_read_pem(struct vb2_private_key **key_ptr,
102 				     const char *filename)
103 {
104 	struct vb2_private_key *key;
105 	FILE *f;
106 
107 	*key_ptr = NULL;
108 
109 	/* Allocate the new key */
110 	key = calloc(1, sizeof(*key));
111 	if (!key)
112 		return VB2_ERROR_READ_PEM_ALLOC;
113 
114 	/* Read private key */
115 	f = fopen(filename, "rb");
116 	if (!f) {
117 		free(key);
118 		return VB2_ERROR_READ_PEM_FILE_OPEN;
119 	}
120 
121 	key->rsa_private_key = PEM_read_RSAPrivateKey(f, NULL, NULL, NULL);
122 	fclose(f);
123 
124 	if (!key->rsa_private_key) {
125 		free(key);
126 		return VB2_ERROR_READ_PEM_RSA;
127 	}
128 
129 	*key_ptr = key;
130 	return VB2_SUCCESS;
131 }
132 
vb2_private_key_set_desc(struct vb2_private_key * key,const char * desc)133 vb2_error_t vb2_private_key_set_desc(struct vb2_private_key *key,
134 				     const char *desc)
135 {
136 	if (key->desc)
137 		free(key->desc);
138 
139 	if (desc) {
140 		key->desc = strdup(desc);
141 		if (!key->desc)
142 			return VB2_ERROR_PRIVATE_KEY_SET_DESC;
143 	} else {
144 		key->desc = NULL;
145 	}
146 
147 	return VB2_SUCCESS;
148 }
149 
vb21_private_key_write(const struct vb2_private_key * key,const char * filename)150 vb2_error_t vb21_private_key_write(const struct vb2_private_key *key,
151 				   const char *filename)
152 {
153 	struct vb21_packed_private_key pkey = {
154 		.c.magic = VB21_MAGIC_PACKED_PRIVATE_KEY,
155 		.c.struct_version_major = VB21_PACKED_PRIVATE_KEY_VERSION_MAJOR,
156 		.c.struct_version_minor = VB21_PACKED_PRIVATE_KEY_VERSION_MINOR,
157 		.c.fixed_size = sizeof(pkey),
158 		.sig_alg = key->sig_alg,
159 		.hash_alg = key->hash_alg,
160 		.id = key->id,
161 	};
162 	uint8_t *buf;
163 	uint8_t *rsabuf = NULL;
164 	int rsalen = 0;
165 	vb2_error_t rv;
166 
167 	memcpy(&pkey.id, &key->id, sizeof(pkey.id));
168 
169 	pkey.c.desc_size = vb2_desc_size(key->desc);
170 
171 	if (key->sig_alg != VB2_SIG_NONE) {
172 		/* Pack RSA key */
173 		rsalen = i2d_RSAPrivateKey(key->rsa_private_key, &rsabuf);
174 		if (rsalen <= 0 || !rsabuf)
175 			return VB2_ERROR_PRIVATE_KEY_WRITE_RSA;
176 	}
177 
178 	pkey.key_offset = pkey.c.fixed_size + pkey.c.desc_size;
179 	pkey.key_size = roundup32(rsalen);
180 	pkey.c.total_size = pkey.key_offset + pkey.key_size;
181 
182 	/* Pack private key */
183 	buf = calloc(1, pkey.c.total_size);
184 	if (!buf) {
185 		free(rsabuf);
186 		return VB2_ERROR_PRIVATE_KEY_WRITE_ALLOC;
187 	}
188 
189 	memcpy(buf, &pkey, sizeof(pkey));
190 
191 	/* strcpy() is ok here because we checked the length above */
192 	if (pkey.c.desc_size)
193 		strcpy((char *)buf + pkey.c.fixed_size, key->desc);
194 
195 	if (rsabuf) {
196 		memcpy(buf + pkey.key_offset, rsabuf, rsalen);
197 		free(rsabuf);
198 	}
199 
200 	rv = vb21_write_object(filename, buf);
201 	free(buf);
202 
203 	return rv ? VB2_ERROR_PRIVATE_KEY_WRITE_FILE : VB2_SUCCESS;
204 }
205 
vb2_private_key_hash(const struct vb2_private_key ** key_ptr,enum vb2_hash_algorithm hash_alg)206 vb2_error_t vb2_private_key_hash(const struct vb2_private_key **key_ptr,
207 				 enum vb2_hash_algorithm hash_alg)
208 {
209 	*key_ptr = NULL;
210 
211 	switch (hash_alg) {
212 #if VB2_SUPPORT_SHA1
213 	case VB2_HASH_SHA1:
214 		{
215 			static const struct vb2_private_key key = {
216 				.hash_alg = VB2_HASH_SHA1,
217 				.sig_alg = VB2_SIG_NONE,
218 				.desc = (char *)"Unsigned SHA1",
219 				.id = VB2_ID_NONE_SHA1,
220 			};
221 			*key_ptr = &key;
222 			return VB2_SUCCESS;
223 		}
224 #endif
225 #if VB2_SUPPORT_SHA256
226 	case VB2_HASH_SHA256:
227 		{
228 			static const struct vb2_private_key key = {
229 				.hash_alg = VB2_HASH_SHA256,
230 				.sig_alg = VB2_SIG_NONE,
231 				.desc = (char *)"Unsigned SHA-256",
232 				.id = VB2_ID_NONE_SHA256,
233 			};
234 			*key_ptr = &key;
235 			return VB2_SUCCESS;
236 		}
237 #endif
238 #if VB2_SUPPORT_SHA512
239 	case VB2_HASH_SHA512:
240 		{
241 			static const struct vb2_private_key key = {
242 				.hash_alg = VB2_HASH_SHA512,
243 				.sig_alg = VB2_SIG_NONE,
244 				.desc = (char *)"Unsigned SHA-512",
245 				.id = VB2_ID_NONE_SHA512,
246 			};
247 			*key_ptr = &key;
248 			return VB2_SUCCESS;
249 		}
250 #endif
251 	default:
252 		return VB2_ERROR_PRIVATE_KEY_HASH;
253 	}
254 }
255 
vb2_public_key_alloc(struct vb2_public_key ** key_ptr,enum vb2_signature_algorithm sig_alg)256 vb2_error_t vb2_public_key_alloc(struct vb2_public_key **key_ptr,
257 				 enum vb2_signature_algorithm sig_alg)
258 {
259 	struct vb2_public_key *key;
260 	uint32_t key_data_size = vb2_packed_key_size(sig_alg);
261 
262 	/* The buffer contains the key, its ID, and its packed data */
263 	uint32_t buf_size = sizeof(*key) + sizeof(struct vb2_id) +
264 		key_data_size;
265 
266 	if (!key_data_size)
267 		return VB2_ERROR_PUBLIC_KEY_ALLOC_SIZE;
268 
269 	key = calloc(1, buf_size);
270 	if (!key)
271 		return VB2_ERROR_PUBLIC_KEY_ALLOC;
272 
273 	key->id = (struct vb2_id *)(key + 1);
274 	key->sig_alg = sig_alg;
275 
276 	*key_ptr = key;
277 
278 	return VB2_SUCCESS;
279 }
280 
vb2_public_key_free(struct vb2_public_key * key)281 void vb2_public_key_free(struct vb2_public_key *key)
282 {
283 	if (!key)
284 		return;
285 
286 	if (key->desc)
287 		free((void *)key->desc);
288 
289 	free(key);
290 }
291 
vb2_public_key_packed_data(struct vb2_public_key * key)292 uint8_t *vb2_public_key_packed_data(struct vb2_public_key *key)
293 {
294 	return (uint8_t *)(key->id + 1);
295 }
296 
vb2_public_key_read_keyb(struct vb2_public_key ** key_ptr,const char * filename)297 vb2_error_t vb2_public_key_read_keyb(struct vb2_public_key **key_ptr,
298 				     const char *filename)
299 {
300 	struct vb2_public_key *key = NULL;
301 	uint8_t *key_data, *key_buf;
302 	uint32_t key_size;
303 	enum vb2_signature_algorithm sig_alg;
304 
305 	*key_ptr = NULL;
306 
307 	if (vb2_read_file(filename, &key_data, &key_size))
308 		return VB2_ERROR_READ_KEYB_DATA;
309 
310 	/* Guess the signature algorithm from the key size
311 	 * Note: This only considers exponent F4 keys, as there is no way to
312 	 * distinguish between exp 3 and F4 based on size. Vboot API 2.1 is
313 	 * required to make proper use of exp 3 keys. */
314 	for (sig_alg = VB2_SIG_RSA1024; sig_alg <= VB2_SIG_RSA8192; sig_alg++) {
315 		if (key_size == vb2_packed_key_size(sig_alg))
316 			break;
317 	}
318 	if (sig_alg > VB2_SIG_RSA8192) {
319 		free(key_data);
320 		return VB2_ERROR_READ_KEYB_SIZE;
321 	}
322 
323 	if (vb2_public_key_alloc(&key, sig_alg)) {
324 		free(key_data);
325 		return VB2_ERROR_READ_KEYB_ALLOC;
326 	}
327 
328 	/* Copy data from the file buffer to the public key buffer */
329 	key_buf = vb2_public_key_packed_data(key);
330 	memcpy(key_buf, key_data, key_size);
331 	free(key_data);
332 
333 	if (vb2_unpack_key_data(key, key_buf, key_size)) {
334 		vb2_public_key_free(key);
335 		return VB2_ERROR_READ_KEYB_UNPACK;
336 	}
337 
338 	*key_ptr = key;
339 
340 	return VB2_SUCCESS;
341 }
342 
vb2_public_key_set_desc(struct vb2_public_key * key,const char * desc)343 vb2_error_t vb2_public_key_set_desc(struct vb2_public_key *key,
344 				    const char *desc)
345 {
346 	if (key->desc)
347 		free((void *)key->desc);
348 
349 	if (desc) {
350 		key->desc = strdup(desc);
351 		if (!key->desc)
352 			return VB2_ERROR_PUBLIC_KEY_SET_DESC;
353 	} else {
354 		key->desc = NULL;
355 	}
356 
357 	return VB2_SUCCESS;
358 }
359 
vb21_packed_key_read(struct vb21_packed_key ** key_ptr,const char * filename)360 vb2_error_t vb21_packed_key_read(struct vb21_packed_key **key_ptr,
361 				 const char *filename)
362 {
363 	struct vb2_public_key key;
364 	uint8_t *buf;
365 	uint32_t size;
366 
367 	*key_ptr = NULL;
368 
369 	if (vb2_read_file(filename, &buf, &size))
370 		return VB2_ERROR_READ_PACKED_KEY_DATA;
371 
372 	/* Validity check: make sure key unpacks properly */
373 	if (vb21_unpack_key(&key, buf, size))
374 		return VB2_ERROR_READ_PACKED_KEY;
375 
376 	*key_ptr = (struct vb21_packed_key *)buf;
377 
378 	return VB2_SUCCESS;
379 }
380 
vb21_public_key_pack(struct vb21_packed_key ** key_ptr,const struct vb2_public_key * pubk)381 vb2_error_t vb21_public_key_pack(struct vb21_packed_key **key_ptr,
382 				 const struct vb2_public_key *pubk)
383 {
384 	struct vb21_packed_key key = {
385 		.c.magic = VB21_MAGIC_PACKED_KEY,
386 		.c.struct_version_major = VB21_PACKED_KEY_VERSION_MAJOR,
387 		.c.struct_version_minor = VB21_PACKED_KEY_VERSION_MINOR,
388 	};
389 	uint8_t *buf;
390 	uint32_t *buf32;
391 
392 	*key_ptr = NULL;
393 
394 	/* Calculate sizes and offsets */
395 	key.c.fixed_size = sizeof(key);
396 	key.c.desc_size = vb2_desc_size(pubk->desc);
397 	key.key_offset = key.c.fixed_size + key.c.desc_size;
398 
399 	if (pubk->sig_alg != VB2_SIG_NONE) {
400 		key.key_size = vb2_packed_key_size(pubk->sig_alg);
401 		if (!key.key_size)
402 			return VB2_ERROR_PUBLIC_KEY_PACK_SIZE;
403 	}
404 
405 	key.c.total_size = key.key_offset + key.key_size;
406 
407 	/* Copy/initialize fields */
408 	key.key_version = pubk->version;
409 	key.sig_alg = pubk->sig_alg;
410 	key.hash_alg = pubk->hash_alg;
411 	key.id = *pubk->id;
412 
413 	/* Allocate the new buffer */
414 	buf = calloc(1, key.c.total_size);
415 
416 	/* Copy data into the buffer */
417 	memcpy(buf, &key, sizeof(key));
418 
419 	/* strcpy() is safe because we allocated above based on strlen() */
420 	if (pubk->desc && *pubk->desc) {
421 		strcpy((char *)(buf + key.c.fixed_size), pubk->desc);
422 		buf[key.c.fixed_size + key.c.desc_size - 1] = 0;
423 	}
424 
425 	if (pubk->sig_alg != VB2_SIG_NONE) {
426 		/* Re-pack the key arrays */
427 		buf32 = (uint32_t *)(buf + key.key_offset);
428 		buf32[0] = pubk->arrsize;
429 		buf32[1] = pubk->n0inv;
430 		memcpy(buf32 + 2, pubk->n, pubk->arrsize * sizeof(uint32_t));
431 		memcpy(buf32 + 2 + pubk->arrsize, pubk->rr,
432 		       pubk->arrsize * sizeof(uint32_t));
433 	}
434 
435 	*key_ptr = (struct vb21_packed_key *)buf;
436 
437 	return VB2_SUCCESS;
438 }
439 
vb2_public_key_hash(struct vb2_public_key * key,enum vb2_hash_algorithm hash_alg)440 vb2_error_t vb2_public_key_hash(struct vb2_public_key *key,
441 				enum vb2_hash_algorithm hash_alg)
442 {
443 	switch (hash_alg) {
444 #if VB2_SUPPORT_SHA1
445 	case VB2_HASH_SHA1:
446 		key->desc = "Unsigned SHA1";
447 		break;
448 #endif
449 #if VB2_SUPPORT_SHA256
450 	case VB2_HASH_SHA256:
451 		key->desc = "Unsigned SHA-256";
452 		break;
453 #endif
454 #if VB2_SUPPORT_SHA512
455 	case VB2_HASH_SHA512:
456 		key->desc = "Unsigned SHA-512";
457 		break;
458 #endif
459 	default:
460 		return VB2_ERROR_PUBLIC_KEY_HASH;
461 	}
462 
463 	key->sig_alg = VB2_SIG_NONE;
464 	key->hash_alg = hash_alg;
465 	key->id = vb2_hash_id(hash_alg);
466 	return VB2_SUCCESS;
467 }
468 
vb2_rsa_sig_alg(struct rsa_st * rsa)469 enum vb2_signature_algorithm vb2_rsa_sig_alg(struct rsa_st *rsa)
470 {
471 	const BIGNUM *e, *n;
472 	uint32_t exp, bits;
473 
474 	RSA_get0_key(rsa, &n, &e, NULL);
475 	exp = BN_get_word(e);
476 	bits = BN_num_bits(n);
477 
478 	return vb2_get_sig_alg(exp, bits);
479 }
480 
vb21_public_key_write(const struct vb2_public_key * key,const char * filename)481 vb2_error_t vb21_public_key_write(const struct vb2_public_key *key,
482 				  const char *filename)
483 {
484 	struct vb21_packed_key *pkey;
485 	int ret;
486 
487 	ret = vb21_public_key_pack(&pkey, key);
488 	if (ret)
489 		return ret;
490 
491 	ret = vb21_write_object(filename, pkey);
492 
493 	free(pkey);
494 	return ret;
495 }
496 
vb21_unpack_key(struct vb2_public_key * key,const uint8_t * buf,uint32_t size)497 vb2_error_t vb21_unpack_key(struct vb2_public_key *key, const uint8_t *buf,
498 			    uint32_t size)
499 {
500 	const struct vb21_packed_key *pkey =
501 		(const struct vb21_packed_key *)buf;
502 	uint32_t sig_size;
503 	uint32_t min_offset = 0;
504 	vb2_error_t rv;
505 
506 	/* Check magic number */
507 	if (pkey->c.magic != VB21_MAGIC_PACKED_KEY)
508 		return VB2_ERROR_UNPACK_KEY_MAGIC;
509 
510 	rv = vb21_verify_common_header(buf, size);
511 	if (rv)
512 		return rv;
513 
514 	/* Make sure key data is inside */
515 	rv = vb21_verify_common_member(pkey, &min_offset,
516 				       pkey->key_offset, pkey->key_size);
517 	if (rv)
518 		return rv;
519 
520 	/*
521 	 * Check for compatible version.  No need to check minor version, since
522 	 * that's compatible across readers matching the major version, and we
523 	 * haven't added any new fields.
524 	 */
525 	if (pkey->c.struct_version_major != VB21_PACKED_KEY_VERSION_MAJOR)
526 		return VB2_ERROR_UNPACK_KEY_STRUCT_VERSION;
527 
528 	/* Copy key algorithms */
529 	key->hash_alg = pkey->hash_alg;
530 	if (!vb2_digest_size(key->hash_alg))
531 		return VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM;
532 
533 	key->sig_alg = pkey->sig_alg;
534 	if (key->sig_alg != VB2_SIG_NONE) {
535 		sig_size = vb2_rsa_sig_size(key->sig_alg);
536 		if (!sig_size)
537 			return VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM;
538 		rv = vb2_unpack_key_data(
539 				key,
540 				(const uint8_t *)pkey + pkey->key_offset,
541 				pkey->key_size);
542 		if (rv)
543 			return rv;
544 	}
545 
546 	/* Key description */
547 	key->desc = vb21_common_desc(pkey);
548 	key->version = pkey->key_version;
549 	key->id = &pkey->id;
550 
551 	return VB2_SUCCESS;
552 }
553