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

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

Issue 1732022: VBoot Reference: Make kernel_config a 4K byte block, and move it after the verified boot block. (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: Created 10 years, 8 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
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 734111c6840e75acb8be72adaf721a586f443f25..23111e93cd042732da327f85a38955e8fbe28c2c 100644
--- a/src/platform/vboot_reference/vkernel/kernel_image_fw.c
+++ b/src/platform/vboot_reference/vkernel/kernel_image_fw.c
@@ -15,11 +15,6 @@
/* Macro to determine the size of a field structure in the KernelImage
* structure. */
#define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field))
-#define KERNEL_CONFIG_FIELD_LEN (FIELD_LEN(kernel_version) + FIELD_LEN(options.version) + \
- FIELD_LEN(options.cmd_line) + \
- FIELD_LEN(options.kernel_len) + \
- FIELD_LEN(options.kernel_load_addr) + \
- FIELD_LEN(options.kernel_entry_addr))
char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = {
"Success.",
@@ -31,6 +26,45 @@ char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = {
"Wrong Kernel Magic.",
};
+uint64_t GetVblockHeaderSize(const uint8_t* vkernel_blob) {
+ uint64_t len = 0;
+ uint16_t firmware_sign_algorithm;
+ uint16_t kernel_sign_algorithm;
+ int algorithms_offset = (FIELD_LEN(magic) +
+ FIELD_LEN(header_version) +
+ FIELD_LEN(header_len));
+ if (SafeMemcmp(vkernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) {
+ debug("Not a valid verified boot kernel blob.\n");
+ return 0;
+ }
+ Memcpy(&firmware_sign_algorithm,
+ vkernel_blob + algorithms_offset,
+ sizeof(firmware_sign_algorithm));
+ Memcpy(&kernel_sign_algorithm,
+ vkernel_blob + algorithms_offset + FIELD_LEN(kernel_sign_algorithm),
+ sizeof(kernel_sign_algorithm));
+ if (firmware_sign_algorithm >= kNumAlgorithms) {
+ debug("Invalid firmware signing algorithm.\n");
+ return 0;
+ }
+ if (kernel_sign_algorithm >= kNumAlgorithms) {
+ debug("Invalid kernel signing algorithm.\n");
+ return 0;
+ }
+ len = algorithms_offset; /* magic, header length and version. */
+ len += (FIELD_LEN(firmware_sign_algorithm) +
+ FIELD_LEN(kernel_sign_algorithm) +
+ FIELD_LEN(kernel_key_version) +
+ 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 */
+ 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,
@@ -116,43 +150,73 @@ int VerifyKernelConfig(RSAPublicKey* kernel_sign_key,
const uint8_t* config_blob,
int algorithm,
uint64_t* kernel_len) {
- uint64_t len;
- if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */
- config_blob, /* Data to verify */
- KERNEL_CONFIG_FIELD_LEN, /* Length of data */
- config_blob + KERNEL_CONFIG_FIELD_LEN, /* Expected
- * Signature */
- algorithm))
- return VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED;
+ int signature_len = siglen_map[algorithm];
+ const uint8_t* config_signature = NULL;
+ const uint8_t* kernel_config = NULL;
+ uint8_t* digest = NULL;
+ DigestContext ctx;
- Memcpy(&len,
- config_blob + (FIELD_LEN(kernel_version) + FIELD_LEN(options.version) +
- FIELD_LEN(options.cmd_line)),
- sizeof(len));
- *kernel_len = len;
+ 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);
+ Memcpy(kernel_len,
+ config_blob + FIELD_LEN(kernel_version),
+ FIELD_LEN(kernel_len));
return 0;
}
int VerifyKernelData(RSAPublicKey* kernel_sign_key,
- const uint8_t* kernel_config_start,
- const uint8_t* kernel_data_start,
+ const uint8_t* config_blob,
+ const uint8_t* kernel_data,
uint64_t kernel_len,
int algorithm) {
int signature_len = siglen_map[algorithm];
- uint8_t* digest;
+ const uint8_t* kernel_signature = NULL;
+ const uint8_t* kernel_config = NULL;
+ uint8_t* digest = NULL;
DigestContext ctx;
- /* Since the kernel signature is computed over the kernel version, options
- * and data, which does not form a contiguous region of memory, we calculate
- * the message digest ourselves. */
+ kernel_signature = config_blob + (FIELD_LEN(kernel_version) +
+ FIELD_LEN(kernel_len) +
+ signature_len);
+ kernel_config = kernel_signature + 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
+ * region of memory, we calculate the message digest ourselves. */
DigestInit(&ctx, algorithm);
- DigestUpdate(&ctx, kernel_config_start, KERNEL_CONFIG_FIELD_LEN);
- DigestUpdate(&ctx, kernel_data_start + signature_len, kernel_len);
+ DigestUpdate(&ctx,
+ config_blob,
+ FIELD_LEN(kernel_version) + FIELD_LEN(kernel_len));
+ DigestUpdate(&ctx, kernel_config,
+ FIELD_LEN(kernel_config));
+ DigestUpdate(&ctx, kernel_data, kernel_len);
digest = DigestFinal(&ctx);
if (!RSAVerifyBinaryWithDigest_f(
NULL, kernel_sign_key, /* Key to use. */
digest, /* Digest of the data to verify. */
- kernel_data_start, /* Expected Signature */
+ kernel_signature, /* Expected Signature */
algorithm)) {
Free(digest);
return VERIFY_KERNEL_SIGNATURE_FAILED;
@@ -214,11 +278,15 @@ int VerifyKernel(const uint8_t* firmware_key_blob,
}
/* Only continue if kernel data verification succeeds. */
kernel_ptr = (config_ptr +
- KERNEL_CONFIG_FIELD_LEN + /* Skip config block/signature. */
- kernel_signature_len);
-
- if ((error_code = VerifyKernelData(kernel_sign_key, config_ptr, kernel_ptr,
- kernel_len,
+ FIELD_LEN(kernel_version) +
+ FIELD_LEN(kernel_len) +
+ 2 * kernel_signature_len + /* config and kernel signature. */
+ FIELD_LEN(kernel_config));
+
+ if ((error_code = VerifyKernelData(kernel_sign_key, /* Verification key */
+ config_ptr, /* Start of config block */
+ kernel_ptr, /* Start of kernel image */
+ kernel_len, /* Length of kernel image. */
kernel_sign_algorithm))) {
RSAPublicKeyFree(kernel_sign_key);
return error_code; /* AKA jump to recovery. */
@@ -248,6 +316,7 @@ uint32_t GetLogicalKernelVersion(uint8_t* kernel_blob) {
return 0;
if (kernel_sign_algorithm >= kNumAlgorithms)
return 0;
+
kernel_key_signature_len = siglen_map[firmware_sign_algorithm];
kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm);
kernel_ptr += (FIELD_LEN(kernel_key_version) +

Powered by Google App Engine
This is Rietveld 408576698