Index: src/platform/vboot_reference/vboot_firmware/lib/kernel_image_fw.c |
diff --git a/src/platform/vboot_reference/vboot_firmware/lib/kernel_image_fw.c b/src/platform/vboot_reference/vboot_firmware/lib/kernel_image_fw.c |
index 5a6afcfa82a37b9f73bb59894cbf28747262b932..280902d2595326bb15cda8fd321752ca9d304d67 100644 |
--- a/src/platform/vboot_reference/vboot_firmware/lib/kernel_image_fw.c |
+++ b/src/platform/vboot_reference/vboot_firmware/lib/kernel_image_fw.c |
@@ -10,6 +10,7 @@ |
#include "cryptolib.h" |
#include "rollback_index.h" |
+#include "stateful_util.h" |
#include "utility.h" |
/* Macro to determine the size of a field structure in the KernelImage |
@@ -187,61 +188,91 @@ int VerifyKernelData(RSAPublicKey* kernel_sign_key, |
int VerifyKernelHeader(const uint8_t* firmware_key_blob, |
const uint8_t* kernel_header_blob, |
+ uint64_t kernel_header_blob_len, |
const int dev_mode, |
- const uint8_t** expected_kernel_signature, |
- RSAPublicKey** kernel_sign_key, |
- int* kernel_sign_algorithm, |
- uint64_t* kernel_len) { |
+ KernelImage *image, |
+ RSAPublicKey** kernel_sign_key) { |
int error_code; |
int firmware_sign_algorithm; /* Firmware signing key algorithm. */ |
+ int kernel_sign_algorithm; /* Kernel signing key algorithm. */ |
int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len, |
header_len; |
+ uint64_t kernel_len; |
const uint8_t* header_ptr = NULL; /* Pointer to key header. */ |
const uint8_t* preamble_ptr = NULL; /* Pointer to start of preamble. */ |
- const uint8_t* kernel_sign_key_ptr = NULL; /* Pointer to signing key. */ |
+ MemcpyState st; |
- /* Note: All the offset calculations are based on struct FirmwareImage which |
- * is defined in include/firmware_image.h. */ |
+ /* Note: All the offset calculations are based on struct KernelImage which |
+ * is defined in include/kernel_image_fw.h. */ |
+ st.remaining_buf = (void *)kernel_header_blob; |
+ st.remaining_len = kernel_header_blob_len; |
+ st.overrun = 0; |
- /* Compare magic bytes. */ |
- if (SafeMemcmp(kernel_header_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) |
+ /* Clear destination image struct */ |
+ Memset(image, 0, sizeof(KernelImage)); |
+ |
+ /* Read and compare magic bytes. */ |
+ StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE); |
+ if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) { |
return VERIFY_KERNEL_WRONG_MAGIC; |
+ } |
+ StatefulMemcpy(&st, &image->header_version, FIELD_LEN(header_version)); |
+ StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len)); |
+ StatefulMemcpy(&st, &image->firmware_sign_algorithm, |
+ FIELD_LEN(firmware_sign_algorithm)); |
+ StatefulMemcpy(&st, &image->kernel_sign_algorithm, |
+ FIELD_LEN(kernel_sign_algorithm)); |
+ |
header_ptr = kernel_header_blob + KERNEL_MAGIC_SIZE; |
/* Only continue if header verification succeeds. */ |
if ((error_code = VerifyKernelKeyHeader(firmware_key_blob, header_ptr, |
dev_mode, |
&firmware_sign_algorithm, |
- kernel_sign_algorithm, |
+ &kernel_sign_algorithm, |
&header_len))) { |
debug("VerifyKernelHeader: Kernel Key Header verification failed.\n"); |
return error_code; /* AKA jump to recovery. */ |
} |
- /* Parse signing key into RSAPublicKey structure since it is required multiple |
- * times. */ |
- kernel_sign_key_len = RSAProcessedKeySize(*kernel_sign_algorithm); |
- kernel_sign_key_ptr = header_ptr + (FIELD_LEN(header_version) + |
- FIELD_LEN(header_len) + |
- FIELD_LEN(firmware_sign_algorithm) + |
- FIELD_LEN(kernel_sign_algorithm) + |
- FIELD_LEN(kernel_key_version)); |
- *kernel_sign_key = RSAPublicKeyFromBuf(kernel_sign_key_ptr, |
+ |
+ /* Read pre-processed public half of the kernel signing key. */ |
+ kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm); |
+ StatefulMemcpy(&st, &image->kernel_key_version, |
+ FIELD_LEN(kernel_key_version)); |
+ image->kernel_sign_key = (uint8_t*)st.remaining_buf; |
+ StatefulSkip(&st, kernel_sign_key_len); |
+ StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum)); |
+ |
+ /* Parse signing key into RSAPublicKey structure since it is |
+ * required multiple times. */ |
+ *kernel_sign_key = RSAPublicKeyFromBuf(image->kernel_sign_key, |
kernel_sign_key_len); |
- kernel_signature_len = siglen_map[*kernel_sign_algorithm]; |
+ kernel_signature_len = siglen_map[kernel_sign_algorithm]; |
kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; |
+ image->kernel_key_signature = (uint8_t*)st.remaining_buf; |
+ StatefulSkip(&st, kernel_signature_len); |
/* Only continue if preamble verification succeeds. */ |
- preamble_ptr = (header_ptr + header_len + kernel_key_signature_len); |
+ /* TODO: should pass the remaining len into VerifyKernelPreamble() */ |
+ preamble_ptr = (const uint8_t*)st.remaining_buf; |
if ((error_code = VerifyKernelPreamble(*kernel_sign_key, preamble_ptr, |
- *kernel_sign_algorithm, |
- kernel_len))) { |
+ kernel_sign_algorithm, |
+ &kernel_len))) { |
RSAPublicKeyFree(*kernel_sign_key); |
return error_code; /* AKA jump to recovery. */ |
} |
- *expected_kernel_signature = (preamble_ptr + |
- GetKernelPreambleLen(*kernel_sign_algorithm) - |
- kernel_signature_len); /* Skip beginning of |
- * preamble. */ |
+ |
+ /* Copy preamble fields */ |
+ StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version)); |
+ StatefulMemcpy(&st, &image->kernel_len, FIELD_LEN(kernel_len)); |
+ StatefulMemcpy(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset)); |
+ StatefulMemcpy(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); |
+ StatefulMemcpy(&st, &image->padded_header_size, |
+ FIELD_LEN(padded_header_size)); |
+ image->kernel_signature = (uint8_t*)st.remaining_buf; |
+ StatefulSkip(&st, kernel_signature_len); |
+ image->preamble_signature = (uint8_t*)st.remaining_buf; |
+ |
return 0; |
} |