diff --git a/tests/kernel_image_tests.c b/tests/kernel_image_tests.c index 15f75bd418..4890de3a18 100644 --- a/tests/kernel_image_tests.c +++ b/tests/kernel_image_tests.c @@ -40,14 +40,14 @@ void VerifyKernelImageTest(KernelImage* image, /* Tampered KernelImage Verification Tests. */ void VerifyKernelImageTamperTest(KernelImage* image, RSAPublicKey* firmware_key) { - image->kernel_config[0] ^= 0xFF; + image->bootloader_offset ^= 0xFF; TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_ENABLED), - VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED, + VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED, "KernelImage Config Tamper Verification (Dev Mode)"); TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_DISABLED), - VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED, + VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED, "KernelImage Config Tamper Verification (Trusted)"); - image->kernel_config[0] ^= 0xFF; + image->bootloader_offset ^= 0xFF; image->kernel_data[0] = 'T'; TEST_EQ(VerifyKernelImage(firmware_key, image, DEV_MODE_ENABLED), diff --git a/tests/test_common.c b/tests/test_common.c index 6027a89371..53c6fdf166 100644 --- a/tests/test_common.c +++ b/tests/test_common.c @@ -160,7 +160,9 @@ KernelImage* GenerateTestKernelImage(int firmware_sign_algorithm, /* Populate kernel options and data with dummy data. */ image->kernel_version = kernel_version; - Memset(image->kernel_config, 0, sizeof(image->kernel_config)); + image->bootloader_offset = 0; + image->bootloader_size = 512; + image->padded_header_size = 100; image->kernel_len = kernel_len; image->kernel_key_signature = image->kernel_signature = NULL; image->kernel_data = Malloc(kernel_len); diff --git a/utility/include/kernel_utility.h b/utility/include/kernel_utility.h index 16967adbdc..5b0cab398c 100644 --- a/utility/include/kernel_utility.h +++ b/utility/include/kernel_utility.h @@ -58,11 +58,6 @@ class KernelUtility { std::string firmware_key_pub_file_; std::string kernel_key_file_; // Private key for signing the kernel. std::string kernel_key_pub_file_; - std::string config_file_; // File containing kernel config options. - // TODO(gauravsh): Currently this just fills in options.cmd_line in struct - // KernelImage (from vkernel/kernel_image_fw.h). Ideally we'd like to have - // a well defined config file format which is also backwards compatible with - // Legacy BIOS boot loaders. // Fields of a KernelImage. (read from the command line). int header_version_; diff --git a/utility/kernel_utility.cc b/utility/kernel_utility.cc index e979b760d5..7a1e66903e 100644 --- a/utility/kernel_utility.cc +++ b/utility/kernel_utility.cc @@ -36,7 +36,6 @@ KernelUtility::KernelUtility(): image_(NULL), kernel_key_version_(-1), kernel_version_(-1), kernel_len_(0), - kernel_config_(NULL), is_generate_(false), is_verify_(false), is_describe_(false), @@ -44,7 +43,6 @@ KernelUtility::KernelUtility(): image_(NULL), } KernelUtility::~KernelUtility() { - Free(kernel_config_); RSAPublicKeyFree(firmware_key_pub_); KernelImageFree(image_); } @@ -70,7 +68,6 @@ void KernelUtility::PrintUsage(void) { "--in \t\tKernel Image to sign\n" "--out \t\tOutput file for verified boot Kernel image\n\n" "Optional arguments for \"--generate\" include:\n" - "--config \t\t\tPopulate contents of kernel config from a file\n" "--vblock\t\t\tJust output the verification block\n\n" " (for --*_sign_algorithm) is one of the following:\n"; for (int i = 0; i < kNumAlgorithms; i++) { @@ -95,7 +92,6 @@ bool KernelUtility::ParseCmdLineOptions(int argc, char* argv[]) { OPT_GENERATE, OPT_VERIFY, OPT_DESCRIBE, - OPT_CONFIG, OPT_VBLOCK, }; static struct option long_options[] = { @@ -112,7 +108,6 @@ bool KernelUtility::ParseCmdLineOptions(int argc, char* argv[]) { {"generate", 0, 0, OPT_GENERATE }, {"verify", 0, 0, OPT_VERIFY }, {"describe", 0, 0, OPT_DESCRIBE }, - {"config", 1, 0, OPT_CONFIG }, {"vblock", 0, 0, OPT_VBLOCK }, {NULL, 0, 0, 0} }; @@ -176,9 +171,6 @@ bool KernelUtility::ParseCmdLineOptions(int argc, char* argv[]) { case OPT_DESCRIBE: is_describe_ = true; break; - case OPT_CONFIG: - config_file_ = optarg; - break; case OPT_VBLOCK: is_only_vblock_ = true; break; @@ -206,7 +198,6 @@ void KernelUtility::DescribeSignedImage(void) { } bool KernelUtility::GenerateSignedImage(void) { - uint64_t len; uint64_t kernel_key_pub_len; image_ = KernelImageNew(); @@ -230,18 +221,6 @@ bool KernelUtility::GenerateSignedImage(void) { CalculateKernelHeaderChecksum(image_, image_->header_checksum); image_->kernel_version = kernel_version_; - if (!config_file_.empty()) { - kernel_config_ = BufferFromFile(config_file_.c_str(), &len); - if (len >= sizeof(image_->kernel_config)) { - cerr << "Input kernel config file is too big!"; - return false; - } - Memcpy(image_->kernel_config, - kernel_config_, len); - } else { - Memset(image_->kernel_config, 0, - sizeof(image_->kernel_config)); - } image_->kernel_data = BufferFromFile(in_file_.c_str(), &image_->kernel_len); if (!image_->kernel_data) diff --git a/vboot_firmware/include/kernel_image_fw.h b/vboot_firmware/include/kernel_image_fw.h index 3e00ec275a..17458e6edf 100644 --- a/vboot_firmware/include/kernel_image_fw.h +++ b/vboot_firmware/include/kernel_image_fw.h @@ -15,7 +15,6 @@ #define KERNEL_MAGIC "CHROMEOS" #define KERNEL_MAGIC_SIZE 8 -#define KERNEL_CONFIG_SIZE 4096 #define DEV_MODE_ENABLED 1 #define DEV_MODE_DISABLED 0 @@ -41,7 +40,7 @@ typedef struct KernelImage { * firmware_sign_algorithm, * sign_algorithm, sign_key, * key_version] */ - + /* End of kernel key header. */ uint8_t* kernel_key_signature; /* Signature of the header above. */ /* Kernel preamble */ @@ -49,18 +48,16 @@ typedef struct KernelImage { uint64_t kernel_len; /* Length of the actual kernel image. */ uint64_t bootloader_offset; /* Offset of bootloader in kernel_data. */ uint64_t bootloader_size; /* Size of bootloader in bytes. */ - uint8_t* config_signature; /* Signature on the concatenation of - * [kernel_version], [kernel_len] and - * [kernel_config]. */ + uint64_t padded_header_size; /* start of kernel_data in disk partition */ + /* 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 - * [kernel_version], [kernel_len], [kernel_config] - * and [kernel_data]. */ - /* The kernel config string is stored right before the kernel image data for - * easy mapping while loading into the memory. */ - uint8_t kernel_config[KERNEL_CONFIG_SIZE]; /* Kernel Config command line. */ + * the kernel preamble and [kernel_data]. */ uint8_t* kernel_data; /* Actual kernel data. */ } KernelImage; @@ -70,50 +67,52 @@ typedef struct KernelImage { #define VERIFY_KERNEL_INVALID_IMAGE 1 #define VERIFY_KERNEL_KEY_SIGNATURE_FAILED 2 #define VERIFY_KERNEL_INVALID_ALGORITHM 3 -#define VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED 4 +#define VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED 4 #define VERIFY_KERNEL_SIGNATURE_FAILED 5 #define VERIFY_KERNEL_WRONG_MAGIC 6 #define VERIFY_KERNEL_MAX 7 /* Generic catch-all. */ extern char* kVerifyKernelErrors[VERIFY_KERNEL_MAX]; +/* Returns the length of the verified boot kernel preamble. */ +uint64_t GetKernelPreambleLen(void); + /* Returns the length of the Kernel Verified Boot header excluding - * [kernel_config] and [kernel_data]. + * [kernel_data]. * * This is always non-zero, so a return value of 0 signifies an error. */ uint64_t GetVBlockHeaderSize(const uint8_t* vkernel_blob); -/* Checks for the sanity of the kernel header pointed by [kernel_header_blob]. - * If [dev_mode] is enabled, also checks the firmware key signature using the +/* Checks for the sanity of the kernel key header at [kernel_header_blob]. + * If [dev_mode] is enabled, also checks the kernel key signature using the * pre-processed public firmware signing key [firmware_sign_key_blob]. * - * On success, put firmware signature algorithm in [firmware_algorithm], + * On success, puts firmware signature algorithm in [firmware_algorithm], * kernel signature algorithm in [kernel_algorithm], kernel header * length in [header_len], and return 0. * Else, return error code on failure. */ -int VerifyKernelHeader(const uint8_t* firmware_sign_key_blob, - const uint8_t* kernel_header_blob, - const int dev_mode, - int* firmware_algorithm, - int* kernel_algorithm, - int* header_len); +int VerifyKernelKeyHeader(const uint8_t* firmware_sign_key_blob, + const uint8_t* kernel_header_blob, + const int dev_mode, + int* firmware_algorithm, + int* kernel_algorithm, + int* header_len); -/* Checks the kernel config (analogous to preamble for firmware) signature on - * kernel config pointed by [kernel_config_blob] using the signing key - * [kernel_sign_key]. +/* Checks the kernel preamble signature at [kernel_preamble_blob] + * using the signing key [kernel_sign_key]. * * On success, put kernel length into [kernel_len], and return 0. * Else, return error code on failure. */ -int VerifyKernelConfig(RSAPublicKey* kernel_sign_key, - const uint8_t* kernel_config_blob, - int algorithm, - uint64_t* kernel_len); +int VerifyKernelPreamble(RSAPublicKey* kernel_sign_key, + const uint8_t* kernel_preamble_blob, + 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 + * 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]. * @@ -125,13 +124,35 @@ int VerifyKernelData(RSAPublicKey* kernel_sign_key, uint64_t kernel_len, int algorithm); +/* Verifies the kernel key header and preamble at [kernel_header_blob] + * 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 + * within [kernel_header_blob] in [expected_kernel_signature]. + * + * The signing key to use for kernel data verification is returned in + * [kernel_sign_key], This must be free-d explicitly by the caller after use. + * The kernel signing algorithm is returned in [kernel_sign_algorithm] and its + * length in [kernel_len]. + * + * Returns 0 on success, error code on failure. + */ +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); + /* Performs a chained verify of the kernel blob [kernel_blob]. If * [dev_mode] is 0 [inactive], then the pre-processed public signing key * [root_key_blob] is used to verify the signature of the signing key, * else the check is skipped. * - * TODO(gauravsh): Does the dev mode only effect the R/W firmware verification, - * or kernel verification, or both? * * Returns 0 on success, error code on failure. * diff --git a/vboot_firmware/lib/kernel_image_fw.c b/vboot_firmware/lib/kernel_image_fw.c index 23111e93cd..5a1e978594 100644 --- a/vboot_firmware/lib/kernel_image_fw.c +++ b/vboot_firmware/lib/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 + * 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))) { diff --git a/vkernel/kernel_image.c b/vkernel/kernel_image.c index 6833ef64bd..fc71f35bc0 100644 --- a/vkernel/kernel_image.c +++ b/vkernel/kernel_image.c @@ -29,10 +29,7 @@ KernelImage* KernelImageNew(void) { if (image) { image->kernel_sign_key = NULL; image->kernel_key_signature = NULL; - Memset(image->kernel_config, - 0, - sizeof(image->kernel_config)); - image->config_signature = NULL; + image->preamble_signature = NULL; image->kernel_signature = NULL; image->kernel_data = NULL; } @@ -43,7 +40,7 @@ void KernelImageFree(KernelImage* image) { if (image) { Free(image->kernel_sign_key); Free(image->kernel_key_signature); - Free(image->config_signature); + Free(image->preamble_signature); Free(image->kernel_signature); Free(image->kernel_data); Free(image); @@ -136,18 +133,21 @@ KernelImage* ReadKernelImage(const char* input_file) { StatefulMemcpy(&st, image->kernel_key_signature, kernel_key_signature_len); - /* Read the kernel config. */ + /* Read the kernel preamble. */ 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)); /* Read config and kernel signatures. */ - image->config_signature = (uint8_t*) Malloc(kernel_signature_len); - StatefulMemcpy(&st, image->config_signature, kernel_signature_len); + image->preamble_signature = (uint8_t*) Malloc(kernel_signature_len); + StatefulMemcpy(&st, image->preamble_signature, kernel_signature_len); image->kernel_signature = (uint8_t*) Malloc(kernel_signature_len); StatefulMemcpy(&st, image->kernel_signature, kernel_signature_len); - /* Read kernel config command line and kernel image data. */ - StatefulMemcpy(&st, image->kernel_config, FIELD_LEN(kernel_config)); + /* Read kernel image data. */ image->kernel_data = (uint8_t*) Malloc(image->kernel_len); StatefulMemcpy(&st, image->kernel_data, image->kernel_len); @@ -218,30 +218,27 @@ uint8_t* GetKernelHeaderBlob(const KernelImage* image) { return header_blob; } -int GetKernelConfigLen(const KernelImage* image) { - return (FIELD_LEN(kernel_version) + - FIELD_LEN(kernel_len) + - FIELD_LEN(kernel_config)); -} - -uint8_t* GetKernelConfigBlob(const KernelImage* image) { - uint8_t* config_blob = NULL; +uint8_t* GetKernelPreambleBlob(const KernelImage* image) { + uint8_t* preamble_blob = NULL; MemcpyState st; - config_blob = (uint8_t*) Malloc(GetKernelConfigLen(image)); - st.remaining_len = GetKernelConfigLen(image); - st.remaining_buf = config_blob; + preamble_blob = (uint8_t*) Malloc(GetKernelPreambleLen()); + st.remaining_len = GetKernelPreambleLen(); + st.remaining_buf = preamble_blob; st.overrun = 0; StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len)); - StatefulMemcpy_r(&st, image->kernel_config, FIELD_LEN(kernel_config)); + StatefulMemcpy_r(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset)); + StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); + StatefulMemcpy_r(&st, &image->padded_header_size, + FIELD_LEN(padded_header_size)); if (st.overrun || st.remaining_len != 0) { /* Overrun or Underrun. */ - Free(config_blob); + Free(preamble_blob); return NULL; } - return config_blob; + return preamble_blob; } uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) { @@ -258,7 +255,7 @@ uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) { *blob_len = (FIELD_LEN(magic) + GetKernelHeaderLen(image) + kernel_key_signature_len + - GetKernelConfigLen(image) + + GetKernelPreambleLen() + 2 * kernel_signature_len + image->kernel_len); kernel_blob = (uint8_t*) Malloc(*blob_len); @@ -271,12 +268,16 @@ uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) { StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic)); StatefulMemcpy_r(&st, header_blob, GetKernelHeaderLen(image)); StatefulMemcpy_r(&st, image->kernel_key_signature, kernel_key_signature_len); - /* Copy over kernel config blob (including signatures.) */ + /* Copy over kernel preamble blob (including signatures.) */ StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len)); - StatefulMemcpy_r(&st, image->config_signature, kernel_signature_len); + StatefulMemcpy_r(&st, &image->bootloader_offset, + FIELD_LEN(bootloader_offset)); + 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->kernel_config, FIELD_LEN(kernel_config)); StatefulMemcpy_r(&st, image->kernel_data, image->kernel_len); Free(header_blob); @@ -315,9 +316,8 @@ int WriteKernelImage(const char* input_file, success = 0; } } else { - /* Exclude kernel_config and kernel_data. */ - int vblock_len = blob_len - (image->kernel_len + - sizeof(image->kernel_config)); + /* Exclude kernel_data. */ + int vblock_len = blob_len - (image->kernel_len); if (vblock_len != write(fd, kernel_blob, vblock_len)) { debug("Couldn't write Kernel Image Verification block to file: %s\n", input_file); @@ -347,11 +347,15 @@ void PrintKernelImage(const KernelImage* image) { /* TODO(gauravsh): Output hash and key signature here? */ /* Print preamble. */ printf("Kernel Version = %d\n" - "Kernel Config command line = \"%s\"\n" - "kernel Length = %" PRId64 "\n", + "kernel Length = %" PRId64 "\n" + "Bootloader Offset = %" PRId64 "\n" + "Bootloader Size = %" PRId64 "\n" + "Padded Header Size = %" PRId64 "\n", image->kernel_version, - image->kernel_config, - image->kernel_len); + image->kernel_len, + image->bootloader_offset, + image->bootloader_size, + image->padded_header_size); /* TODO(gauravsh): Output kernel signature here? */ } @@ -361,7 +365,7 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, const int dev_mode) { RSAPublicKey* kernel_sign_key = NULL; uint8_t* header_digest = NULL; - uint8_t* config_digest = NULL; + uint8_t* preamble_digest = NULL; uint8_t* kernel_digest = NULL; int kernel_sign_key_size; int kernel_signature_size; @@ -417,19 +421,23 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, kernel_sign_key_size); kernel_signature_size = siglen_map[image->kernel_sign_algorithm]; - /* Verify kernel config signature. */ + /* Verify kernel preamble signature. */ DigestInit(&ctx, image->kernel_sign_algorithm); DigestUpdate(&ctx, (uint8_t*) &image->kernel_version, FIELD_LEN(kernel_version)); DigestUpdate(&ctx, (uint8_t*) &image->kernel_len, FIELD_LEN(kernel_len)); - DigestUpdate(&ctx, (uint8_t*) image->kernel_config, - FIELD_LEN(kernel_config)); - config_digest = DigestFinal(&ctx); - if (!RSAVerify(kernel_sign_key, image->config_signature, + DigestUpdate(&ctx, (uint8_t*) &image->bootloader_offset, + FIELD_LEN(bootloader_offset)); + DigestUpdate(&ctx, (uint8_t*) &image->bootloader_size, + FIELD_LEN(bootloader_size)); + DigestUpdate(&ctx, (uint8_t*) &image->padded_header_size, + FIELD_LEN(padded_header_size)); + preamble_digest = DigestFinal(&ctx); + if (!RSAVerify(kernel_sign_key, image->preamble_signature, kernel_signature_size, image->kernel_sign_algorithm, - config_digest)) { - error_code = VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED; + preamble_digest)) { + error_code = VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED; goto verify_failure; } @@ -440,9 +448,14 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, FIELD_LEN(kernel_version)); DigestUpdate(&kernel_ctx, (uint8_t*) &image->kernel_len, FIELD_LEN(kernel_len)); - DigestUpdate(&kernel_ctx, (uint8_t*) image->kernel_config, - FIELD_LEN(kernel_config)); - DigestUpdate(&kernel_ctx, image->kernel_data, image->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); if (!RSAVerify(kernel_sign_key, image->kernel_signature, kernel_signature_size, image->kernel_sign_algorithm, @@ -454,7 +467,7 @@ int VerifyKernelImage(const RSAPublicKey* firmware_key, verify_failure: RSAPublicKeyFree(kernel_sign_key); Free(kernel_digest); - Free(config_digest); + Free(preamble_digest); Free(header_digest); return error_code; } @@ -488,38 +501,38 @@ int AddKernelKeySignature(KernelImage* image, const char* firmware_key_file) { int AddKernelSignature(KernelImage* image, const char* kernel_signing_key_file) { - uint8_t* config_blob = NULL; - uint8_t* config_signature = NULL; + uint8_t* preamble_blob = NULL; + uint8_t* preamble_signature = NULL; uint8_t* kernel_signature = NULL; uint8_t* kernel_buf; int signature_len = siglen_map[image->kernel_sign_algorithm]; - config_blob = GetKernelConfigBlob(image); - if (!(config_signature = SignatureBuf(config_blob, - GetKernelConfigLen(image), - kernel_signing_key_file, - image->kernel_sign_algorithm))) { - debug("Could not compute signature on the kernel config.\n"); - Free(config_blob); + 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->config_signature = (uint8_t*) Malloc(signature_len); - Memcpy(image->config_signature, config_signature, signature_len); - Free(config_signature); + 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(GetKernelConfigLen(image) + + kernel_buf = (uint8_t*) Malloc(GetKernelPreambleLen() + image->kernel_len); - Memcpy(kernel_buf, config_blob, GetKernelConfigLen(image)); - Memcpy(kernel_buf + GetKernelConfigLen(image), image->kernel_data, + Memcpy(kernel_buf, preamble_blob, GetKernelPreambleLen()); + Memcpy(kernel_buf + GetKernelPreambleLen(), image->kernel_data, image->kernel_len); if (!(kernel_signature = SignatureBuf(kernel_buf, - GetKernelConfigLen(image) + + GetKernelPreambleLen() + image->kernel_len, kernel_signing_key_file, image->kernel_sign_algorithm))) { - Free(config_blob); + Free(preamble_blob); Free(kernel_buf); debug("Could not compute signature on the kernel.\n"); return 0; @@ -528,7 +541,7 @@ int AddKernelSignature(KernelImage* image, Memcpy(image->kernel_signature, kernel_signature, signature_len); Free(kernel_signature); Free(kernel_buf); - Free(config_blob); + Free(preamble_blob); return 1; }