delta_generator: Include per-operation source hash.
This adds a src_sha256_hash field in the operation if minor version is 3.
Bug: 23182225
TEST=cros_workon_make update_engine --test
TEST=Generated a minor version 3 payload, the manifest is about 50% larger.
Change-Id: I0e363fca4de24bae64ac83930afdd42a6ddc21c9
diff --git a/payload_constants.cc b/payload_constants.cc
index cc18430..b831240 100644
--- a/payload_constants.cc
+++ b/payload_constants.cc
@@ -24,6 +24,7 @@
const uint32_t kFullPayloadMinorVersion = 0;
const uint32_t kInPlaceMinorPayloadVersion = 1;
const uint32_t kSourceMinorPayloadVersion = 2;
+const uint32_t kOpSrcHashMinorPayloadVersion = 3;
const char kLegacyPartitionNameKernel[] = "boot";
const char kLegacyPartitionNameRoot[] = "system";
diff --git a/payload_constants.h b/payload_constants.h
index 38cc075..d423eeb 100644
--- a/payload_constants.h
+++ b/payload_constants.h
@@ -40,6 +40,9 @@
// The minor version used by the A to B delta generator algorithm.
extern const uint32_t kSourceMinorPayloadVersion;
+// The minor version that allows per-operation source hash.
+extern const uint32_t kOpSrcHashMinorPayloadVersion;
+
// The kernel and rootfs partition names used by the BootControlInterface when
// handling update payloads with a major version 1. The names of the updated
diff --git a/payload_generator/ab_generator.cc b/payload_generator/ab_generator.cc
index 336e6a8..2658fb8 100644
--- a/payload_generator/ab_generator.cc
+++ b/payload_generator/ab_generator.cc
@@ -20,7 +20,8 @@
#include <base/strings/stringprintf.h>
-#include "update_engine/delta_performer.h"
+#include "update_engine/omaha_hash_calculator.h"
+#include "update_engine/payload_constants.h"
#include "update_engine/payload_generator/annotated_operation.h"
#include "update_engine/payload_generator/bzip.h"
#include "update_engine/payload_generator/delta_diff_generator.h"
@@ -72,6 +73,10 @@
merge_chunk_blocks,
new_part.path,
blob_file));
+
+ if (config.minor_version == kOpSrcHashMinorPayloadVersion)
+ TEST_AND_RETURN_FALSE(AddSourceHash(aops, old_part.path));
+
return true;
}
@@ -305,4 +310,26 @@
return true;
}
+bool ABGenerator::AddSourceHash(vector<AnnotatedOperation>* aops,
+ const string& source_part_path) {
+ for (AnnotatedOperation& aop : *aops) {
+ if (aop.op.src_extents_size() == 0)
+ continue;
+
+ vector<Extent> src_extents;
+ ExtentsToVector(aop.op.src_extents(), &src_extents);
+ brillo::Blob src_data, src_hash;
+ uint64_t src_length =
+ aop.op.has_src_length()
+ ? aop.op.src_length()
+ : BlocksInExtents(aop.op.src_extents()) * kBlockSize;
+ TEST_AND_RETURN_FALSE(utils::ReadExtents(
+ source_part_path, src_extents, &src_data, src_length, kBlockSize));
+ TEST_AND_RETURN_FALSE(
+ OmahaHashCalculator::RawHashOfData(src_data, &src_hash));
+ aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
+ }
+ return true;
+}
+
} // namespace chromeos_update_engine
diff --git a/payload_generator/ab_generator.h b/payload_generator/ab_generator.h
index 25a7811..31cbb1e 100644
--- a/payload_generator/ab_generator.h
+++ b/payload_generator/ab_generator.h
@@ -107,6 +107,11 @@
const std::string& target_part,
BlobFileWriter* blob_file);
+ // Takes a vector of AnnotatedOperations |aops|, adds source hash to all
+ // operations that have src_extents.
+ static bool AddSourceHash(std::vector<AnnotatedOperation>* aops,
+ const std::string& source_part_path);
+
private:
// Adds the data payload for a REPLACE/REPLACE_BZ operation |aop| by reading
// its output extents from |target_part_path| and appending a corresponding
diff --git a/payload_generator/ab_generator_unittest.cc b/payload_generator/ab_generator_unittest.cc
index 4248f8d..8854225 100644
--- a/payload_generator/ab_generator_unittest.cc
+++ b/payload_generator/ab_generator_unittest.cc
@@ -25,6 +25,7 @@
#include <gtest/gtest.h>
+#include "update_engine/omaha_hash_calculator.h"
#include "update_engine/payload_generator/annotated_operation.h"
#include "update_engine/payload_generator/bzip.h"
#include "update_engine/payload_generator/delta_diff_generator.h"
@@ -550,4 +551,40 @@
EXPECT_EQ(aops.size(), 4);
}
+TEST_F(ABGeneratorTest, AddSourceHashTest) {
+ vector<AnnotatedOperation> aops;
+ InstallOperation first_op;
+ first_op.set_type(InstallOperation::SOURCE_COPY);
+ first_op.set_src_length(kBlockSize);
+ *(first_op.add_src_extents()) = ExtentForRange(0, 1);
+ AnnotatedOperation first_aop;
+ first_aop.op = first_op;
+ aops.push_back(first_aop);
+
+ InstallOperation second_op;
+ second_op.set_type(InstallOperation::REPLACE);
+ AnnotatedOperation second_aop;
+ second_aop.op = second_op;
+ aops.push_back(second_aop);
+
+ string src_part_path;
+ EXPECT_TRUE(utils::MakeTempFile("AddSourceHashTest_src_part.XXXXXX",
+ &src_part_path, nullptr));
+ ScopedPathUnlinker src_part_path_unlinker(src_part_path);
+ brillo::Blob src_data(kBlockSize);
+ test_utils::FillWithData(&src_data);
+ ASSERT_TRUE(utils::WriteFile(src_part_path.c_str(), src_data.data(),
+ src_data.size()));
+
+ EXPECT_TRUE(ABGenerator::AddSourceHash(&aops, src_part_path));
+
+ EXPECT_TRUE(aops[0].op.has_src_sha256_hash());
+ EXPECT_FALSE(aops[1].op.has_src_sha256_hash());
+ brillo::Blob expected_hash;
+ EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(src_data, &expected_hash));
+ brillo::Blob result_hash(aops[0].op.src_sha256_hash().begin(),
+ aops[0].op.src_sha256_hash().end());
+ EXPECT_EQ(expected_hash, result_hash);
+}
+
} // namespace chromeos_update_engine
diff --git a/payload_generator/delta_diff_generator.cc b/payload_generator/delta_diff_generator.cc
index af81e62..96730aa 100644
--- a/payload_generator/delta_diff_generator.cc
+++ b/payload_generator/delta_diff_generator.cc
@@ -104,7 +104,8 @@
if (config.minor_version == kInPlaceMinorPayloadVersion) {
LOG(INFO) << "Using generator InplaceGenerator().";
strategy.reset(new InplaceGenerator());
- } else if (config.minor_version == kSourceMinorPayloadVersion) {
+ } else if (config.minor_version == kSourceMinorPayloadVersion ||
+ config.minor_version == kOpSrcHashMinorPayloadVersion) {
LOG(INFO) << "Using generator ABGenerator().";
strategy.reset(new ABGenerator());
} else {
diff --git a/payload_generator/payload_generation_config.cc b/payload_generator/payload_generation_config.cc
index 66928d3..c2a78cc 100644
--- a/payload_generator/payload_generation_config.cc
+++ b/payload_generator/payload_generation_config.cc
@@ -99,7 +99,8 @@
// Check for the supported minor_version values.
TEST_AND_RETURN_FALSE(minor_version == kInPlaceMinorPayloadVersion ||
- minor_version == kSourceMinorPayloadVersion);
+ minor_version == kSourceMinorPayloadVersion ||
+ minor_version == kOpSrcHashMinorPayloadVersion);
// If new_image_info is present, old_image_info must be present.
TEST_AND_RETURN_FALSE(source.ImageInfoIsEmpty() ==