Support needed for generating metadata signature in paygen
The metadata is the first portion of a payload that contains the following:
1. magic string ("CrOS")
2. version number
3. length of the manifest protobuf
4. manifest protobuf itself
<payload blobs begin here>
<payload signature as the last blob>
Currently we have a manifest signature which protects only #4 above. In
this CL we're extending the scope of manifest signature to include the rest
of the metadata (1-4). The reason we need to do this is to protect the
version value in HTTP as we're going to use it in future to have the
flexibility to change the protobuf format of the manifest.
Besides this change, this CL also contains:
1. Renaming of manifest_size and manifest_signature to metadata_size and
metadata_signature respectively to reflect the above change and keep
consistent terminology throughout. Also it renames protobuf_offset and
protobuf_length to manifest_offset and manifest_size to increase the
contextual semantics of the protobuf.
2. Addition of a new command-line option --out_metadata_hash_file in
delta_generator so that au_generate can use it in a subsequent CL to get
the SHA256 hash of the payload metadata in order to get it signed with
the signer.
3. Reusing LoadPayload in unit tests to get rid of some hardcoding. Also
updated delta_performer to localize such hardcoded constants within that
class and not have callers worry about those values.
BUG=chromium-os:33603
TEST=Tested on ZGB. Reran existing unit tests.
Change-Id: Iace5aebe8f7d054a0fa3a224a588ef52d85f510b
Reviewed-on: https://gerrit.chromium.org/gerrit/33726
Commit-Ready: Jay Srinivasan <jaysri@chromium.org>
Reviewed-by: Jay Srinivasan <jaysri@chromium.org>
Tested-by: Jay Srinivasan <jaysri@chromium.org>
diff --git a/generate_delta_main.cc b/generate_delta_main.cc
index f5fe5e7..6991813 100644
--- a/generate_delta_main.cc
+++ b/generate_delta_main.cc
@@ -41,6 +41,7 @@
"and apply delta over old_image (for debugging)");
DEFINE_string(out_file, "", "Path to output delta payload file");
DEFINE_string(out_hash_file, "", "Path to output hash file");
+DEFINE_string(out_metadata_hash_file, "", "Path to output metadata hash file");
DEFINE_string(private_key, "", "Path to private key in .pem format");
DEFINE_string(public_key, "", "Path to public key in .pem format");
DEFINE_int32(public_key_version,
@@ -78,32 +79,63 @@
return S_ISDIR(stbuf.st_mode);
}
+void ParseSignatureSizes(vector<int>* sizes) {
+ LOG_IF(FATAL, FLAGS_signature_size.empty())
+ << "Must pass --signature_size to calculate hash for signing.";
+ vector<string> strsizes;
+ base::SplitString(FLAGS_signature_size, ':', &strsizes);
+ for (vector<string>::iterator it = strsizes.begin(), e = strsizes.end();
+ it != e; ++it) {
+ int size = 0;
+ bool parsing_successful = base::StringToInt(*it, &size);
+ LOG_IF(FATAL, !parsing_successful)
+ << "Invalid signature size: " << *it;
+ sizes->push_back(size);
+ }
+}
+
+
void CalculatePayloadHashForSigning() {
LOG(INFO) << "Calculating payload hash for signing.";
LOG_IF(FATAL, FLAGS_in_file.empty())
<< "Must pass --in_file to calculate hash for signing.";
LOG_IF(FATAL, FLAGS_out_hash_file.empty())
<< "Must pass --out_hash_file to calculate hash for signing.";
- LOG_IF(FATAL, FLAGS_signature_size.empty())
- << "Must pass --signature_size to calculate hash for signing.";
vector<int> sizes;
- vector<string> strsizes;
- base::SplitString(FLAGS_signature_size, ':', &strsizes);
- for (vector<string>::iterator it = strsizes.begin(), e = strsizes.end();
- it != e; ++it) {
- int size = 0;
- LOG_IF(FATAL, !base::StringToInt(*it, &size))
- << "Not an integer: " << *it;
- sizes.push_back(size);
- }
+ ParseSignatureSizes(&sizes);
+
vector<char> hash;
- CHECK(PayloadSigner::HashPayloadForSigning(
- FLAGS_in_file, sizes, &hash));
- CHECK(utils::WriteFile(
- FLAGS_out_hash_file.c_str(), hash.data(), hash.size()));
+ bool result = PayloadSigner::HashPayloadForSigning(FLAGS_in_file, sizes,
+ &hash);
+ CHECK(result);
+
+ result = utils::WriteFile(FLAGS_out_hash_file.c_str(), hash.data(),
+ hash.size());
+ CHECK(result);
LOG(INFO) << "Done calculating payload hash for signing.";
}
+
+void CalculateMetadataHashForSigning() {
+ LOG(INFO) << "Calculating metadata hash for signing.";
+ LOG_IF(FATAL, FLAGS_in_file.empty())
+ << "Must pass --in_file to calculate metadata hash for signing.";
+ LOG_IF(FATAL, FLAGS_out_metadata_hash_file.empty())
+ << "Must pass --out_metadata_hash_file to calculate metadata hash.";
+ vector<int> sizes;
+ ParseSignatureSizes(&sizes);
+
+ vector<char> hash;
+ bool result = PayloadSigner::HashMetadataForSigning(FLAGS_in_file, &hash);
+ CHECK(result);
+
+ result = utils::WriteFile(FLAGS_out_metadata_hash_file.c_str(), hash.data(),
+ hash.size());
+ CHECK(result);
+
+ LOG(INFO) << "Done calculating metadata hash for signing.";
+}
+
void SignPayload() {
LOG(INFO) << "Signing payload.";
LOG_IF(FATAL, FLAGS_in_file.empty())
@@ -189,8 +221,19 @@
logging::DONT_LOCK_LOG_FILE,
logging::APPEND_TO_OLD_LOG_FILE,
logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
- if (!FLAGS_signature_size.empty() || !FLAGS_out_hash_file.empty()) {
- CalculatePayloadHashForSigning();
+ if (!FLAGS_signature_size.empty()) {
+ bool work_done = false;
+ if (!FLAGS_out_hash_file.empty()) {
+ CalculatePayloadHashForSigning();
+ work_done = true;
+ }
+ if (!FLAGS_out_metadata_hash_file.empty()) {
+ CalculateMetadataHashForSigning();
+ work_done = true;
+ }
+ if (!work_done) {
+ LOG(FATAL) << "Neither payload hash file nor metadata hash file supplied";
+ }
return 0;
}
if (!FLAGS_signature_file.empty()) {