OLD | NEW |
| (Empty) |
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | |
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 verifying a verified boot kernel image. | |
6 * (Firmware portion) | |
7 */ | |
8 | |
9 #include "kernel_image_fw.h" | |
10 | |
11 #include "cryptolib.h" | |
12 #include "rollback_index.h" | |
13 #include "stateful_util.h" | |
14 #include "utility.h" | |
15 | |
16 /* Macro to determine the size of a field structure in the KernelImage | |
17 * structure. */ | |
18 #define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field)) | |
19 | |
20 char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = { | |
21 "Success.", | |
22 "Invalid Image.", | |
23 "Kernel Key Signature Failed.", | |
24 "Invalid Kernel Verification Algorithm.", | |
25 "Preamble Signature Failed.", | |
26 "Kernel Signature Failed.", | |
27 "Wrong Kernel Magic.", | |
28 }; | |
29 | |
30 inline uint64_t GetKernelPreambleLen(int algorithm) { | |
31 return (FIELD_LEN(kernel_version) + | |
32 FIELD_LEN(kernel_len) + | |
33 FIELD_LEN(bootloader_offset) + | |
34 FIELD_LEN(bootloader_size) + | |
35 FIELD_LEN(padded_header_size) + | |
36 siglen_map[algorithm]); | |
37 } | |
38 | |
39 uint64_t GetVblockHeaderSize(const uint8_t* vkernel_blob) { | |
40 uint64_t len = 0; | |
41 uint16_t firmware_sign_algorithm; | |
42 uint16_t kernel_sign_algorithm; | |
43 int algorithms_offset = (FIELD_LEN(magic) + | |
44 FIELD_LEN(header_version) + | |
45 FIELD_LEN(header_len)); | |
46 if (SafeMemcmp(vkernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { | |
47 debug("Not a valid verified boot kernel blob.\n"); | |
48 return 0; | |
49 } | |
50 Memcpy(&firmware_sign_algorithm, | |
51 vkernel_blob + algorithms_offset, | |
52 sizeof(firmware_sign_algorithm)); | |
53 Memcpy(&kernel_sign_algorithm, | |
54 vkernel_blob + algorithms_offset + FIELD_LEN(kernel_sign_algorithm), | |
55 sizeof(kernel_sign_algorithm)); | |
56 if (firmware_sign_algorithm >= kNumAlgorithms) { | |
57 debug("Invalid firmware signing algorithm.\n"); | |
58 return 0; | |
59 } | |
60 if (kernel_sign_algorithm >= kNumAlgorithms) { | |
61 debug("Invalid kernel signing algorithm.\n"); | |
62 return 0; | |
63 } | |
64 len = algorithms_offset; /* magic, header length and version. */ | |
65 len += (FIELD_LEN(firmware_sign_algorithm) + | |
66 FIELD_LEN(kernel_sign_algorithm) + | |
67 FIELD_LEN(kernel_key_version) + | |
68 RSAProcessedKeySize(kernel_sign_algorithm) + /* kernel_sign_key */ | |
69 FIELD_LEN(header_checksum) + | |
70 siglen_map[firmware_sign_algorithm] + /* kernel_key_signature */ | |
71 GetKernelPreambleLen(kernel_sign_algorithm) + | |
72 siglen_map[kernel_sign_algorithm]); /* preamble_signature */ | |
73 return len; | |
74 } | |
75 | |
76 int VerifyKernelKeyHeader(const uint8_t* firmware_key_blob, | |
77 const uint8_t* header_blob, | |
78 const int dev_mode, | |
79 int* firmware_algorithm, | |
80 int* kernel_algorithm, | |
81 int* kernel_header_len) { | |
82 int kernel_sign_key_len; | |
83 int firmware_sign_key_len; | |
84 uint16_t header_version, header_len; | |
85 uint16_t firmware_sign_algorithm, kernel_sign_algorithm; | |
86 uint8_t* header_checksum = NULL; | |
87 | |
88 /* Base Offset for the header_checksum field. Actual offset is | |
89 * this + kernel_sign_key_len. */ | |
90 int base_header_checksum_offset = (FIELD_LEN(header_version) + | |
91 FIELD_LEN(header_len) + | |
92 FIELD_LEN(firmware_sign_algorithm) + | |
93 FIELD_LEN(kernel_sign_algorithm) + | |
94 FIELD_LEN(kernel_key_version)); | |
95 | |
96 Memcpy(&header_version, header_blob, sizeof(header_version)); | |
97 Memcpy(&header_len, header_blob + FIELD_LEN(header_version), | |
98 sizeof(header_len)); | |
99 Memcpy(&firmware_sign_algorithm, | |
100 header_blob + (FIELD_LEN(header_version) + | |
101 FIELD_LEN(header_len)), | |
102 sizeof(firmware_sign_algorithm)); | |
103 Memcpy(&kernel_sign_algorithm, | |
104 header_blob + (FIELD_LEN(header_version) + | |
105 FIELD_LEN(header_len) + | |
106 FIELD_LEN(firmware_sign_algorithm)), | |
107 sizeof(kernel_sign_algorithm)); | |
108 | |
109 /* TODO(gauravsh): Make this return two different error types depending | |
110 * on whether the firmware or kernel signing algorithm is invalid. */ | |
111 if (firmware_sign_algorithm >= kNumAlgorithms) | |
112 return VERIFY_KERNEL_INVALID_ALGORITHM; | |
113 if (kernel_sign_algorithm >= kNumAlgorithms) | |
114 return VERIFY_KERNEL_INVALID_ALGORITHM; | |
115 | |
116 *firmware_algorithm = (int) firmware_sign_algorithm; | |
117 *kernel_algorithm = (int) kernel_sign_algorithm; | |
118 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); | |
119 firmware_sign_key_len = RSAProcessedKeySize(firmware_sign_algorithm); | |
120 | |
121 | |
122 /* Verify if header len is correct? */ | |
123 if (header_len != (base_header_checksum_offset + | |
124 kernel_sign_key_len + | |
125 FIELD_LEN(header_checksum))) { | |
126 debug("VerifyKernelKeyHeader: Header length mismatch\n"); | |
127 return VERIFY_KERNEL_INVALID_IMAGE; | |
128 } | |
129 *kernel_header_len = (int) header_len; | |
130 | |
131 /* Verify if the hash of the header is correct. */ | |
132 header_checksum = DigestBuf(header_blob, | |
133 header_len - FIELD_LEN(header_checksum), | |
134 SHA512_DIGEST_ALGORITHM); | |
135 if (SafeMemcmp(header_checksum, | |
136 header_blob + (base_header_checksum_offset + | |
137 kernel_sign_key_len), | |
138 FIELD_LEN(header_checksum))) { | |
139 Free(header_checksum); | |
140 debug("VerifyKernelKeyHeader: Invalid header hash\n"); | |
141 return VERIFY_KERNEL_INVALID_IMAGE; | |
142 } | |
143 Free(header_checksum); | |
144 | |
145 /* Verify kernel key signature unless we are in dev mode. */ | |
146 if (!dev_mode) { | |
147 if (!RSAVerifyBinary_f(firmware_key_blob, NULL, /* Key to use */ | |
148 header_blob, /* Data to verify */ | |
149 header_len, /* Length of data */ | |
150 header_blob + header_len, /* Expected Signature */ | |
151 firmware_sign_algorithm)) | |
152 return VERIFY_KERNEL_KEY_SIGNATURE_FAILED; | |
153 } | |
154 return 0; | |
155 } | |
156 | |
157 int VerifyKernelPreamble(RSAPublicKey* kernel_sign_key, | |
158 const uint8_t* preamble_blob, | |
159 int algorithm, | |
160 uint64_t* kernel_len) { | |
161 int preamble_len = GetKernelPreambleLen(algorithm); | |
162 if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */ | |
163 preamble_blob, /* Data to verify */ | |
164 preamble_len, /* Length of data */ | |
165 preamble_blob + preamble_len, /* Expected Signature */ | |
166 algorithm)) | |
167 return VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED; | |
168 Memcpy(kernel_len, | |
169 preamble_blob + FIELD_LEN(kernel_version), | |
170 FIELD_LEN(kernel_len)); | |
171 return 0; | |
172 } | |
173 | |
174 int VerifyKernelData(RSAPublicKey* kernel_sign_key, | |
175 const uint8_t* kernel_signature, | |
176 const uint8_t* kernel_data, | |
177 uint64_t kernel_len, | |
178 int algorithm) { | |
179 | |
180 if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */ | |
181 kernel_data, /* Data to verify */ | |
182 kernel_len, /* Length of data */ | |
183 kernel_signature, /* Expected Signature */ | |
184 algorithm)) | |
185 return VERIFY_KERNEL_SIGNATURE_FAILED; | |
186 return 0; | |
187 } | |
188 | |
189 int VerifyKernelHeader(const uint8_t* firmware_key_blob, | |
190 const uint8_t* kernel_header_blob, | |
191 uint64_t kernel_header_blob_len, | |
192 const int dev_mode, | |
193 KernelImage* image, | |
194 RSAPublicKey** kernel_sign_key) { | |
195 int error_code; | |
196 int firmware_sign_algorithm; /* Firmware signing key algorithm. */ | |
197 int kernel_sign_algorithm; /* Kernel signing key algorithm. */ | |
198 int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len, | |
199 header_len; | |
200 uint64_t kernel_len; | |
201 const uint8_t* header_ptr = NULL; /* Pointer to key header. */ | |
202 const uint8_t* preamble_ptr = NULL; /* Pointer to start of preamble. */ | |
203 MemcpyState st; | |
204 | |
205 /* Note: All the offset calculations are based on struct KernelImage which | |
206 * is defined in include/kernel_image_fw.h. */ | |
207 st.remaining_buf = (void *)kernel_header_blob; | |
208 st.remaining_len = kernel_header_blob_len; | |
209 st.overrun = 0; | |
210 | |
211 /* Clear destination image struct */ | |
212 Memset(image, 0, sizeof(KernelImage)); | |
213 | |
214 /* Read and compare magic bytes. */ | |
215 StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE); | |
216 if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { | |
217 return VERIFY_KERNEL_WRONG_MAGIC; | |
218 } | |
219 StatefulMemcpy(&st, &image->header_version, FIELD_LEN(header_version)); | |
220 StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len)); | |
221 StatefulMemcpy(&st, &image->firmware_sign_algorithm, | |
222 FIELD_LEN(firmware_sign_algorithm)); | |
223 StatefulMemcpy(&st, &image->kernel_sign_algorithm, | |
224 FIELD_LEN(kernel_sign_algorithm)); | |
225 | |
226 header_ptr = kernel_header_blob + KERNEL_MAGIC_SIZE; | |
227 | |
228 /* Only continue if header verification succeeds. */ | |
229 if ((error_code = VerifyKernelKeyHeader(firmware_key_blob, header_ptr, | |
230 dev_mode, | |
231 &firmware_sign_algorithm, | |
232 &kernel_sign_algorithm, | |
233 &header_len))) { | |
234 debug("VerifyKernelHeader: Kernel Key Header verification failed.\n"); | |
235 return error_code; /* AKA jump to recovery. */ | |
236 } | |
237 | |
238 /* Read pre-processed public half of the kernel signing key. */ | |
239 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); | |
240 StatefulMemcpy(&st, &image->kernel_key_version, | |
241 FIELD_LEN(kernel_key_version)); | |
242 image->kernel_sign_key = (uint8_t*)st.remaining_buf; | |
243 StatefulSkip(&st, kernel_sign_key_len); | |
244 StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum)); | |
245 | |
246 /* Parse signing key into RSAPublicKey structure since it is | |
247 * required multiple times. */ | |
248 *kernel_sign_key = RSAPublicKeyFromBuf(image->kernel_sign_key, | |
249 kernel_sign_key_len); | |
250 kernel_signature_len = siglen_map[kernel_sign_algorithm]; | |
251 kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; | |
252 image->kernel_key_signature = (uint8_t*)st.remaining_buf; | |
253 StatefulSkip(&st, kernel_key_signature_len); | |
254 | |
255 /* Only continue if preamble verification succeeds. */ | |
256 /* TODO: should pass the remaining len into VerifyKernelPreamble() */ | |
257 preamble_ptr = (const uint8_t*)st.remaining_buf; | |
258 if ((error_code = VerifyKernelPreamble(*kernel_sign_key, preamble_ptr, | |
259 kernel_sign_algorithm, | |
260 &kernel_len))) { | |
261 RSAPublicKeyFree(*kernel_sign_key); | |
262 *kernel_sign_key = NULL; | |
263 return error_code; /* AKA jump to recovery. */ | |
264 } | |
265 | |
266 /* Copy preamble fields */ | |
267 StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version)); | |
268 StatefulMemcpy(&st, &image->kernel_len, FIELD_LEN(kernel_len)); | |
269 StatefulMemcpy(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset)); | |
270 StatefulMemcpy(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); | |
271 StatefulMemcpy(&st, &image->padded_header_size, | |
272 FIELD_LEN(padded_header_size)); | |
273 image->kernel_signature = (uint8_t*)st.remaining_buf; | |
274 StatefulSkip(&st, kernel_signature_len); | |
275 image->preamble_signature = (uint8_t*)st.remaining_buf; | |
276 | |
277 return 0; | |
278 } | |
279 | |
280 int VerifyKernel(const uint8_t* firmware_key_blob, | |
281 const uint8_t* kernel_blob, | |
282 const int dev_mode) { | |
283 int error_code; | |
284 int firmware_sign_algorithm; /* Firmware signing key algorithm. */ | |
285 int kernel_sign_algorithm; /* Kernel Signing key algorithm. */ | |
286 RSAPublicKey* kernel_sign_key; | |
287 int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len, | |
288 header_len; | |
289 uint64_t kernel_len; | |
290 const uint8_t* header_ptr; /* Pointer to header. */ | |
291 const uint8_t* kernel_sign_key_ptr; /* Pointer to signing key. */ | |
292 const uint8_t* preamble_ptr; /* Pointer to kernel preamble block. */ | |
293 const uint8_t* kernel_ptr; /* Pointer to kernel signature/data. */ | |
294 const uint8_t* kernel_signature; | |
295 | |
296 /* Note: All the offset calculations are based on struct FirmwareImage which | |
297 * is defined in include/firmware_image.h. */ | |
298 | |
299 /* Compare magic bytes. */ | |
300 if (SafeMemcmp(kernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { | |
301 debug("VerifyKernel: Kernel magic bytes not found.\n"); | |
302 return VERIFY_KERNEL_WRONG_MAGIC; | |
303 } | |
304 header_ptr = kernel_blob + KERNEL_MAGIC_SIZE; | |
305 | |
306 /* Only continue if header verification succeeds. */ | |
307 if ((error_code = VerifyKernelKeyHeader(firmware_key_blob, header_ptr, dev_mod
e, | |
308 &firmware_sign_algorithm, | |
309 &kernel_sign_algorithm, &header_len)))
{ | |
310 debug("VerifyKernel: Kernel header verification failed.\n"); | |
311 return error_code; /* AKA jump to recovery. */ | |
312 } | |
313 /* Parse signing key into RSAPublicKey structure since it is required multiple | |
314 * times. */ | |
315 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); | |
316 kernel_sign_key_ptr = header_ptr + (FIELD_LEN(header_version) + | |
317 FIELD_LEN(header_len) + | |
318 FIELD_LEN(firmware_sign_algorithm) + | |
319 FIELD_LEN(kernel_sign_algorithm) + | |
320 FIELD_LEN(kernel_key_version)); | |
321 kernel_sign_key = RSAPublicKeyFromBuf(kernel_sign_key_ptr, | |
322 kernel_sign_key_len); | |
323 kernel_signature_len = siglen_map[kernel_sign_algorithm]; | |
324 kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; | |
325 | |
326 /* Only continue if preamble verification succeeds. */ | |
327 preamble_ptr = (header_ptr + header_len + kernel_key_signature_len); | |
328 if ((error_code = VerifyKernelPreamble(kernel_sign_key, preamble_ptr, | |
329 kernel_sign_algorithm, | |
330 &kernel_len))) { | |
331 debug("VerifyKernel: Kernel preamble verification failed.\n"); | |
332 RSAPublicKeyFree(kernel_sign_key); | |
333 return error_code; /* AKA jump to recovery. */ | |
334 } | |
335 /* Only continue if kernel data verification succeeds. */ | |
336 kernel_ptr = (preamble_ptr + | |
337 GetKernelPreambleLen(kernel_sign_algorithm) + | |
338 kernel_signature_len); /* preamble signature. */ | |
339 kernel_signature = kernel_ptr - 2 * kernel_signature_len; /* end of kernel | |
340 * preamble. */ | |
341 | |
342 if ((error_code = VerifyKernelData(kernel_sign_key, /* Verification key */ | |
343 kernel_signature, /* kernel signature */ | |
344 kernel_ptr, /* Start of kernel data */ | |
345 kernel_len, /* Length of kernel data. */ | |
346 kernel_sign_algorithm))) { | |
347 RSAPublicKeyFree(kernel_sign_key); | |
348 return error_code; /* AKA jump to recovery. */ | |
349 } | |
350 RSAPublicKeyFree(kernel_sign_key); | |
351 return 0; /* Success! */ | |
352 } | |
353 | |
354 uint32_t GetLogicalKernelVersion(uint8_t* kernel_blob) { | |
355 uint8_t* kernel_ptr; | |
356 uint16_t kernel_key_version; | |
357 uint16_t kernel_version; | |
358 uint16_t firmware_sign_algorithm; | |
359 uint16_t kernel_sign_algorithm; | |
360 int kernel_key_signature_len; | |
361 int kernel_sign_key_len; | |
362 kernel_ptr = kernel_blob + (FIELD_LEN(magic) + | |
363 FIELD_LEN(header_version) + | |
364 FIELD_LEN(header_len)); | |
365 Memcpy(&firmware_sign_algorithm, kernel_ptr, sizeof(firmware_sign_algorithm)); | |
366 kernel_ptr += FIELD_LEN(firmware_sign_algorithm); | |
367 Memcpy(&kernel_sign_algorithm, kernel_ptr, sizeof(kernel_sign_algorithm)); | |
368 kernel_ptr += FIELD_LEN(kernel_sign_algorithm); | |
369 Memcpy(&kernel_key_version, kernel_ptr, sizeof(kernel_key_version)); | |
370 | |
371 if (firmware_sign_algorithm >= kNumAlgorithms) | |
372 return 0; | |
373 if (kernel_sign_algorithm >= kNumAlgorithms) | |
374 return 0; | |
375 | |
376 kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; | |
377 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); | |
378 kernel_ptr += (FIELD_LEN(kernel_key_version) + | |
379 kernel_sign_key_len + | |
380 FIELD_LEN(header_checksum) + | |
381 kernel_key_signature_len); | |
382 Memcpy(&kernel_version, kernel_ptr, sizeof(kernel_version)); | |
383 return CombineUint16Pair(kernel_key_version, kernel_version); | |
384 } | |
OLD | NEW |