Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Unified Diff: src/platform/vboot_reference/vkernel/kernel_image_fw.c

Issue 2234003: Change kernel vboot header layout and add support for separate header verification. (Closed) Base URL: ssh://git@gitrw.chromium.org/chromiumos
Patch Set: add verifykernelheader(). rename old function to verifykernelkeyheader(). Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/platform/vboot_reference/vkernel/kernel_image.c ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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))) {
« no previous file with comments | « src/platform/vboot_reference/vkernel/kernel_image.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698