OLD | NEW |
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 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 | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 * | 4 * |
5 * Functions for verifying a verified boot kernel image. | 5 * Functions for verifying a verified boot kernel image. |
6 * (Firmware portion) | 6 * (Firmware portion) |
7 */ | 7 */ |
8 | 8 |
9 #include "kernel_image_fw.h" | 9 #include "kernel_image_fw.h" |
10 | 10 |
11 #include "cryptolib.h" | 11 #include "cryptolib.h" |
12 #include "rollback_index.h" | 12 #include "rollback_index.h" |
| 13 #include "stateful_util.h" |
13 #include "utility.h" | 14 #include "utility.h" |
14 | 15 |
15 /* Macro to determine the size of a field structure in the KernelImage | 16 /* Macro to determine the size of a field structure in the KernelImage |
16 * structure. */ | 17 * structure. */ |
17 #define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field)) | 18 #define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field)) |
18 | 19 |
19 char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = { | 20 char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = { |
20 "Success.", | 21 "Success.", |
21 "Invalid Image.", | 22 "Invalid Image.", |
22 "Kernel Key Signature Failed.", | 23 "Kernel Key Signature Failed.", |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 kernel_data, /* Data to verify */ | 181 kernel_data, /* Data to verify */ |
181 kernel_len, /* Length of data */ | 182 kernel_len, /* Length of data */ |
182 kernel_signature, /* Expected Signature */ | 183 kernel_signature, /* Expected Signature */ |
183 algorithm)) | 184 algorithm)) |
184 return VERIFY_KERNEL_SIGNATURE_FAILED; | 185 return VERIFY_KERNEL_SIGNATURE_FAILED; |
185 return 0; | 186 return 0; |
186 } | 187 } |
187 | 188 |
188 int VerifyKernelHeader(const uint8_t* firmware_key_blob, | 189 int VerifyKernelHeader(const uint8_t* firmware_key_blob, |
189 const uint8_t* kernel_header_blob, | 190 const uint8_t* kernel_header_blob, |
| 191 uint64_t kernel_header_blob_len, |
190 const int dev_mode, | 192 const int dev_mode, |
191 const uint8_t** expected_kernel_signature, | 193 KernelImage *image, |
192 RSAPublicKey** kernel_sign_key, | 194 RSAPublicKey** kernel_sign_key) { |
193 int* kernel_sign_algorithm, | |
194 uint64_t* kernel_len) { | |
195 int error_code; | 195 int error_code; |
196 int firmware_sign_algorithm; /* Firmware signing key algorithm. */ | 196 int firmware_sign_algorithm; /* Firmware signing key algorithm. */ |
| 197 int kernel_sign_algorithm; /* Kernel signing key algorithm. */ |
197 int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len, | 198 int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len, |
198 header_len; | 199 header_len; |
| 200 uint64_t kernel_len; |
199 const uint8_t* header_ptr = NULL; /* Pointer to key header. */ | 201 const uint8_t* header_ptr = NULL; /* Pointer to key header. */ |
200 const uint8_t* preamble_ptr = NULL; /* Pointer to start of preamble. */ | 202 const uint8_t* preamble_ptr = NULL; /* Pointer to start of preamble. */ |
201 const uint8_t* kernel_sign_key_ptr = NULL; /* Pointer to signing key. */ | 203 MemcpyState st; |
202 | 204 |
203 /* Note: All the offset calculations are based on struct FirmwareImage which | 205 /* Note: All the offset calculations are based on struct KernelImage which |
204 * is defined in include/firmware_image.h. */ | 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; |
205 | 210 |
206 /* Compare magic bytes. */ | 211 /* Clear destination image struct */ |
207 if (SafeMemcmp(kernel_header_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) | 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)) { |
208 return VERIFY_KERNEL_WRONG_MAGIC; | 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 |
209 header_ptr = kernel_header_blob + KERNEL_MAGIC_SIZE; | 226 header_ptr = kernel_header_blob + KERNEL_MAGIC_SIZE; |
210 | 227 |
211 /* Only continue if header verification succeeds. */ | 228 /* Only continue if header verification succeeds. */ |
212 if ((error_code = VerifyKernelKeyHeader(firmware_key_blob, header_ptr, | 229 if ((error_code = VerifyKernelKeyHeader(firmware_key_blob, header_ptr, |
213 dev_mode, | 230 dev_mode, |
214 &firmware_sign_algorithm, | 231 &firmware_sign_algorithm, |
215 kernel_sign_algorithm, | 232 &kernel_sign_algorithm, |
216 &header_len))) { | 233 &header_len))) { |
217 debug("VerifyKernelHeader: Kernel Key Header verification failed.\n"); | 234 debug("VerifyKernelHeader: Kernel Key Header verification failed.\n"); |
218 return error_code; /* AKA jump to recovery. */ | 235 return error_code; /* AKA jump to recovery. */ |
219 } | 236 } |
220 /* Parse signing key into RSAPublicKey structure since it is required multiple | 237 |
221 * times. */ | 238 /* Read pre-processed public half of the kernel signing key. */ |
222 kernel_sign_key_len = RSAProcessedKeySize(*kernel_sign_algorithm); | 239 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); |
223 kernel_sign_key_ptr = header_ptr + (FIELD_LEN(header_version) + | 240 StatefulMemcpy(&st, &image->kernel_key_version, |
224 FIELD_LEN(header_len) + | 241 FIELD_LEN(kernel_key_version)); |
225 FIELD_LEN(firmware_sign_algorithm) + | 242 image->kernel_sign_key = (uint8_t*)st.remaining_buf; |
226 FIELD_LEN(kernel_sign_algorithm) + | 243 StatefulSkip(&st, kernel_sign_key_len); |
227 FIELD_LEN(kernel_key_version)); | 244 StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum)); |
228 *kernel_sign_key = RSAPublicKeyFromBuf(kernel_sign_key_ptr, | 245 |
| 246 /* Parse signing key into RSAPublicKey structure since it is |
| 247 * required multiple times. */ |
| 248 *kernel_sign_key = RSAPublicKeyFromBuf(image->kernel_sign_key, |
229 kernel_sign_key_len); | 249 kernel_sign_key_len); |
230 kernel_signature_len = siglen_map[*kernel_sign_algorithm]; | 250 kernel_signature_len = siglen_map[kernel_sign_algorithm]; |
231 kernel_key_signature_len = siglen_map[firmware_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_signature_len); |
232 | 254 |
233 /* Only continue if preamble verification succeeds. */ | 255 /* Only continue if preamble verification succeeds. */ |
234 preamble_ptr = (header_ptr + header_len + kernel_key_signature_len); | 256 /* TODO: should pass the remaining len into VerifyKernelPreamble() */ |
| 257 preamble_ptr = (const uint8_t*)st.remaining_buf; |
235 if ((error_code = VerifyKernelPreamble(*kernel_sign_key, preamble_ptr, | 258 if ((error_code = VerifyKernelPreamble(*kernel_sign_key, preamble_ptr, |
236 *kernel_sign_algorithm, | 259 kernel_sign_algorithm, |
237 kernel_len))) { | 260 &kernel_len))) { |
238 RSAPublicKeyFree(*kernel_sign_key); | 261 RSAPublicKeyFree(*kernel_sign_key); |
239 return error_code; /* AKA jump to recovery. */ | 262 return error_code; /* AKA jump to recovery. */ |
240 } | 263 } |
241 *expected_kernel_signature = (preamble_ptr + | 264 |
242 GetKernelPreambleLen(*kernel_sign_algorithm) - | 265 /* Copy preamble fields */ |
243 kernel_signature_len); /* Skip beginning of | 266 StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version)); |
244 * preamble. */ | 267 StatefulMemcpy(&st, &image->kernel_len, FIELD_LEN(kernel_len)); |
| 268 StatefulMemcpy(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset)); |
| 269 StatefulMemcpy(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); |
| 270 StatefulMemcpy(&st, &image->padded_header_size, |
| 271 FIELD_LEN(padded_header_size)); |
| 272 image->kernel_signature = (uint8_t*)st.remaining_buf; |
| 273 StatefulSkip(&st, kernel_signature_len); |
| 274 image->preamble_signature = (uint8_t*)st.remaining_buf; |
| 275 |
245 return 0; | 276 return 0; |
246 } | 277 } |
247 | 278 |
248 int VerifyKernel(const uint8_t* firmware_key_blob, | 279 int VerifyKernel(const uint8_t* firmware_key_blob, |
249 const uint8_t* kernel_blob, | 280 const uint8_t* kernel_blob, |
250 const int dev_mode) { | 281 const int dev_mode) { |
251 int error_code; | 282 int error_code; |
252 int firmware_sign_algorithm; /* Firmware signing key algorithm. */ | 283 int firmware_sign_algorithm; /* Firmware signing key algorithm. */ |
253 int kernel_sign_algorithm; /* Kernel Signing key algorithm. */ | 284 int kernel_sign_algorithm; /* Kernel Signing key algorithm. */ |
254 RSAPublicKey* kernel_sign_key; | 285 RSAPublicKey* kernel_sign_key; |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 /* Lock Kernel TPM rollback indices from further writes. | 481 /* Lock Kernel TPM rollback indices from further writes. |
451 * TODO(gauravsh): Figure out if these can be combined into one | 482 * TODO(gauravsh): Figure out if these can be combined into one |
452 * 32-bit location since we seem to always use them together. This can help | 483 * 32-bit location since we seem to always use them together. This can help |
453 * us minimize the number of NVRAM writes/locks (which are limited over flash | 484 * us minimize the number of NVRAM writes/locks (which are limited over flash |
454 * memory lifetimes. | 485 * memory lifetimes. |
455 */ | 486 */ |
456 LockStoredVersion(KERNEL_KEY_VERSION); | 487 LockStoredVersion(KERNEL_KEY_VERSION); |
457 LockStoredVersion(KERNEL_VERSION); | 488 LockStoredVersion(KERNEL_VERSION); |
458 return kernel_to_boot; | 489 return kernel_to_boot; |
459 } | 490 } |
OLD | NEW |