From b85b06bb25dc4f55aedb0cb7f71c0b1b01ef7b66 Mon Sep 17 00:00:00 2001 From: Gaurav Shah Date: Thu, 27 May 2010 13:29:20 -0700 Subject: [PATCH] Add a --subkey switch to kernel signing utility. This option makes the signing utility just output the kernel subkey (key signature) header which can be used to generate subsequent signed kernel images without needing the firmware root key and using the same kernel signing key. (This feature will be a part of a subsequent CL). Review URL: http://codereview.chromium.org/2310002 --- utility/include/kernel_utility.h | 3 ++- utility/kernel_utility.cc | 13 +++++++++++-- vkernel/include/kernel_image.h | 4 +++- vkernel/kernel_image.c | 27 +++++++++++++++++++++++++-- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/utility/include/kernel_utility.h b/utility/include/kernel_utility.h index 1d03685aa5..66802cf3c6 100644 --- a/utility/include/kernel_utility.h +++ b/utility/include/kernel_utility.h @@ -77,7 +77,8 @@ class KernelUtility { bool is_generate_; // Are we generating a new image? bool is_verify_; // Are we just verifying an already signed image? bool is_describe_; // Should we print out description of the image? - bool is_only_vblock_; // Show we just output the verification block? + bool is_only_vblock_; // Should we just output the verification block? + bool is_subkey_out_; // Should we just output the subkey header? }; } // namespace vboot_reference diff --git a/utility/kernel_utility.cc b/utility/kernel_utility.cc index 99f637f60a..a75e4fbb87 100644 --- a/utility/kernel_utility.cc +++ b/utility/kernel_utility.cc @@ -76,8 +76,9 @@ void KernelUtility::PrintUsage(void) { " --out \t\t\tOutput file for verified boot image\n" "\n" "Optional arguments for \"--generate\" are:\n" + " --padding \t\t\tPad the header to this size\n" + " --subkey_out\t\t\t\tJust output the subkey (key verification) header\n" " --vblock\t\t\t\tJust output the verification block\n" - " --padding\t\t\t\tPad the header to this size\n" "\n" " (for --*_sign_algorithm) is one of the following:\n"; for (int i = 0; i < kNumAlgorithms; i++) { @@ -108,6 +109,7 @@ bool KernelUtility::ParseCmdLineOptions(int argc, char* argv[]) { OPT_VMLINUZ, OPT_CONFIG, OPT_PADDING, + OPT_SUBKEY, }; static struct option long_options[] = { {"firmware_key", 1, 0, OPT_FIRMWARE_KEY }, @@ -128,6 +130,7 @@ bool KernelUtility::ParseCmdLineOptions(int argc, char* argv[]) { {"vmlinuz", 1, 0, OPT_VMLINUZ }, {"config", 1, 0, OPT_CONFIG }, {"padding", 1, 0, OPT_PADDING }, + {"subkey_out", 0, 0, OPT_SUBKEY }, {NULL, 0, 0, 0} }; while ((i = getopt_long(argc, argv, "", long_options, &option_index)) != -1) { @@ -222,6 +225,9 @@ bool KernelUtility::ParseCmdLineOptions(int argc, char* argv[]) { return false; } break; + case OPT_SUBKEY: + is_subkey_out_ = true; + break; } } return CheckOptions(); @@ -229,7 +235,9 @@ bool KernelUtility::ParseCmdLineOptions(int argc, char* argv[]) { void KernelUtility::OutputSignedImage(void) { if (image_) { - if (!WriteKernelImage(out_file_.c_str(), image_, is_only_vblock_)) { + if (!WriteKernelImage(out_file_.c_str(), image_, + is_only_vblock_, + is_subkey_out_)) { cerr << "Couldn't write verified boot kernel image to file " << out_file_ <<".\n"; } @@ -389,6 +397,7 @@ bool KernelUtility::CheckOptions(void) { cerr << "No vmlinuz file specified.\n"; return false; } + // TODO(gauravsh): Enforce only one of --vblock or --subkey_out is specified } return true; } diff --git a/vkernel/include/kernel_image.h b/vkernel/include/kernel_image.h index 58e1b1ac99..73ed3a56cd 100644 --- a/vkernel/include/kernel_image.h +++ b/vkernel/include/kernel_image.h @@ -54,6 +54,7 @@ uint8_t* GetKernelConfigBlob(const KernelImage* image); */ uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len); + /* Write kernel data from [image] to a file named [input_file]. * If [is_only_vblock] is non-zero, only the verification block is output. * @@ -61,7 +62,8 @@ uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len); */ int WriteKernelImage(const char* input_file, const KernelImage* image, - int is_only_vblock); + int is_only_vblock, + int is_subkey_out); /* Create a kernel_data blob from its components and fill * its length into blob_len, plus some information about the bootloader. diff --git a/vkernel/kernel_image.c b/vkernel/kernel_image.c index 0c323f7299..e0b7a55d79 100644 --- a/vkernel/kernel_image.c +++ b/vkernel/kernel_image.c @@ -322,10 +322,13 @@ uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) { int WriteKernelImage(const char* output_file, const KernelImage* image, - int is_only_vblock) { + int is_only_vblock, + int is_subkey_out) { int fd; int success = 1; - uint8_t* kernel_blob; + uint8_t* kernel_blob = NULL; + uint8_t* subkey_out_buf = NULL; + uint8_t* subkey_header = NULL; uint64_t blob_len; if (!image) @@ -335,6 +338,26 @@ int WriteKernelImage(const char* output_file, output_file); return 0; } + if (is_subkey_out) { + blob_len = GetKernelHeaderLen(image) + + siglen_map[image->firmware_sign_algorithm]; + subkey_out_buf = (uint8_t*) Malloc(blob_len); + subkey_header = GetKernelHeaderBlob(image); + Memcpy(subkey_out_buf, subkey_header, GetKernelHeaderLen(image)); + Memcpy(subkey_out_buf + GetKernelHeaderLen(image), + image->kernel_key_signature, + siglen_map[image->firmware_sign_algorithm]); + if (blob_len != write(fd, subkey_out_buf, blob_len)) { + debug("Couldn't write Kernel Subkey header to file: %s\n", + output_file); + success = 0; + } + Free(subkey_header); + Free(subkey_out_buf); + close(fd); + return success; + } + kernel_blob = GetKernelBlob(image, &blob_len); if (!kernel_blob) { debug("Couldn't create kernel blob from KernelImage.\n");