summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/kernel_splicing_tests.c10
-rw-r--r--tests/test_common.c12
-rw-r--r--tests/test_common.h4
-rw-r--r--vboot_firmware/include/kernel_image_fw.h33
-rw-r--r--vboot_firmware/lib/kernel_image_fw.c80
-rw-r--r--vboot_firmware/linktest/main.c2
-rw-r--r--vkernel/kernel_image.c87
7 files changed, 112 insertions, 116 deletions
diff --git a/tests/kernel_splicing_tests.c b/tests/kernel_splicing_tests.c
index 9335d935..241f1096 100644
--- a/tests/kernel_splicing_tests.c
+++ b/tests/kernel_splicing_tests.c
@@ -65,12 +65,12 @@ void VerifyKernelSplicingTest()
Memcpy(image2->kernel_data, image1->kernel_data,
image2->kernel_len);
- TEST_EQ(VerifyKernelImage(firmware_key, image2, 0),
- VERIFY_KERNEL_SIGNATURE_FAILED,
- "KernelImage kernel_data Splicing");
+ TEST_NEQ(VerifyKernelImage(firmware_key, image2, 0),
+ VERIFY_KERNEL_SUCCESS,
+ "KernelImage kernel_data Splicing");
kernel_blob = GetKernelBlob(image2, &len);
- TEST_EQ(VerifyKernel(firmware_key_blob, kernel_blob, 0),
- VERIFY_KERNEL_SIGNATURE_FAILED,
+ TEST_NEQ(VerifyKernel(firmware_key_blob, kernel_blob, 0),
+ VERIFY_KERNEL_SUCCESS,
"Kernel Blob kernel_data Splicing");
}
diff --git a/tests/test_common.c b/tests/test_common.c
index 53c6fdf1..5c39413f 100644
--- a/tests/test_common.c
+++ b/tests/test_common.c
@@ -33,6 +33,18 @@ int TEST_EQ(int result, int expected_result, char* testname) {
}
}
+int TEST_NEQ(int result, int not_expected_result, char* testname) {
+ if (result != not_expected_result) {
+ fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname);
+ return 1;
+ }
+ else {
+ fprintf(stderr, "%s Test " COL_RED "FAILED\n" COL_STOP, testname);
+ gTestSuccess = 0;
+ return 0;
+ }
+}
+
FirmwareImage* GenerateTestFirmwareImage(int algorithm,
const uint8_t* firmware_sign_key,
int firmware_key_version,
diff --git a/tests/test_common.h b/tests/test_common.h
index d73dc0ea..c8404154 100644
--- a/tests/test_common.h
+++ b/tests/test_common.h
@@ -13,9 +13,13 @@
#include "kernel_image.h"
extern int gTestSuccess;
+
/* Return 1 if result is equal to expected_result, else return 0.
* Also update the global gTestSuccess flag if test fails. */
int TEST_EQ(int result, int expected_result, char* testname);
+/* Return 0 if result is equal to not_expected_result, else return 1.
+ * Also update the global gTestSuccess flag if test fails. */
+int TEST_NEQ(int result, int not_expected_result, char* testname);
/* Test firmware image generation functions. */
FirmwareImage* GenerateTestFirmwareImage(int algorithm,
diff --git a/vboot_firmware/include/kernel_image_fw.h b/vboot_firmware/include/kernel_image_fw.h
index 17458e6e..03bcf858 100644
--- a/vboot_firmware/include/kernel_image_fw.h
+++ b/vboot_firmware/include/kernel_image_fw.h
@@ -49,15 +49,12 @@ typedef struct KernelImage {
uint64_t bootloader_offset; /* Offset of bootloader in kernel_data. */
uint64_t bootloader_size; /* Size of bootloader in bytes. */
uint64_t padded_header_size; /* start of kernel_data in disk partition */
+ uint8_t* kernel_signature; /* Signature on [kernel_data] below.
+ * NOTE: This is only considered valid
+ * if preamble_signature successfully verifies. */
/* end of preamble */
-
- uint8_t* preamble_signature; /* Signature on the kernel preamble. */
-
- /* The kernel signature comes first as it may allow us to parallelize
- * the kernel data fetch and RSA public key operation.
- */
- uint8_t* kernel_signature; /* Signature on the concatenation of
- * the kernel preamble and [kernel_data]. */
+ uint8_t* preamble_signature; /* signature on preamble, (includes
+ [kernel_signature]) */
uint8_t* kernel_data; /* Actual kernel data. */
} KernelImage;
@@ -74,8 +71,9 @@ typedef struct KernelImage {
extern char* kVerifyKernelErrors[VERIFY_KERNEL_MAX];
-/* Returns the length of the verified boot kernel preamble. */
-uint64_t GetKernelPreambleLen(void);
+/* Returns the length of the verified boot kernel preamble based on
+ * kernel signing algorithm [algorithm]. */
+uint64_t GetKernelPreambleLen(int algorithm);
/* Returns the length of the Kernel Verified Boot header excluding
* [kernel_data].
@@ -111,16 +109,15 @@ int VerifyKernelPreamble(RSAPublicKey* kernel_sign_key,
int algorithm,
uint64_t* kernel_len);
-/* Checks the signature on the kernel data at location [kernel_data_start].
- * The length of the actual kernel data is kernel_len and it is assumed to
- * be prepended with the signature whose size depends on the signature_algorithm
- * [algorithm].
+/* Checks [kernel_signature] on the kernel data at location [kernel_data]. The
+ * signature is assumed to be generated using algorithm [algorithm].
+ * The length of the kernel data is [kernel_len].
*
* Return 0 on success, error code on failure.
*/
int VerifyKernelData(RSAPublicKey* kernel_sign_key,
- const uint8_t* kernel_config_start,
- const uint8_t* kernel_data_start,
+ const uint8_t* kernel_signature,
+ const uint8_t* kernel_data,
uint64_t kernel_len,
int algorithm);
@@ -128,8 +125,7 @@ int VerifyKernelData(RSAPublicKey* kernel_sign_key,
* using the firmware public key [firmware_key_blob]. If [dev_mode] is 1
* (active), then key header verification is skipped.
*
- * Fills in a pointer to preamble blob within [kernel_header_blob] in
- * [preamble_blob], pointer to expected kernel data signature
+ * Fills in a pointer to expected kernel data signature
* within [kernel_header_blob] in [expected_kernel_signature].
*
* The signing key to use for kernel data verification is returned in
@@ -142,7 +138,6 @@ int VerifyKernelData(RSAPublicKey* kernel_sign_key,
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,
diff --git a/vboot_firmware/lib/kernel_image_fw.c b/vboot_firmware/lib/kernel_image_fw.c
index 5a1e9785..5a6afcfa 100644
--- a/vboot_firmware/lib/kernel_image_fw.c
+++ b/vboot_firmware/lib/kernel_image_fw.c
@@ -26,12 +26,13 @@ char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = {
"Wrong Kernel Magic.",
};
-inline uint64_t GetKernelPreambleLen(void) {
+inline uint64_t GetKernelPreambleLen(int algorithm) {
return (FIELD_LEN(kernel_version) +
FIELD_LEN(kernel_len) +
FIELD_LEN(bootloader_offset) +
FIELD_LEN(bootloader_size) +
- FIELD_LEN(padded_header_size));
+ FIELD_LEN(padded_header_size) +
+ siglen_map[algorithm]);
}
uint64_t GetVblockHeaderSize(const uint8_t* vkernel_blob) {
@@ -66,9 +67,8 @@ 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 */
- GetKernelPreambleLen() +
- siglen_map[kernel_sign_algorithm] + /* preamble_signature */
- siglen_map[kernel_sign_algorithm]); /* kernel_signature */
+ GetKernelPreambleLen(kernel_sign_algorithm) +
+ siglen_map[kernel_sign_algorithm]); /* preamble_signature */
return len;
}
@@ -157,7 +157,7 @@ int VerifyKernelPreamble(RSAPublicKey* kernel_sign_key,
const uint8_t* preamble_blob,
int algorithm,
uint64_t* kernel_len) {
- int preamble_len = GetKernelPreambleLen();
+ int preamble_len = GetKernelPreambleLen(algorithm);
if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */
preamble_blob, /* Data to verify */
preamble_len, /* Length of data */
@@ -171,43 +171,23 @@ int VerifyKernelPreamble(RSAPublicKey* kernel_sign_key,
}
int VerifyKernelData(RSAPublicKey* kernel_sign_key,
- const uint8_t* preamble_blob,
+ const uint8_t* kernel_signature,
const uint8_t* kernel_data,
uint64_t kernel_len,
int algorithm) {
- int signature_len = siglen_map[algorithm];
- const uint8_t* kernel_signature = NULL;
- uint8_t* digest = NULL;
- DigestContext ctx;
-
- kernel_signature = preamble_blob + (GetKernelPreambleLen() +
- signature_len);
-
- /* 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,
- preamble_blob,
- GetKernelPreambleLen());
- 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_signature, /* Expected Signature */
- algorithm)) {
- Free(digest);
+
+ if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */
+ kernel_data, /* Data to verify */
+ kernel_len, /* Length of data */
+ kernel_signature, /* Expected Signature */
+ algorithm))
return VERIFY_KERNEL_SIGNATURE_FAILED;
- }
- Free(digest);
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,
@@ -216,8 +196,9 @@ int VerifyKernelHeader(const uint8_t* firmware_key_blob,
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. */
+ 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. */
/* Note: All the offset calculations are based on struct FirmwareImage which
* is defined in include/firmware_image.h. */
@@ -250,16 +231,17 @@ int VerifyKernelHeader(const uint8_t* firmware_key_blob,
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,
+ 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. */
}
- *expected_kernel_signature = (*preamble_blob +
- GetKernelPreambleLen() +
- kernel_signature_len); /* Skip preamble. */
+ *expected_kernel_signature = (preamble_ptr +
+ GetKernelPreambleLen(*kernel_sign_algorithm) -
+ kernel_signature_len); /* Skip beginning of
+ * preamble. */
return 0;
}
@@ -277,13 +259,16 @@ int VerifyKernel(const uint8_t* firmware_key_blob,
const uint8_t* kernel_sign_key_ptr; /* Pointer to signing key. */
const uint8_t* preamble_ptr; /* Pointer to kernel preamble block. */
const uint8_t* kernel_ptr; /* Pointer to kernel signature/data. */
+ const uint8_t* kernel_signature;
/* Note: All the offset calculations are based on struct FirmwareImage which
* is defined in include/firmware_image.h. */
/* Compare magic bytes. */
- if (SafeMemcmp(kernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE))
+ if (SafeMemcmp(kernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) {
+ debug("VerifyKernel: Kernel magic bytes not found.\n");
return VERIFY_KERNEL_WRONG_MAGIC;
+ }
header_ptr = kernel_blob + KERNEL_MAGIC_SIZE;
/* Only continue if header verification succeeds. */
@@ -311,18 +296,21 @@ int VerifyKernel(const uint8_t* firmware_key_blob,
if ((error_code = VerifyKernelPreamble(kernel_sign_key, preamble_ptr,
kernel_sign_algorithm,
&kernel_len))) {
+ debug("VerifyKernel: Kernel preamble verification failed.\n");
RSAPublicKeyFree(kernel_sign_key);
return error_code; /* AKA jump to recovery. */
}
/* Only continue if kernel data verification succeeds. */
kernel_ptr = (preamble_ptr +
- GetKernelPreambleLen() +
- 2 * kernel_signature_len); /* preamble and kernel signature. */
+ GetKernelPreambleLen(kernel_sign_algorithm) +
+ kernel_signature_len); /* preamble signature. */
+ kernel_signature = kernel_ptr - 2 * kernel_signature_len; /* end of kernel
+ * preamble. */
if ((error_code = VerifyKernelData(kernel_sign_key, /* Verification key */
- preamble_ptr, /* Start of preamble */
- kernel_ptr, /* Start of kernel image */
- kernel_len, /* Length of kernel image. */
+ kernel_signature, /* kernel signature */
+ kernel_ptr, /* Start of kernel data */
+ kernel_len, /* Length of kernel data. */
kernel_sign_algorithm))) {
RSAPublicKeyFree(kernel_sign_key);
return error_code; /* AKA jump to recovery. */
diff --git a/vboot_firmware/linktest/main.c b/vboot_firmware/linktest/main.c
index cf08e26b..0897c1ef 100644
--- a/vboot_firmware/linktest/main.c
+++ b/vboot_firmware/linktest/main.c
@@ -21,7 +21,7 @@ int main(void)
VerifyKernelKeyHeader(0, 0, 0, 0, 0, 0);
VerifyKernelPreamble(0, 0, 0, 0);
VerifyKernelData(0, 0, 0, 0, 0);
- VerifyKernelHeader(0, 0, 0, 0, 0, 0, 0, 0);
+ VerifyKernelHeader(0, 0, 0, 0, 0, 0, 0);
VerifyKernel(0, 0, 0);
GetLogicalKernelVersion(0);
VerifyKernelDriver_f(0, 0, 0, 0);
diff --git a/vkernel/kernel_image.c b/vkernel/kernel_image.c
index fc71f35b..5eeb784f 100644
--- a/vkernel/kernel_image.c
+++ b/vkernel/kernel_image.c
@@ -222,8 +222,9 @@ uint8_t* GetKernelPreambleBlob(const KernelImage* image) {
uint8_t* preamble_blob = NULL;
MemcpyState st;
- preamble_blob = (uint8_t*) Malloc(GetKernelPreambleLen());
- st.remaining_len = GetKernelPreambleLen();
+ preamble_blob = (uint8_t*) Malloc(
+ GetKernelPreambleLen(image->kernel_sign_algorithm));
+ st.remaining_len = GetKernelPreambleLen(image->kernel_sign_algorithm);
st.remaining_buf = preamble_blob;
st.overrun = 0;
@@ -233,6 +234,8 @@ uint8_t* GetKernelPreambleBlob(const KernelImage* image) {
StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size));
StatefulMemcpy_r(&st, &image->padded_header_size,
FIELD_LEN(padded_header_size));
+ StatefulMemcpy_r(&st, image->kernel_signature,
+ siglen_map[image->kernel_sign_algorithm]);
if (st.overrun || st.remaining_len != 0) { /* Overrun or Underrun. */
Free(preamble_blob);
@@ -255,8 +258,8 @@ uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) {
*blob_len = (FIELD_LEN(magic) +
GetKernelHeaderLen(image) +
kernel_key_signature_len +
- GetKernelPreambleLen() +
- 2 * kernel_signature_len +
+ GetKernelPreambleLen(image->kernel_sign_algorithm) +
+ kernel_signature_len +
image->kernel_len);
kernel_blob = (uint8_t*) Malloc(*blob_len);
st.remaining_len = *blob_len;
@@ -276,13 +279,14 @@ uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) {
StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size));
StatefulMemcpy_r(&st, &image->padded_header_size,
FIELD_LEN(padded_header_size));
- StatefulMemcpy_r(&st, image->preamble_signature, kernel_signature_len);
StatefulMemcpy_r(&st, image->kernel_signature, kernel_signature_len);
+ StatefulMemcpy_r(&st, image->preamble_signature, kernel_signature_len);
StatefulMemcpy_r(&st, image->kernel_data, image->kernel_len);
Free(header_blob);
if (st.overrun || st.remaining_len != 0) { /* Underrun or Overrun. */
+ debug("GetKernelBlob() failed.\n");
Free(kernel_blob);
return NULL;
}
@@ -371,7 +375,6 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key,
int kernel_signature_size;
int error_code = 0;
DigestContext ctx;
- DigestContext kernel_ctx;
if (!image)
return VERIFY_KERNEL_INVALID_IMAGE;
@@ -433,6 +436,8 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key,
FIELD_LEN(bootloader_size));
DigestUpdate(&ctx, (uint8_t*) &image->padded_header_size,
FIELD_LEN(padded_header_size));
+ DigestUpdate(&ctx, (uint8_t*) image->kernel_signature,
+ kernel_signature_size);
preamble_digest = DigestFinal(&ctx);
if (!RSAVerify(kernel_sign_key, image->preamble_signature,
kernel_signature_size, image->kernel_sign_algorithm,
@@ -442,21 +447,14 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key,
}
/* Verify kernel signature - kernel signature is computed on the contents
- of kernel version + kernel options + kernel_data. */
- DigestInit(&kernel_ctx, image->kernel_sign_algorithm);
- DigestUpdate(&kernel_ctx, (uint8_t*) &image->kernel_version,
- FIELD_LEN(kernel_version));
- DigestUpdate(&kernel_ctx, (uint8_t*) &image->kernel_len,
- FIELD_LEN(kernel_len));
- DigestUpdate(&kernel_ctx, (uint8_t*) &image->bootloader_offset,
- FIELD_LEN(bootloader_offset));
- DigestUpdate(&kernel_ctx, (uint8_t*) &image->bootloader_size,
- FIELD_LEN(bootloader_size));
- DigestUpdate(&kernel_ctx, (uint8_t*) &image->padded_header_size,
- FIELD_LEN(padded_header_size));
- DigestUpdate(&kernel_ctx, (uint8_t*) image->kernel_data,
- image->kernel_len);
- kernel_digest = DigestFinal(&kernel_ctx);
+ * of kernel_data.
+ * Association between the kernel_data and preamble is maintained by making
+ * the kernel signature a part of the preamble and verifying it as part
+ * of preamble signature checking. */
+
+ kernel_digest = DigestBuf(image->kernel_data,
+ image->kernel_len,
+ image->kernel_sign_algorithm);
if (!RSAVerify(kernel_sign_key, image->kernel_signature,
kernel_signature_size, image->kernel_sign_algorithm,
kernel_digest)) {
@@ -505,33 +503,17 @@ int AddKernelSignature(KernelImage* image,
uint8_t* preamble_signature = NULL;
uint8_t* kernel_signature = NULL;
uint8_t* kernel_buf;
- int signature_len = siglen_map[image->kernel_sign_algorithm];
+ int algorithm = image->kernel_sign_algorithm;
+ int signature_len = siglen_map[algorithm];
- preamble_blob = GetKernelPreambleBlob(image);
- if (!(preamble_signature = SignatureBuf(preamble_blob,
- GetKernelPreambleLen(),
- kernel_signing_key_file,
- image->kernel_sign_algorithm))) {
- debug("Could not compute signature on the kernel preamble.\n");
- Free(preamble_blob);
- return 0;
- }
-
- image->preamble_signature = (uint8_t*) Malloc(signature_len);
- Memcpy(image->preamble_signature, preamble_signature, signature_len);
- Free(preamble_signature);
- /* Kernel signature muse be calculated on the kernel version, options and
- * kernel data to avoid splicing attacks. */
- kernel_buf = (uint8_t*) Malloc(GetKernelPreambleLen() +
- image->kernel_len);
- Memcpy(kernel_buf, preamble_blob, GetKernelPreambleLen());
- Memcpy(kernel_buf + GetKernelPreambleLen(), image->kernel_data,
- image->kernel_len);
+ /* Kernel signature must be calculated first as its used for computing the
+ * preamble signature. */
+ kernel_buf = (uint8_t*) Malloc(image->kernel_len);
+ Memcpy(kernel_buf, image->kernel_data, image->kernel_len);
if (!(kernel_signature = SignatureBuf(kernel_buf,
- GetKernelPreambleLen() +
image->kernel_len,
kernel_signing_key_file,
- image->kernel_sign_algorithm))) {
+ algorithm))) {
Free(preamble_blob);
Free(kernel_buf);
debug("Could not compute signature on the kernel.\n");
@@ -539,9 +521,24 @@ int AddKernelSignature(KernelImage* image,
}
image->kernel_signature = (uint8_t*) Malloc(signature_len);
Memcpy(image->kernel_signature, kernel_signature, signature_len);
+
+
+ preamble_blob = GetKernelPreambleBlob(image);
+ if (!(preamble_signature = SignatureBuf(preamble_blob,
+ GetKernelPreambleLen(algorithm),
+ kernel_signing_key_file,
+ algorithm))) {
+ debug("Could not compute signature on the kernel preamble.\n");
+ Free(preamble_blob);
+ return 0;
+ }
+ image->preamble_signature = (uint8_t*) Malloc(signature_len);
+ Memcpy(image->preamble_signature, preamble_signature, signature_len);
+
+ Free(preamble_signature);
+ Free(preamble_blob);
Free(kernel_signature);
Free(kernel_buf);
- Free(preamble_blob);
return 1;
}