xref: /aosp_15_r20/external/vboot_reference/host/lib/host_keyblock.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2011 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 verified boot.
6  */
7 
8 #include <stdio.h>
9 
10 #include "2sysincludes.h"
11 
12 #include "2api.h"
13 #include "2common.h"
14 #include "2rsa.h"
15 #include "2sha.h"
16 #include "host_common.h"
17 #include "host_key21.h"
18 #include "host_keyblock.h"
19 #include "host_key.h"
20 
vb2_create_keyblock(const struct vb2_packed_key * data_key,const struct vb2_private_key * signing_key,uint32_t flags)21 struct vb2_keyblock *vb2_create_keyblock(
22 		const struct vb2_packed_key *data_key,
23 		const struct vb2_private_key *signing_key,
24 		uint32_t flags)
25 {
26 	/* Allocate keyblock */
27 	uint32_t signed_size = sizeof(struct vb2_keyblock) + data_key->key_size;
28 	uint32_t sig_data_size =
29 		(signing_key ? vb2_rsa_sig_size(signing_key->sig_alg) : 0);
30 	uint32_t block_size =
31 		signed_size + VB2_SHA512_DIGEST_SIZE + sig_data_size;
32 	struct vb2_keyblock *h = (struct vb2_keyblock *)calloc(block_size, 1);
33 	if (!h)
34 		return NULL;
35 
36 	uint8_t *data_key_dest = (uint8_t *)(h + 1);
37 	uint8_t *block_chk_dest = data_key_dest + data_key->key_size;
38 	uint8_t *block_sig_dest = block_chk_dest + VB2_SHA512_DIGEST_SIZE;
39 
40 	memcpy(h->magic, VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE);
41 	h->header_version_major = VB2_KEYBLOCK_VERSION_MAJOR;
42 	h->header_version_minor = VB2_KEYBLOCK_VERSION_MINOR;
43 	h->keyblock_size = block_size;
44 	h->keyblock_flags = flags;
45 
46 	/* Copy data key */
47 	vb2_init_packed_key(&h->data_key, data_key_dest, data_key->key_size);
48 	vb2_copy_packed_key(&h->data_key, data_key);
49 
50 	/* Set up signature structs so we can calculate the signatures */
51 	vb2_init_signature(&h->keyblock_hash, block_chk_dest,
52 			   VB2_SHA512_DIGEST_SIZE, signed_size);
53 	if (signing_key) {
54 		vb2_init_signature(&h->keyblock_signature, block_sig_dest,
55 				   sig_data_size, signed_size);
56 	} else {
57 		memset(&h->keyblock_signature, 0,
58 		       sizeof(h->keyblock_signature));
59 	}
60 
61 	/* Calculate hash */
62 	struct vb2_signature *chk =
63 		vb2_sha512_signature((uint8_t*)h, signed_size);
64 	vb2_copy_signature(&h->keyblock_hash, chk);
65 	free(chk);
66 
67 	/* Calculate signature */
68 	if (signing_key) {
69 		struct vb2_signature *sigtmp =
70 			vb2_calculate_signature((uint8_t*)h,
71 						signed_size,
72 						signing_key);
73 		vb2_copy_signature(&h->keyblock_signature, sigtmp);
74 		free(sigtmp);
75 	}
76 
77 	/* Return the header */
78 	return h;
79 }
80 
81 /* TODO(gauravsh): This could easily be integrated into the function above
82  * since the code is almost a mirror - I have kept it as such to avoid changing
83  * the existing interface. */
vb2_create_keyblock_external(const struct vb2_packed_key * data_key,const char * signing_key_pem_file,uint32_t algorithm,uint32_t flags,const char * external_signer)84 struct vb2_keyblock *vb2_create_keyblock_external(
85 		const struct vb2_packed_key *data_key,
86 		const char *signing_key_pem_file,
87 		uint32_t algorithm,
88 		uint32_t flags,
89 		const char *external_signer)
90 {
91 	if (!signing_key_pem_file || !data_key || !external_signer)
92 		return NULL;
93 
94 	uint32_t signed_size = sizeof(struct vb2_keyblock) + data_key->key_size;
95 	uint32_t sig_data_size = vb2_rsa_sig_size(vb2_crypto_to_signature(algorithm));
96 	uint32_t block_size =
97 		signed_size + VB2_SHA512_DIGEST_SIZE + sig_data_size;
98 
99 	/* Allocate keyblock */
100 	struct vb2_keyblock *h = (struct vb2_keyblock *)calloc(block_size, 1);
101 	if (!h)
102 		return NULL;
103 
104 	uint8_t *data_key_dest = (uint8_t *)(h + 1);
105 	uint8_t *block_chk_dest = data_key_dest + data_key->key_size;
106 	uint8_t *block_sig_dest = block_chk_dest + VB2_SHA512_DIGEST_SIZE;
107 
108 	memcpy(h->magic, VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE);
109 	h->header_version_major = VB2_KEYBLOCK_VERSION_MAJOR;
110 	h->header_version_minor = VB2_KEYBLOCK_VERSION_MINOR;
111 	h->keyblock_size = block_size;
112 	h->keyblock_flags = flags;
113 
114 	/* Copy data key */
115 	vb2_init_packed_key(&h->data_key, data_key_dest, data_key->key_size);
116 	vb2_copy_packed_key(&h->data_key, data_key);
117 
118 	/* Set up signature structs so we can calculate the signatures */
119 	vb2_init_signature(&h->keyblock_hash, block_chk_dest,
120 			   VB2_SHA512_DIGEST_SIZE, signed_size);
121 	vb2_init_signature(&h->keyblock_signature, block_sig_dest,
122 			   sig_data_size, signed_size);
123 
124 	/* Calculate checksum */
125 	struct vb2_signature *chk =
126 		vb2_sha512_signature((uint8_t*)h, signed_size);
127 	vb2_copy_signature(&h->keyblock_hash, chk);
128 	free(chk);
129 
130 	/* Calculate signature */
131 	struct vb2_signature *sigtmp =
132 		vb2_external_signature((uint8_t*)h, signed_size,
133 				       signing_key_pem_file, algorithm,
134 				       external_signer);
135 	vb2_copy_signature(&h->keyblock_signature, sigtmp);
136 	free(sigtmp);
137 
138 	/* Return the header */
139 	return h;
140 }
141 
vb2_read_keyblock(const char * filename)142 struct vb2_keyblock *vb2_read_keyblock(const char *filename)
143 {
144 	uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
145 		__attribute__((aligned(VB2_WORKBUF_ALIGN)));
146 	struct vb2_workbuf wb;
147 	vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
148 
149 	struct vb2_keyblock *block;
150 	uint32_t file_size;
151 	if (VB2_SUCCESS !=
152 	    vb2_read_file(filename, (uint8_t **)&block, &file_size)) {
153 		fprintf(stderr, "Error reading keyblock file: %s\n", filename);
154 		return NULL;
155 	}
156 
157 	/* Verify the hash of the keyblock, since we can do that without
158 	 * the public signing key. */
159 	if (VB2_SUCCESS != vb2_verify_keyblock_hash(block, file_size, &wb)) {
160 		fprintf(stderr, "Invalid keyblock file: %s\n", filename);
161 		free(block);
162 		return NULL;
163 	}
164 
165 	return block;
166 }
167 
168 
vb2_write_keyblock(const char * filename,const struct vb2_keyblock * keyblock)169 int vb2_write_keyblock(const char *filename,
170 		       const struct vb2_keyblock *keyblock)
171 {
172 	return vb2_write_file(filename, keyblock, keyblock->keyblock_size);
173 }
174