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");