Index: src/platform/vboot_reference/vkernel/kernel_image_fw.c |
diff --git a/src/platform/vboot_reference/vkernel/kernel_image_fw.c b/src/platform/vboot_reference/vkernel/kernel_image_fw.c |
index 23111e93cd042732da327f85a38955e8fbe28c2c..5a1e9785949fd374f403e604d40f46cb805854fb 100644 |
--- a/src/platform/vboot_reference/vkernel/kernel_image_fw.c |
+++ b/src/platform/vboot_reference/vkernel/kernel_image_fw.c |
@@ -21,11 +21,19 @@ char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = { |
"Invalid Image.", |
"Kernel Key Signature Failed.", |
"Invalid Kernel Verification Algorithm.", |
- "Config Signature Failed.", |
+ "Preamble Signature Failed.", |
"Kernel Signature Failed.", |
"Wrong Kernel Magic.", |
}; |
+inline uint64_t GetKernelPreambleLen(void) { |
+ return (FIELD_LEN(kernel_version) + |
+ FIELD_LEN(kernel_len) + |
+ FIELD_LEN(bootloader_offset) + |
+ FIELD_LEN(bootloader_size) + |
+ FIELD_LEN(padded_header_size)); |
+} |
+ |
uint64_t GetVblockHeaderSize(const uint8_t* vkernel_blob) { |
uint64_t len = 0; |
uint16_t firmware_sign_algorithm; |
@@ -58,19 +66,18 @@ uint64_t GetVblockHeaderSize(const uint8_t* vkernel_blob) { |
RSAProcessedKeySize(kernel_sign_algorithm) + /* kernel_sign_key */ |
FIELD_LEN(header_checksum) + |
siglen_map[firmware_sign_algorithm] + /* kernel_key_signature */ |
- FIELD_LEN(kernel_version) + |
- FIELD_LEN(kernel_len) + |
- siglen_map[kernel_sign_algorithm] + /* config_signature */ |
+ GetKernelPreambleLen() + |
+ siglen_map[kernel_sign_algorithm] + /* preamble_signature */ |
siglen_map[kernel_sign_algorithm]); /* kernel_signature */ |
return len; |
} |
-int VerifyKernelHeader(const uint8_t* firmware_key_blob, |
- const uint8_t* header_blob, |
- const int dev_mode, |
- int* firmware_algorithm, |
- int* kernel_algorithm, |
- int* kernel_header_len) { |
+int VerifyKernelKeyHeader(const uint8_t* firmware_key_blob, |
+ const uint8_t* header_blob, |
+ const int dev_mode, |
+ int* firmware_algorithm, |
+ int* kernel_algorithm, |
+ int* kernel_header_len) { |
int kernel_sign_key_len; |
int firmware_sign_key_len; |
uint16_t header_version, header_len; |
@@ -115,7 +122,7 @@ int VerifyKernelHeader(const uint8_t* firmware_key_blob, |
if (header_len != (base_header_checksum_offset + |
kernel_sign_key_len + |
FIELD_LEN(header_checksum))) { |
- debug("VerifyKernelHeader: Header length mismatch\n"); |
+ debug("VerifyKernelKeyHeader: Header length mismatch\n"); |
return VERIFY_KERNEL_INVALID_IMAGE; |
} |
*kernel_header_len = (int) header_len; |
@@ -129,7 +136,7 @@ int VerifyKernelHeader(const uint8_t* firmware_key_blob, |
kernel_sign_key_len), |
FIELD_LEN(header_checksum))) { |
Free(header_checksum); |
- debug("VerifyKernelHeader: Invalid header hash\n"); |
+ debug("VerifyKernelKeyHeader: Invalid header hash\n"); |
return VERIFY_KERNEL_INVALID_IMAGE; |
} |
Free(header_checksum); |
@@ -146,71 +153,43 @@ int VerifyKernelHeader(const uint8_t* firmware_key_blob, |
return 0; |
} |
-int VerifyKernelConfig(RSAPublicKey* kernel_sign_key, |
- const uint8_t* config_blob, |
- int algorithm, |
- uint64_t* kernel_len) { |
- int signature_len = siglen_map[algorithm]; |
- const uint8_t* config_signature = NULL; |
- const uint8_t* kernel_config = NULL; |
- uint8_t* digest = NULL; |
- DigestContext ctx; |
- |
- config_signature = config_blob + (FIELD_LEN(kernel_version) + |
- FIELD_LEN(kernel_len)); |
- kernel_config = config_signature + 2 * signature_len; /* kernel and config |
- * signature. */ |
- /* Since the kernel config signature is computed over the kernel version, |
- * kernel length and config, which does not form a contiguous region memory, |
- * we calculate the message digest ourselves. */ |
- DigestInit(&ctx, algorithm); |
- DigestUpdate(&ctx, |
- config_blob, |
- FIELD_LEN(kernel_version) + FIELD_LEN(kernel_len)); |
- DigestUpdate(&ctx, |
- kernel_config, |
- FIELD_LEN(kernel_config)); |
- digest = DigestFinal(&ctx); |
- if (!RSAVerifyBinaryWithDigest_f( |
- NULL, kernel_sign_key, /* Key to use. */ |
- digest, /* Digest of the Data to verify. */ |
- config_signature, /* Expected signature. */ |
- algorithm)) { |
- Free(digest); |
- return VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED; |
- } |
- Free(digest); |
+int VerifyKernelPreamble(RSAPublicKey* kernel_sign_key, |
+ const uint8_t* preamble_blob, |
+ int algorithm, |
+ uint64_t* kernel_len) { |
+ int preamble_len = GetKernelPreambleLen(); |
+ if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */ |
+ preamble_blob, /* Data to verify */ |
+ preamble_len, /* Length of data */ |
+ preamble_blob + preamble_len, /* Expected Signature */ |
+ algorithm)) |
+ return VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED; |
Memcpy(kernel_len, |
- config_blob + FIELD_LEN(kernel_version), |
+ preamble_blob + FIELD_LEN(kernel_version), |
FIELD_LEN(kernel_len)); |
return 0; |
} |
int VerifyKernelData(RSAPublicKey* kernel_sign_key, |
- const uint8_t* config_blob, |
+ const uint8_t* preamble_blob, |
const uint8_t* kernel_data, |
uint64_t kernel_len, |
int algorithm) { |
int signature_len = siglen_map[algorithm]; |
const uint8_t* kernel_signature = NULL; |
- const uint8_t* kernel_config = NULL; |
uint8_t* digest = NULL; |
DigestContext ctx; |
- kernel_signature = config_blob + (FIELD_LEN(kernel_version) + |
- FIELD_LEN(kernel_len) + |
- signature_len); |
- kernel_config = kernel_signature + signature_len; |
+ kernel_signature = preamble_blob + (GetKernelPreambleLen() + |
+ signature_len); |
- /* Since the kernel signature is computed over the kernel version, length, |
- * config cmd line, and kernel image data, which does not form a contiguous |
+ /* Since the kernel signature is computed over the kernel preamble |
+ * and kernel image data, which does not form a contiguous |
* region of memory, we calculate the message digest ourselves. */ |
DigestInit(&ctx, algorithm); |
DigestUpdate(&ctx, |
- config_blob, |
- FIELD_LEN(kernel_version) + FIELD_LEN(kernel_len)); |
- DigestUpdate(&ctx, kernel_config, |
- FIELD_LEN(kernel_config)); |
+ preamble_blob, |
+ GetKernelPreambleLen()); |
DigestUpdate(&ctx, kernel_data, kernel_len); |
digest = DigestFinal(&ctx); |
if (!RSAVerifyBinaryWithDigest_f( |
@@ -225,6 +204,65 @@ int VerifyKernelData(RSAPublicKey* kernel_sign_key, |
return 0; |
} |
+int VerifyKernelHeader(const uint8_t* firmware_key_blob, |
+ const uint8_t* kernel_header_blob, |
+ const int dev_mode, |
+ const uint8_t** preamble_blob, |
+ const uint8_t** expected_kernel_signature, |
+ RSAPublicKey** kernel_sign_key, |
+ int* kernel_sign_algorithm, |
+ uint64_t* kernel_len) { |
+ int error_code; |
+ int firmware_sign_algorithm; /* Firmware signing key algorithm. */ |
+ int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len, |
+ header_len; |
+ const uint8_t* header_ptr; /* Pointer to header. */ |
+ const uint8_t* kernel_sign_key_ptr; /* Pointer to signing key. */ |
+ |
+ /* Note: All the offset calculations are based on struct FirmwareImage which |
Randall Spangler
2010/05/26 16:35:23
KernelImage
|
+ * is defined in include/firmware_image.h. */ |
+ |
+ /* Compare magic bytes. */ |
+ if (SafeMemcmp(kernel_header_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) |
+ return VERIFY_KERNEL_WRONG_MAGIC; |
+ 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, |
+ &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, |
+ kernel_sign_key_len); |
+ kernel_signature_len = siglen_map[*kernel_sign_algorithm]; |
+ kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; |
+ |
+ /* Only continue if preamble verification succeeds. */ |
+ *preamble_blob = (header_ptr + header_len + kernel_key_signature_len); |
+ if ((error_code = VerifyKernelPreamble(*kernel_sign_key, *preamble_blob, |
+ *kernel_sign_algorithm, |
+ kernel_len))) { |
+ RSAPublicKeyFree(*kernel_sign_key); |
+ return error_code; /* AKA jump to recovery. */ |
+ } |
+ *expected_kernel_signature = (*preamble_blob + |
+ GetKernelPreambleLen() + |
+ kernel_signature_len); /* Skip preamble. */ |
+ return 0; |
+} |
+ |
int VerifyKernel(const uint8_t* firmware_key_blob, |
const uint8_t* kernel_blob, |
const int dev_mode) { |
@@ -237,7 +275,7 @@ int VerifyKernel(const uint8_t* firmware_key_blob, |
uint64_t kernel_len; |
const uint8_t* header_ptr; /* Pointer to header. */ |
const uint8_t* kernel_sign_key_ptr; /* Pointer to signing key. */ |
- const uint8_t* config_ptr; /* Pointer to kernel config block. */ |
+ const uint8_t* preamble_ptr; /* Pointer to kernel preamble block. */ |
const uint8_t* kernel_ptr; /* Pointer to kernel signature/data. */ |
/* Note: All the offset calculations are based on struct FirmwareImage which |
@@ -249,9 +287,9 @@ int VerifyKernel(const uint8_t* firmware_key_blob, |
header_ptr = kernel_blob + KERNEL_MAGIC_SIZE; |
/* Only continue if header verification succeeds. */ |
- if ((error_code = VerifyKernelHeader(firmware_key_blob, header_ptr, dev_mode, |
- &firmware_sign_algorithm, |
- &kernel_sign_algorithm, &header_len))) { |
+ if ((error_code = VerifyKernelKeyHeader(firmware_key_blob, header_ptr, dev_mode, |
+ &firmware_sign_algorithm, |
+ &kernel_sign_algorithm, &header_len))) { |
debug("VerifyKernel: Kernel header verification failed.\n"); |
return error_code; /* AKA jump to recovery. */ |
} |
@@ -268,23 +306,21 @@ int VerifyKernel(const uint8_t* firmware_key_blob, |
kernel_signature_len = siglen_map[kernel_sign_algorithm]; |
kernel_key_signature_len = siglen_map[firmware_sign_algorithm]; |
- /* Only continue if config verification succeeds. */ |
- config_ptr = (header_ptr + header_len + kernel_key_signature_len); |
- if ((error_code = VerifyKernelConfig(kernel_sign_key, config_ptr, |
- kernel_sign_algorithm, |
- &kernel_len))) { |
+ /* Only continue if preamble verification succeeds. */ |
+ preamble_ptr = (header_ptr + header_len + kernel_key_signature_len); |
+ if ((error_code = VerifyKernelPreamble(kernel_sign_key, preamble_ptr, |
+ kernel_sign_algorithm, |
+ &kernel_len))) { |
RSAPublicKeyFree(kernel_sign_key); |
return error_code; /* AKA jump to recovery. */ |
} |
/* Only continue if kernel data verification succeeds. */ |
- kernel_ptr = (config_ptr + |
- FIELD_LEN(kernel_version) + |
- FIELD_LEN(kernel_len) + |
- 2 * kernel_signature_len + /* config and kernel signature. */ |
- FIELD_LEN(kernel_config)); |
+ kernel_ptr = (preamble_ptr + |
+ GetKernelPreambleLen() + |
+ 2 * kernel_signature_len); /* preamble and kernel signature. */ |
if ((error_code = VerifyKernelData(kernel_sign_key, /* Verification key */ |
- config_ptr, /* Start of config block */ |
+ preamble_ptr, /* Start of preamble */ |
kernel_ptr, /* Start of kernel image */ |
kernel_len, /* Length of kernel image. */ |
kernel_sign_algorithm))) { |