1 /* Copyright 2021 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 * Functions for reading, checking and verifying firmware and
6 * kernel data structures.
7 */
8
9 #include "2common.h"
10
vb2_check_keyblock(const struct vb2_keyblock * block,uint32_t size,const struct vb2_signature * sig)11 vb2_error_t vb2_check_keyblock(const struct vb2_keyblock *block, uint32_t size,
12 const struct vb2_signature *sig)
13 {
14 if (size < sizeof(*block)) {
15 VB2_DEBUG("Not enough space for keyblock header.\n");
16 return VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER;
17 }
18
19 if (memcmp(block->magic, VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE)) {
20 VB2_DEBUG("Not a valid verified boot keyblock.\n");
21 return VB2_ERROR_KEYBLOCK_MAGIC;
22 }
23
24 if (block->header_version_major != VB2_KEYBLOCK_VERSION_MAJOR) {
25 VB2_DEBUG("Incompatible keyblock header version.\n");
26 return VB2_ERROR_KEYBLOCK_HEADER_VERSION;
27 }
28
29 if (size < block->keyblock_size) {
30 VB2_DEBUG("Not enough data for keyblock.\n");
31 return VB2_ERROR_KEYBLOCK_SIZE;
32 }
33
34 if (vb2_verify_signature_inside(block, block->keyblock_size, sig)) {
35 VB2_DEBUG("Keyblock signature off end of block\n");
36 return VB2_ERROR_KEYBLOCK_SIG_OUTSIDE;
37 }
38
39 /* Make sure advertised signature data sizes are valid. */
40 if (block->keyblock_size < sig->data_size) {
41 VB2_DEBUG("Signature calculated past end of block\n");
42 return VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH;
43 }
44
45 /* Verify we signed enough data */
46 if (sig->data_size < sizeof(struct vb2_keyblock)) {
47 VB2_DEBUG("Didn't sign enough data\n");
48 return VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE;
49 }
50
51 /* Verify data key is inside the block and inside signed data */
52 if (vb2_verify_packed_key_inside(block, block->keyblock_size,
53 &block->data_key)) {
54 VB2_DEBUG("Data key off end of keyblock\n");
55 return VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE;
56 }
57 if (vb2_verify_packed_key_inside(block, sig->data_size,
58 &block->data_key)) {
59 VB2_DEBUG("Data key off end of signed data\n");
60 return VB2_ERROR_KEYBLOCK_DATA_KEY_UNSIGNED;
61 }
62
63 return VB2_SUCCESS;
64 }
65
66 test_mockable
vb2_verify_keyblock(struct vb2_keyblock * block,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)67 vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size,
68 const struct vb2_public_key *key,
69 const struct vb2_workbuf *wb)
70 {
71 struct vb2_signature *sig = &block->keyblock_signature;
72 vb2_error_t rv;
73
74 /* Validity check keyblock before attempting signature check of data */
75 VB2_TRY(vb2_check_keyblock(block, size, sig));
76
77 VB2_DEBUG("Checking keyblock signature...\n");
78 rv = vb2_verify_data((const uint8_t *)block, size, sig, key, wb);
79 if (rv) {
80 VB2_DEBUG("Invalid keyblock signature.\n");
81 return VB2_ERROR_KEYBLOCK_SIG_INVALID;
82 }
83
84 /* Success */
85 return VB2_SUCCESS;
86 }
87
vb2_verify_fw_preamble(struct vb2_fw_preamble * preamble,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)88 vb2_error_t vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble,
89 uint32_t size,
90 const struct vb2_public_key *key,
91 const struct vb2_workbuf *wb)
92 {
93 struct vb2_signature *sig = &preamble->preamble_signature;
94
95 VB2_DEBUG("Verifying preamble.\n");
96
97 /* Validity checks before attempting signature of data */
98 if (size < sizeof(*preamble)) {
99 VB2_DEBUG("Not enough data for preamble header\n");
100 return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
101 }
102 if (preamble->header_version_major !=
103 VB2_FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) {
104 VB2_DEBUG("Incompatible firmware preamble header version.\n");
105 return VB2_ERROR_PREAMBLE_HEADER_VERSION;
106 }
107
108 if (preamble->header_version_minor < 1) {
109 VB2_DEBUG("Only preamble header 2.1+ supported\n");
110 return VB2_ERROR_PREAMBLE_HEADER_OLD;
111 }
112
113 if (size < preamble->preamble_size) {
114 VB2_DEBUG("Not enough data for preamble.\n");
115 return VB2_ERROR_PREAMBLE_SIZE;
116 }
117
118 /* Check signature */
119 if (vb2_verify_signature_inside(preamble, preamble->preamble_size,
120 sig)) {
121 VB2_DEBUG("Preamble signature off end of preamble\n");
122 return VB2_ERROR_PREAMBLE_SIG_OUTSIDE;
123 }
124
125 /* Make sure advertised signature data sizes are valid. */
126 if (preamble->preamble_size < sig->data_size) {
127 VB2_DEBUG("Signature calculated past end of the block\n");
128 return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH;
129 }
130
131 if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) {
132 VB2_DEBUG("Preamble signature validation failed\n");
133 return VB2_ERROR_PREAMBLE_SIG_INVALID;
134 }
135
136 /* Verify we signed enough data */
137 if (sig->data_size < sizeof(struct vb2_fw_preamble)) {
138 VB2_DEBUG("Didn't sign enough data\n");
139 return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE;
140 }
141
142 /* Verify body signature is inside the signed data */
143 if (vb2_verify_signature_inside(preamble, sig->data_size,
144 &preamble->body_signature)) {
145 VB2_DEBUG("Firmware body signature off end of preamble\n");
146 return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE;
147 }
148
149 /* Verify kernel subkey is inside the signed data */
150 if (vb2_verify_packed_key_inside(preamble, sig->data_size,
151 &preamble->kernel_subkey)) {
152 VB2_DEBUG("Kernel subkey off end of preamble\n");
153 return VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE;
154 }
155
156 /* Success */
157 return VB2_SUCCESS;
158 }
159
vb2_kernel_get_flags(const struct vb2_kernel_preamble * preamble)160 uint32_t vb2_kernel_get_flags(const struct vb2_kernel_preamble *preamble)
161 {
162 if (preamble->header_version_minor < 2)
163 return 0;
164
165 return preamble->flags;
166 }
167
168 test_mockable
vb2_verify_keyblock_hash(const struct vb2_keyblock * block,uint32_t size,const struct vb2_workbuf * wb)169 vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block,
170 uint32_t size,
171 const struct vb2_workbuf *wb)
172 {
173 const struct vb2_signature *sig = &block->keyblock_hash;
174 struct vb2_hash hash;
175
176 /* Validity check keyblock before attempting hash check of data */
177 VB2_TRY(vb2_check_keyblock(block, size, sig));
178
179 VB2_DEBUG("Checking keyblock hash...\n");
180
181 /* This is only used in developer mode, so hwcrypto not important. */
182 VB2_TRY(vb2_hash_calculate(false, block, sig->data_size,
183 VB2_HASH_SHA512, &hash));
184
185 if (vb2_safe_memcmp(vb2_signature_data(sig), hash.sha512,
186 sizeof(hash.sha512)) != 0) {
187 VB2_DEBUG("Invalid keyblock hash.\n");
188 return VB2_ERROR_KEYBLOCK_HASH_INVALID_IN_DEV_MODE;
189 }
190
191 /* Success */
192 return VB2_SUCCESS;
193 }
194
195 test_mockable
vb2_verify_kernel_preamble(struct vb2_kernel_preamble * preamble,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)196 vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
197 uint32_t size,
198 const struct vb2_public_key *key,
199 const struct vb2_workbuf *wb)
200 {
201 struct vb2_signature *sig = &preamble->preamble_signature;
202 uint32_t min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_0_SIZE;
203
204 VB2_DEBUG("Verifying kernel preamble.\n");
205
206 /* Make sure it's even safe to look at the struct */
207 if (size < min_size) {
208 VB2_DEBUG("Not enough data for preamble header.\n");
209 return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
210 }
211 if (preamble->header_version_major !=
212 VB2_KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) {
213 VB2_DEBUG("Incompatible kernel preamble header version.\n");
214 return VB2_ERROR_PREAMBLE_HEADER_VERSION;
215 }
216
217 if (preamble->header_version_minor >= 2)
218 min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_2_SIZE;
219 else if (preamble->header_version_minor == 1)
220 min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_1_SIZE;
221 if (preamble->preamble_size < min_size) {
222 VB2_DEBUG("Preamble size too small for header.\n");
223 return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
224 }
225 if (size < preamble->preamble_size) {
226 VB2_DEBUG("Not enough data for preamble.\n");
227 return VB2_ERROR_PREAMBLE_SIZE;
228 }
229
230 /* Check signature */
231 if (vb2_verify_signature_inside(preamble, preamble->preamble_size,
232 sig)) {
233 VB2_DEBUG("Preamble signature off end of preamble\n");
234 return VB2_ERROR_PREAMBLE_SIG_OUTSIDE;
235 }
236
237 /* Make sure advertised signature data sizes are valid. */
238 if (preamble->preamble_size < sig->data_size) {
239 VB2_DEBUG("Signature calculated past end of the block\n");
240 return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH;
241 }
242
243 if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) {
244 VB2_DEBUG("Preamble signature validation failed\n");
245 return VB2_ERROR_PREAMBLE_SIG_INVALID;
246 }
247
248 /* Verify we signed enough data */
249 if (sig->data_size < sizeof(struct vb2_fw_preamble)) {
250 VB2_DEBUG("Didn't sign enough data\n");
251 return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE;
252 }
253
254 /* Verify body signature is inside the signed data */
255 if (vb2_verify_signature_inside(preamble, sig->data_size,
256 &preamble->body_signature)) {
257 VB2_DEBUG("Body signature off end of preamble\n");
258 return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE;
259 }
260
261 /*
262 * If bootloader is present, verify it's covered by the body
263 * signature.
264 */
265 if (preamble->bootloader_size) {
266 const void *body_ptr =
267 (const void *)(uintptr_t)preamble->body_load_address;
268 const void *bootloader_ptr =
269 (const void *)(uintptr_t)preamble->bootloader_address;
270 if (vb2_verify_member_inside(body_ptr,
271 preamble->body_signature.data_size,
272 bootloader_ptr,
273 preamble->bootloader_size,
274 0, 0)) {
275 VB2_DEBUG("Bootloader off end of signed data\n");
276 return VB2_ERROR_PREAMBLE_BOOTLOADER_OUTSIDE;
277 }
278 }
279
280 /*
281 * If vmlinuz header is present, verify it's covered by the body
282 * signature.
283 */
284 if (preamble->header_version_minor >= 1 &&
285 preamble->vmlinuz_header_size) {
286 const void *body_ptr =
287 (const void *)(uintptr_t)preamble->body_load_address;
288 const void *vmlinuz_header_ptr = (const void *)
289 (uintptr_t)preamble->vmlinuz_header_address;
290 if (vb2_verify_member_inside(body_ptr,
291 preamble->body_signature.data_size,
292 vmlinuz_header_ptr,
293 preamble->vmlinuz_header_size,
294 0, 0)) {
295 VB2_DEBUG("Vmlinuz header off end of signed data\n");
296 return VB2_ERROR_PREAMBLE_VMLINUZ_HEADER_OUTSIDE;
297 }
298 }
299
300 /* Success */
301 return VB2_SUCCESS;
302 }
303