• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "update_engine/payload_consumer/delta_performer.h"
18 
19 #include <endian.h>
20 #include <inttypes.h>
21 #include <time.h>
22 
23 #include <algorithm>
24 #include <map>
25 #include <memory>
26 #include <string>
27 #include <vector>
28 
29 #include <base/files/file_path.h>
30 #include <base/files/file_util.h>
31 #include <base/files/scoped_temp_dir.h>
32 #include <base/stl_util.h>
33 #include <base/strings/string_number_conversions.h>
34 #include <base/strings/string_util.h>
35 #include <base/strings/stringprintf.h>
36 #include <brillo/secure_blob.h>
37 #include <gmock/gmock.h>
38 #include <google/protobuf/repeated_field.h>
39 #include <gtest/gtest.h>
40 
41 #include "update_engine/common/constants.h"
42 #include "update_engine/common/error_code.h"
43 #include "update_engine/common/fake_boot_control.h"
44 #include "update_engine/common/fake_hardware.h"
45 #include "update_engine/common/fake_prefs.h"
46 #include "update_engine/common/hardware_interface.h"
47 #include "update_engine/common/hash_calculator.h"
48 #include "update_engine/common/mock_download_action.h"
49 #include "update_engine/common/test_utils.h"
50 #include "update_engine/common/testing_constants.h"
51 #include "update_engine/common/utils.h"
52 #include "update_engine/payload_consumer/fake_file_descriptor.h"
53 #include "update_engine/payload_consumer/mock_partition_writer.h"
54 #include "update_engine/payload_consumer/payload_constants.h"
55 #include "update_engine/payload_consumer/payload_metadata.h"
56 #include "update_engine/payload_generator/bzip.h"
57 #include "update_engine/payload_generator/extent_ranges.h"
58 #include "update_engine/payload_generator/payload_file.h"
59 #include "update_engine/payload_generator/payload_signer.h"
60 #include "update_engine/update_metadata.pb.h"
61 
62 namespace chromeos_update_engine {
63 
64 using std::string;
65 using std::vector;
66 using test_utils::GetBuildArtifactsPath;
67 using test_utils::kRandomString;
68 using testing::_;
69 using testing::Return;
70 using ::testing::Sequence;
71 
72 namespace {
73 
74 const char kBogusMetadataSignature1[] =
75     "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
76     "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
77     "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
78     "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
79     "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
80     "pLRtClp97kN2+tXGNBQqkA==";
81 
82 // Different options that determine what we should fill into the
83 // install_plan.metadata_signature to simulate the contents received in the
84 // Omaha response.
85 enum MetadataSignatureTest {
86   kEmptyMetadataSignature,
87   kInvalidMetadataSignature,
88   kValidMetadataSignature,
89 };
90 
91 // Compressed data without checksum, generated with:
92 // echo -n "a$(head -c 4095 /dev/zero)" | xz -9 --check=none |
93 //     hexdump -v -e '"    " 12/1 "0x%02x, " "\n"'
94 const uint8_t kXzCompressedData[] = {
95     0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x00, 0xff, 0x12, 0xd9, 0x41,
96     0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc,
97     0xe0, 0x0f, 0xff, 0x00, 0x1b, 0x5d, 0x00, 0x30, 0x80, 0x33, 0xff, 0xdf,
98     0xff, 0x51, 0xd6, 0xaf, 0x90, 0x1c, 0x1b, 0x4c, 0xaa, 0x3d, 0x7b, 0x28,
99     0xe4, 0x7a, 0x74, 0xbc, 0xe5, 0xa7, 0x33, 0x4e, 0xcf, 0x00, 0x00, 0x00,
100     0x00, 0x01, 0x2f, 0x80, 0x20, 0x00, 0x00, 0x00, 0x92, 0x7c, 0x7b, 0x24,
101     0xa8, 0x00, 0x0a, 0xfc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x5a,
102 };
103 
104 // clang-format off
105 const uint8_t src_deflates[] = {
106   /* raw      0  */ 0x11, 0x22,
107   /* deflate  2  */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
108   /* raw      9  */ 0x33,
109   /* deflate  10 */ 0x03, 0x00,
110   /* raw      12 */
111   /* deflate  12 */ 0x63, 0x04, 0x00,
112   /* raw      15 */ 0x44, 0x55
113 };
114 
115 const uint8_t dst_deflates[] = {
116   /* deflate  0  */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
117   /* raw      7  */ 0x33, 0x66,
118   /* deflate  9  */ 0x01, 0x05, 0x00, 0xFA, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05,
119   /* deflate  19 */ 0x63, 0x04, 0x00
120 };
121 // clang-format on
122 
123 // To generate this patch either:
124 // - Use puffin/src/patching_unittest.cc:TestPatching
125 // Or
126 // - Use the following approach:
127 // * Make src_deflate a string of hex with only spaces. (e.g. "0XTE 0xST")
128 // * echo "0XTE 0xST" | xxd -r -p > src.bin
129 // * Find the location of deflates in src_deflates (in bytes) in the format of
130 //   "offset:length,...". (e.g. "2:7,10:2,12:3")
131 // * Do previous three steps for dst_deflates.
132 // * puffin --operation=puffdiff --src_file=src.bin --dst_file=dst.bin \
133 //   --src_deflates_byte="2:7,10:2,12:3" --dst_deflates_byte="0:7,9:10,19:3" \
134 //   --patch_file=patch.bin
135 // * hexdump -ve '"  " 12/1 "0x%02x, " "\n"' patch.bin
136 const uint8_t puffdiff_patch[] = {
137     0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x51, 0x08, 0x01, 0x12, 0x27,
138     0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
139     0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
140     0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
141     0x38, 0x18, 0x1F, 0x1A, 0x24, 0x0A, 0x02, 0x10, 0x32, 0x0A, 0x04, 0x08,
142     0x48, 0x10, 0x50, 0x0A, 0x05, 0x08, 0x98, 0x01, 0x10, 0x12, 0x12, 0x02,
143     0x10, 0x58, 0x12, 0x04, 0x08, 0x70, 0x10, 0x58, 0x12, 0x05, 0x08, 0xC8,
144     0x01, 0x10, 0x38, 0x18, 0x21, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34,
145     0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
146     0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147     0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x65,
148     0x29, 0x8C, 0x9B, 0x00, 0x00, 0x03, 0x60, 0x40, 0x7A, 0x0E, 0x08, 0x00,
149     0x40, 0x00, 0x20, 0x00, 0x21, 0x22, 0x9A, 0x3D, 0x4F, 0x50, 0x40, 0x0C,
150     0x3B, 0xC7, 0x9B, 0xB2, 0x21, 0x0E, 0xE9, 0x15, 0x98, 0x7A, 0x7C, 0x5D,
151     0xC9, 0x14, 0xE1, 0x42, 0x41, 0x94, 0xA6, 0x32, 0x6C, 0x42, 0x5A, 0x68,
152     0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xF1, 0x20, 0x5F, 0x0D, 0x00,
153     0x00, 0x02, 0x41, 0x15, 0x42, 0x08, 0x20, 0x00, 0x40, 0x00, 0x00, 0x02,
154     0x40, 0x00, 0x20, 0x00, 0x22, 0x3D, 0x23, 0x10, 0x86, 0x03, 0x96, 0x54,
155     0x11, 0x16, 0x5F, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0xF1, 0x20, 0x5F,
156     0x0D, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x07,
157     0xD4, 0xCB, 0x6E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x00,
158     0x21, 0x18, 0x46, 0x82, 0xEE, 0x48, 0xA7, 0x0A, 0x12, 0x00, 0xFA, 0x99,
159     0x6D, 0xC0};
160 
161 }  // namespace
162 
163 class DeltaPerformerTest : public ::testing::Test {
164  protected:
SetUp()165   void SetUp() override {
166     install_plan_.source_slot = 0;
167     install_plan_.target_slot = 1;
168     EXPECT_CALL(mock_delegate_, ShouldCancel(_))
169         .WillRepeatedly(testing::Return(false));
170     // Set the public key corresponding to the unittest private key.
171     string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath);
172     EXPECT_TRUE(utils::FileExists(public_key_path.c_str()));
173     performer_.set_public_key_path(public_key_path);
174   }
175 
176   // Test helper placed where it can easily be friended from DeltaPerformer.
RunManifestValidation(const DeltaArchiveManifest & manifest,uint64_t major_version,InstallPayloadType payload_type,ErrorCode expected)177   void RunManifestValidation(const DeltaArchiveManifest& manifest,
178                              uint64_t major_version,
179                              InstallPayloadType payload_type,
180                              ErrorCode expected) {
181     payload_.type = payload_type;
182 
183     // The Manifest we are validating.
184     performer_.manifest_.CopyFrom(manifest);
185     performer_.major_payload_version_ = major_version;
186 
187     EXPECT_EQ(expected, performer_.ValidateManifest());
188   }
189 
GeneratePayload(const brillo::Blob & blob_data,const vector<AnnotatedOperation> & aops,bool sign_payload,PartitionConfig * old_part=nullptr)190   brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
191                                const vector<AnnotatedOperation>& aops,
192                                bool sign_payload,
193                                PartitionConfig* old_part = nullptr) {
194     return GeneratePayload(blob_data,
195                            aops,
196                            sign_payload,
197                            kMaxSupportedMajorPayloadVersion,
198                            kMaxSupportedMinorPayloadVersion,
199                            old_part);
200   }
201 
GeneratePayload(const brillo::Blob & blob_data,const vector<AnnotatedOperation> & aops,bool sign_payload,uint64_t major_version,uint32_t minor_version,PartitionConfig * old_part=nullptr)202   brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
203                                const vector<AnnotatedOperation>& aops,
204                                bool sign_payload,
205                                uint64_t major_version,
206                                uint32_t minor_version,
207                                PartitionConfig* old_part = nullptr) {
208     ScopedTempFile blob_file("Blob-XXXXXX");
209     EXPECT_TRUE(test_utils::WriteFileVector(blob_file.path(), blob_data));
210 
211     PayloadGenerationConfig config;
212     config.version.major = major_version;
213     config.version.minor = minor_version;
214 
215     PayloadFile payload;
216     EXPECT_TRUE(payload.Init(config));
217 
218     std::unique_ptr<PartitionConfig> old_part_uptr;
219     if (!old_part) {
220       old_part_uptr = std::make_unique<PartitionConfig>(kPartitionNameRoot);
221       old_part = old_part_uptr.get();
222     }
223     if (minor_version != kFullPayloadMinorVersion) {
224       // When generating a delta payload we need to include the old partition
225       // information to mark it as a delta payload.
226       if (old_part->path.empty()) {
227         old_part->path = "/dev/null";
228       }
229     }
230     PartitionConfig new_part(kPartitionNameRoot);
231     new_part.path = "/dev/zero";
232     new_part.size = 1234;
233 
234     payload.AddPartition(*old_part, new_part, aops, {}, 0);
235 
236     // We include a kernel partition without operations.
237     old_part->name = kPartitionNameKernel;
238     new_part.name = kPartitionNameKernel;
239     new_part.size = 0;
240     payload.AddPartition(*old_part, new_part, {}, {}, 0);
241 
242     ScopedTempFile payload_file("Payload-XXXXXX");
243     string private_key =
244         sign_payload ? GetBuildArtifactsPath(kUnittestPrivateKeyPath) : "";
245     EXPECT_TRUE(payload.WritePayload(payload_file.path(),
246                                      blob_file.path(),
247                                      private_key,
248                                      &payload_.metadata_size));
249 
250     brillo::Blob payload_data;
251     EXPECT_TRUE(utils::ReadFile(payload_file.path(), &payload_data));
252     return payload_data;
253   }
254 
GenerateSourceCopyPayload(const brillo::Blob & copied_data,bool add_hash,PartitionConfig * old_part=nullptr)255   brillo::Blob GenerateSourceCopyPayload(const brillo::Blob& copied_data,
256                                          bool add_hash,
257                                          PartitionConfig* old_part = nullptr) {
258     PayloadGenerationConfig config;
259     const uint64_t kDefaultBlockSize = config.block_size;
260     EXPECT_EQ(0U, copied_data.size() % kDefaultBlockSize);
261     uint64_t num_blocks = copied_data.size() / kDefaultBlockSize;
262     AnnotatedOperation aop;
263     *(aop.op.add_src_extents()) = ExtentForRange(0, num_blocks);
264     *(aop.op.add_dst_extents()) = ExtentForRange(0, num_blocks);
265     aop.op.set_type(InstallOperation::SOURCE_COPY);
266     brillo::Blob src_hash;
267     EXPECT_TRUE(HashCalculator::RawHashOfData(copied_data, &src_hash));
268     if (add_hash)
269       aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
270 
271     return GeneratePayload(brillo::Blob(), {aop}, false, old_part);
272   }
273 
274   // Apply |payload_data| on partition specified in |source_path|.
275   // Expect result of performer_.Write() to be |expect_success|.
276   // Returns the result of the payload application.
ApplyPayload(const brillo::Blob & payload_data,const string & source_path,bool expect_success)277   brillo::Blob ApplyPayload(const brillo::Blob& payload_data,
278                             const string& source_path,
279                             bool expect_success) {
280     return ApplyPayloadToData(
281         &performer_, payload_data, source_path, brillo::Blob(), expect_success);
282   }
ApplyPayloadToData(const brillo::Blob & payload_data,const string & source_path,const brillo::Blob & target_data,bool expect_success)283   brillo::Blob ApplyPayloadToData(const brillo::Blob& payload_data,
284                                   const string& source_path,
285                                   const brillo::Blob& target_data,
286                                   bool expect_success) {
287     return ApplyPayloadToData(
288         &performer_, payload_data, source_path, target_data, expect_success);
289   }
290 
291   // Apply the payload provided in |payload_data| reading from the |source_path|
292   // file and writing the contents to a new partition. The existing data in the
293   // new target file are set to |target_data| before applying the payload.
294   // Expect result of performer_.Write() to be |expect_success|.
295   // Returns the result of the payload application.
ApplyPayloadToData(DeltaPerformer * delta_performer,const brillo::Blob & payload_data,const string & source_path,const brillo::Blob & target_data,bool expect_success)296   brillo::Blob ApplyPayloadToData(DeltaPerformer* delta_performer,
297                                   const brillo::Blob& payload_data,
298                                   const string& source_path,
299                                   const brillo::Blob& target_data,
300                                   bool expect_success) {
301     ScopedTempFile new_part("Partition-XXXXXX");
302     EXPECT_TRUE(test_utils::WriteFileVector(new_part.path(), target_data));
303 
304     payload_.size = payload_data.size();
305     // We installed the operations only in the rootfs partition, but the
306     // delta performer needs to access all the partitions.
307     fake_boot_control_.SetPartitionDevice(
308         kPartitionNameRoot, install_plan_.target_slot, new_part.path());
309     fake_boot_control_.SetPartitionDevice(
310         kPartitionNameRoot, install_plan_.source_slot, source_path);
311     fake_boot_control_.SetPartitionDevice(
312         kPartitionNameKernel, install_plan_.target_slot, "/dev/null");
313     fake_boot_control_.SetPartitionDevice(
314         kPartitionNameKernel, install_plan_.source_slot, "/dev/null");
315 
316     EXPECT_EQ(expect_success,
317               delta_performer->Write(payload_data.data(), payload_data.size()));
318     EXPECT_EQ(0, performer_.Close());
319 
320     brillo::Blob partition_data;
321     EXPECT_TRUE(utils::ReadFile(new_part.path(), &partition_data));
322     return partition_data;
323   }
324 
325   // Calls delta performer's Write method by pretending to pass in bytes from a
326   // delta file whose metadata size is actual_metadata_size and tests if all
327   // checks are correctly performed if the install plan contains
328   // expected_metadata_size and that the result of the parsing are as per
329   // hash_checks_mandatory flag.
DoMetadataSizeTest(uint64_t expected_metadata_size,uint64_t actual_metadata_size,bool hash_checks_mandatory)330   void DoMetadataSizeTest(uint64_t expected_metadata_size,
331                           uint64_t actual_metadata_size,
332                           bool hash_checks_mandatory) {
333     install_plan_.hash_checks_mandatory = hash_checks_mandatory;
334 
335     // Set a valid magic string and version number 1.
336     EXPECT_TRUE(performer_.Write("CrAU", 4));
337     uint64_t version = htobe64(kBrilloMajorPayloadVersion);
338     EXPECT_TRUE(performer_.Write(&version, 8));
339 
340     payload_.metadata_size = expected_metadata_size;
341     payload_.size = actual_metadata_size + 1;
342     ErrorCode error_code;
343     // When filling in size in manifest, exclude the size of the 24-byte header.
344     uint64_t size_in_manifest = htobe64(actual_metadata_size - 24);
345     performer_.Write(&size_in_manifest, 8, &error_code);
346     auto signature_size = htobe64(10);
347     bool result = performer_.Write(&signature_size, 4, &error_code);
348     if (expected_metadata_size == actual_metadata_size ||
349         !hash_checks_mandatory) {
350       EXPECT_TRUE(result);
351     } else {
352       EXPECT_FALSE(result);
353       EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
354     }
355 
356     EXPECT_LT(performer_.Close(), 0);
357   }
358 
359   // Generates a valid delta file but tests the delta performer by supplying
360   // different metadata signatures as per metadata_signature_test flag and
361   // sees if the result of the parsing are as per hash_checks_mandatory flag.
DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,bool sign_payload,bool hash_checks_mandatory)362   void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
363                                bool sign_payload,
364                                bool hash_checks_mandatory) {
365     // Loads the payload and parses the manifest.
366     brillo::Blob payload = GeneratePayload(brillo::Blob(),
367                                            vector<AnnotatedOperation>(),
368                                            sign_payload,
369                                            kBrilloMajorPayloadVersion,
370                                            kFullPayloadMinorVersion);
371 
372     payload_.size = payload.size();
373     LOG(INFO) << "Payload size: " << payload.size();
374 
375     install_plan_.hash_checks_mandatory = hash_checks_mandatory;
376 
377     MetadataParseResult expected_result, actual_result;
378     ErrorCode expected_error, actual_error;
379 
380     // Fill up the metadata signature in install plan according to the test.
381     switch (metadata_signature_test) {
382       case kEmptyMetadataSignature:
383         payload_.metadata_signature.clear();
384         // We need to set the signature size in a signed payload to zero.
385         std::fill(
386             std::next(payload.begin(), 20), std::next(payload.begin(), 24), 0);
387         expected_result = MetadataParseResult::kError;
388         expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
389         break;
390 
391       case kInvalidMetadataSignature:
392         payload_.metadata_signature = kBogusMetadataSignature1;
393         expected_result = MetadataParseResult::kError;
394         expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
395         break;
396 
397       case kValidMetadataSignature:
398       default:
399         // Set the install plan's metadata size to be the same as the one
400         // in the manifest so that we pass the metadata size checks. Only
401         // then we can get to manifest signature checks.
402         ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
403             payload.data(),
404             payload_.metadata_size,
405             GetBuildArtifactsPath(kUnittestPrivateKeyPath),
406             &payload_.metadata_signature));
407         EXPECT_FALSE(payload_.metadata_signature.empty());
408         expected_result = MetadataParseResult::kSuccess;
409         expected_error = ErrorCode::kSuccess;
410         break;
411     }
412 
413     // Ignore the expected result/error if hash checks are not mandatory.
414     if (!hash_checks_mandatory) {
415       expected_result = MetadataParseResult::kSuccess;
416       expected_error = ErrorCode::kSuccess;
417     }
418 
419     // Init actual_error with an invalid value so that we make sure
420     // ParsePayloadMetadata properly populates it in all cases.
421     actual_error = ErrorCode::kUmaReportedMax;
422     actual_result = performer_.ParsePayloadMetadata(payload, &actual_error);
423 
424     EXPECT_EQ(expected_result, actual_result);
425     EXPECT_EQ(expected_error, actual_error);
426 
427     // Check that the parsed metadata size is what's expected. This test
428     // implicitly confirms that the metadata signature is valid, if required.
429     EXPECT_EQ(payload_.metadata_size, performer_.metadata_size_);
430   }
431 
432   FakePrefs prefs_;
433   InstallPlan install_plan_;
434   InstallPlan::Payload payload_;
435   FakeBootControl fake_boot_control_;
436   FakeHardware fake_hardware_;
437   MockDownloadActionDelegate mock_delegate_;
438   FileDescriptorPtr fake_ecc_fd_;
439   DeltaPerformer performer_{&prefs_,
440                             &fake_boot_control_,
441                             &fake_hardware_,
442                             &mock_delegate_,
443                             &install_plan_,
444                             &payload_,
445                             false /* interactive */,
446                             "" /* Update certs path */};
447 };
448 
TEST_F(DeltaPerformerTest,FullPayloadWriteTest)449 TEST_F(DeltaPerformerTest, FullPayloadWriteTest) {
450   payload_.type = InstallPayloadType::kFull;
451   brillo::Blob expected_data =
452       brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
453   expected_data.resize(4096);  // block size
454   vector<AnnotatedOperation> aops;
455   AnnotatedOperation aop;
456   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
457   aop.op.set_data_offset(0);
458   aop.op.set_data_length(expected_data.size());
459   aop.op.set_type(InstallOperation::REPLACE);
460   aops.push_back(aop);
461 
462   brillo::Blob payload_data = GeneratePayload(expected_data,
463                                               aops,
464                                               false,
465                                               kBrilloMajorPayloadVersion,
466                                               kFullPayloadMinorVersion);
467 
468   EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
469 }
470 
TEST_F(DeltaPerformerTest,ShouldCancelTest)471 TEST_F(DeltaPerformerTest, ShouldCancelTest) {
472   payload_.type = InstallPayloadType::kFull;
473   brillo::Blob expected_data =
474       brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
475   expected_data.resize(4096);  // block size
476   vector<AnnotatedOperation> aops;
477   AnnotatedOperation aop;
478   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
479   aop.op.set_data_offset(0);
480   aop.op.set_data_length(expected_data.size());
481   aop.op.set_type(InstallOperation::REPLACE);
482   aops.push_back(aop);
483 
484   brillo::Blob payload_data = GeneratePayload(expected_data,
485                                               aops,
486                                               false,
487                                               kBrilloMajorPayloadVersion,
488                                               kFullPayloadMinorVersion);
489 
490   testing::Mock::VerifyAndClearExpectations(&mock_delegate_);
491   EXPECT_CALL(mock_delegate_, ShouldCancel(_))
492       .WillOnce(testing::DoAll(testing::SetArgPointee<0>(ErrorCode::kError),
493                                testing::Return(true)));
494 
495   ApplyPayload(payload_data, "/dev/null", false);
496 }
497 
TEST_F(DeltaPerformerTest,ReplaceOperationTest)498 TEST_F(DeltaPerformerTest, ReplaceOperationTest) {
499   brillo::Blob expected_data =
500       brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
501   expected_data.resize(4096);  // block size
502   vector<AnnotatedOperation> aops;
503   AnnotatedOperation aop;
504   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
505   aop.op.set_data_offset(0);
506   aop.op.set_data_length(expected_data.size());
507   aop.op.set_type(InstallOperation::REPLACE);
508   aops.push_back(aop);
509 
510   brillo::Blob payload_data = GeneratePayload(expected_data, aops, false);
511 
512   EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
513 }
514 
TEST_F(DeltaPerformerTest,ReplaceBzOperationTest)515 TEST_F(DeltaPerformerTest, ReplaceBzOperationTest) {
516   brillo::Blob expected_data =
517       brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
518   expected_data.resize(4096);  // block size
519   brillo::Blob bz_data;
520   EXPECT_TRUE(BzipCompress(expected_data, &bz_data));
521 
522   vector<AnnotatedOperation> aops;
523   AnnotatedOperation aop;
524   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
525   aop.op.set_data_offset(0);
526   aop.op.set_data_length(bz_data.size());
527   aop.op.set_type(InstallOperation::REPLACE_BZ);
528   aops.push_back(aop);
529 
530   brillo::Blob payload_data = GeneratePayload(bz_data, aops, false);
531 
532   EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
533 }
534 
TEST_F(DeltaPerformerTest,ReplaceXzOperationTest)535 TEST_F(DeltaPerformerTest, ReplaceXzOperationTest) {
536   brillo::Blob xz_data(std::begin(kXzCompressedData),
537                        std::end(kXzCompressedData));
538   // The compressed xz data contains a single "a" and padded with zero for the
539   // rest of the block.
540   brillo::Blob expected_data = brillo::Blob(4096, 0);
541   expected_data[0] = 'a';
542 
543   AnnotatedOperation aop;
544   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
545   aop.op.set_data_offset(0);
546   aop.op.set_data_length(xz_data.size());
547   aop.op.set_type(InstallOperation::REPLACE_XZ);
548   vector<AnnotatedOperation> aops = {aop};
549 
550   brillo::Blob payload_data = GeneratePayload(xz_data, aops, false);
551 
552   EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
553 }
554 
TEST_F(DeltaPerformerTest,ZeroOperationTest)555 TEST_F(DeltaPerformerTest, ZeroOperationTest) {
556   brillo::Blob existing_data = brillo::Blob(4096 * 10, 'a');
557   brillo::Blob expected_data = existing_data;
558   // Blocks 4, 5 and 7 should have zeros instead of 'a' after the operation is
559   // applied.
560   std::fill(
561       expected_data.data() + 4096 * 4, expected_data.data() + 4096 * 6, 0);
562   std::fill(
563       expected_data.data() + 4096 * 7, expected_data.data() + 4096 * 8, 0);
564 
565   AnnotatedOperation aop;
566   *(aop.op.add_dst_extents()) = ExtentForRange(4, 2);
567   *(aop.op.add_dst_extents()) = ExtentForRange(7, 1);
568   aop.op.set_type(InstallOperation::ZERO);
569   vector<AnnotatedOperation> aops = {aop};
570 
571   brillo::Blob payload_data = GeneratePayload(brillo::Blob(), aops, false);
572 
573   EXPECT_EQ(expected_data,
574             ApplyPayloadToData(payload_data, "/dev/null", existing_data, true));
575 }
576 
TEST_F(DeltaPerformerTest,SourceCopyOperationTest)577 TEST_F(DeltaPerformerTest, SourceCopyOperationTest) {
578   brillo::Blob expected_data(std::begin(kRandomString),
579                              std::end(kRandomString));
580   expected_data.resize(4096);  // block size
581   AnnotatedOperation aop;
582   *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
583   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
584   aop.op.set_type(InstallOperation::SOURCE_COPY);
585   brillo::Blob src_hash;
586   EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
587   aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
588 
589   ScopedTempFile source("Source-XXXXXX");
590   EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
591 
592   PartitionConfig old_part(kPartitionNameRoot);
593   old_part.path = source.path();
594   old_part.size = expected_data.size();
595 
596   brillo::Blob payload_data =
597       GeneratePayload(brillo::Blob(), {aop}, false, &old_part);
598 
599   EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
600 }
601 
TEST_F(DeltaPerformerTest,PuffdiffOperationTest)602 TEST_F(DeltaPerformerTest, PuffdiffOperationTest) {
603   AnnotatedOperation aop;
604   *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
605   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
606   brillo::Blob puffdiff_payload(std::begin(puffdiff_patch),
607                                 std::end(puffdiff_patch));
608   aop.op.set_data_offset(0);
609   aop.op.set_data_length(puffdiff_payload.size());
610   aop.op.set_type(InstallOperation::PUFFDIFF);
611   brillo::Blob src(std::begin(src_deflates), std::end(src_deflates));
612   src.resize(4096);  // block size
613   brillo::Blob src_hash;
614   EXPECT_TRUE(HashCalculator::RawHashOfData(src, &src_hash));
615   aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
616 
617   ScopedTempFile source("Source-XXXXXX");
618   EXPECT_TRUE(test_utils::WriteFileVector(source.path(), src));
619 
620   PartitionConfig old_part(kPartitionNameRoot);
621   old_part.path = source.path();
622   old_part.size = src.size();
623 
624   brillo::Blob payload_data =
625       GeneratePayload(puffdiff_payload, {aop}, false, &old_part);
626 
627   brillo::Blob dst(std::begin(dst_deflates), std::end(dst_deflates));
628   EXPECT_EQ(dst, ApplyPayload(payload_data, source.path(), true));
629 }
630 
TEST_F(DeltaPerformerTest,SourceHashMismatchTest)631 TEST_F(DeltaPerformerTest, SourceHashMismatchTest) {
632   brillo::Blob expected_data = {'f', 'o', 'o'};
633   brillo::Blob actual_data = {'b', 'a', 'r'};
634   expected_data.resize(4096);  // block size
635   actual_data.resize(4096);    // block size
636 
637   AnnotatedOperation aop;
638   *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
639   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
640   aop.op.set_type(InstallOperation::SOURCE_COPY);
641   brillo::Blob src_hash;
642   EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
643   aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
644 
645   ScopedTempFile source("Source-XXXXXX");
646   EXPECT_TRUE(test_utils::WriteFileVector(source.path(), actual_data));
647 
648   PartitionConfig old_part(kPartitionNameRoot);
649   old_part.path = source.path();
650   old_part.size = actual_data.size();
651 
652   brillo::Blob payload_data =
653       GeneratePayload(brillo::Blob(), {aop}, false, &old_part);
654 
655   // When source hash mismatches, PartitionWriter will refuse to write anything.
656   // Therefore we should expect an empty blob.
657   EXPECT_EQ(brillo::Blob{}, ApplyPayload(payload_data, source.path(), false));
658 }
659 
TEST_F(DeltaPerformerTest,ExtentsToByteStringTest)660 TEST_F(DeltaPerformerTest, ExtentsToByteStringTest) {
661   uint64_t test[] = {1, 1, 4, 2, 0, 1};
662   static_assert(base::size(test) % 2 == 0, "Array size uneven");
663   const uint64_t block_size = 4096;
664   const uint64_t file_length = 4 * block_size - 13;
665 
666   google::protobuf::RepeatedPtrField<Extent> extents;
667   for (size_t i = 0; i < base::size(test); i += 2) {
668     *(extents.Add()) = ExtentForRange(test[i], test[i + 1]);
669   }
670 
671   string expected_output = "4096:4096,16384:8192,0:4083";
672   string actual_output;
673   EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(
674       extents, block_size, file_length, &actual_output));
675   EXPECT_EQ(expected_output, actual_output);
676 }
677 
TEST_F(DeltaPerformerTest,ValidateManifestFullGoodTest)678 TEST_F(DeltaPerformerTest, ValidateManifestFullGoodTest) {
679   // The Manifest we are validating.
680   DeltaArchiveManifest manifest;
681   for (const auto& part_name : {"kernel", "rootfs"}) {
682     auto part = manifest.add_partitions();
683     part->set_partition_name(part_name);
684     part->mutable_new_partition_info();
685   }
686   manifest.set_minor_version(kFullPayloadMinorVersion);
687 
688   RunManifestValidation(manifest,
689                         kBrilloMajorPayloadVersion,
690                         InstallPayloadType::kFull,
691                         ErrorCode::kSuccess);
692 }
693 
TEST_F(DeltaPerformerTest,ValidateManifestDeltaMaxGoodTest)694 TEST_F(DeltaPerformerTest, ValidateManifestDeltaMaxGoodTest) {
695   // The Manifest we are validating.
696   DeltaArchiveManifest manifest;
697   for (const auto& part_name : {"kernel", "rootfs"}) {
698     auto part = manifest.add_partitions();
699     part->set_partition_name(part_name);
700     part->mutable_old_partition_info();
701     part->mutable_new_partition_info();
702   }
703   manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
704 
705   RunManifestValidation(manifest,
706                         kBrilloMajorPayloadVersion,
707                         InstallPayloadType::kDelta,
708                         ErrorCode::kSuccess);
709 }
710 
TEST_F(DeltaPerformerTest,ValidateManifestDeltaMinGoodTest)711 TEST_F(DeltaPerformerTest, ValidateManifestDeltaMinGoodTest) {
712   // The Manifest we are validating.
713   DeltaArchiveManifest manifest;
714   for (const auto& part_name : {"kernel", "rootfs"}) {
715     auto part = manifest.add_partitions();
716     part->set_partition_name(part_name);
717     part->mutable_old_partition_info();
718     part->mutable_new_partition_info();
719   }
720   manifest.set_minor_version(kMinSupportedMinorPayloadVersion);
721 
722   RunManifestValidation(manifest,
723                         kBrilloMajorPayloadVersion,
724                         InstallPayloadType::kDelta,
725                         ErrorCode::kSuccess);
726 }
727 
TEST_F(DeltaPerformerTest,ValidateManifestFullUnsetMinorVersion)728 TEST_F(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
729   // The Manifest we are validating.
730   DeltaArchiveManifest manifest;
731 
732   RunManifestValidation(manifest,
733                         kMaxSupportedMajorPayloadVersion,
734                         InstallPayloadType::kFull,
735                         ErrorCode::kSuccess);
736 }
737 
TEST_F(DeltaPerformerTest,ValidateManifestDeltaUnsetMinorVersion)738 TEST_F(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
739   // The Manifest we are validating.
740   DeltaArchiveManifest manifest;
741   // Add an empty rootfs partition info to trick the DeltaPerformer into think
742   // that this is a delta payload manifest with a missing minor version.
743   auto rootfs = manifest.add_partitions();
744   rootfs->set_partition_name("rootfs");
745   rootfs->mutable_old_partition_info();
746 
747   RunManifestValidation(manifest,
748                         kMaxSupportedMajorPayloadVersion,
749                         InstallPayloadType::kDelta,
750                         ErrorCode::kUnsupportedMinorPayloadVersion);
751 }
752 
TEST_F(DeltaPerformerTest,ValidateManifestFullOldKernelTest)753 TEST_F(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
754   // The Manifest we are validating.
755   DeltaArchiveManifest manifest;
756   for (const auto& part_name : {"kernel", "rootfs"}) {
757     auto part = manifest.add_partitions();
758     part->set_partition_name(part_name);
759     part->mutable_old_partition_info();
760     part->mutable_new_partition_info();
761   }
762   manifest.mutable_partitions(0)->clear_old_partition_info();
763   RunManifestValidation(manifest,
764                         kBrilloMajorPayloadVersion,
765                         InstallPayloadType::kFull,
766                         ErrorCode::kPayloadMismatchedType);
767 }
768 
TEST_F(DeltaPerformerTest,ValidateManifestFullPartitionUpdateTest)769 TEST_F(DeltaPerformerTest, ValidateManifestFullPartitionUpdateTest) {
770   // The Manifest we are validating.
771   DeltaArchiveManifest manifest;
772   PartitionUpdate* partition = manifest.add_partitions();
773   partition->mutable_old_partition_info();
774   partition->mutable_new_partition_info();
775   manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
776 
777   RunManifestValidation(manifest,
778                         kBrilloMajorPayloadVersion,
779                         InstallPayloadType::kFull,
780                         ErrorCode::kPayloadMismatchedType);
781 }
782 
TEST_F(DeltaPerformerTest,ValidateManifestBadMinorVersion)783 TEST_F(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
784   // The Manifest we are validating.
785   DeltaArchiveManifest manifest;
786 
787   // Generate a bad version number.
788   manifest.set_minor_version(kMaxSupportedMinorPayloadVersion + 10000);
789   // Mark the manifest as a delta payload by setting |old_partition_info|.
790   manifest.add_partitions()->mutable_old_partition_info();
791 
792   RunManifestValidation(manifest,
793                         kMaxSupportedMajorPayloadVersion,
794                         InstallPayloadType::kDelta,
795                         ErrorCode::kUnsupportedMinorPayloadVersion);
796 }
797 
TEST_F(DeltaPerformerTest,ValidateManifestDowngrade)798 TEST_F(DeltaPerformerTest, ValidateManifestDowngrade) {
799   // The Manifest we are validating.
800   DeltaArchiveManifest manifest;
801 
802   manifest.set_minor_version(kFullPayloadMinorVersion);
803   manifest.set_max_timestamp(1);
804   fake_hardware_.SetBuildTimestamp(2);
805 
806   RunManifestValidation(manifest,
807                         kMaxSupportedMajorPayloadVersion,
808                         InstallPayloadType::kFull,
809                         ErrorCode::kPayloadTimestampError);
810 }
811 
TEST_F(DeltaPerformerTest,ValidatePerPartitionTimestampSuccess)812 TEST_F(DeltaPerformerTest, ValidatePerPartitionTimestampSuccess) {
813   // The Manifest we are validating.
814   DeltaArchiveManifest manifest;
815 
816   manifest.set_minor_version(kFullPayloadMinorVersion);
817   manifest.set_max_timestamp(2);
818   fake_hardware_.SetBuildTimestamp(1);
819   auto& partition = *manifest.add_partitions();
820   partition.set_version("10");
821   partition.set_partition_name("system");
822   fake_hardware_.SetVersion("system", "5");
823 
824   RunManifestValidation(manifest,
825                         kMaxSupportedMajorPayloadVersion,
826                         InstallPayloadType::kFull,
827                         ErrorCode::kSuccess);
828 }
829 
TEST_F(DeltaPerformerTest,BrilloMetadataSignatureSizeTest)830 TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeTest) {
831   unsigned int seed = time(nullptr);
832   EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
833 
834   uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
835   EXPECT_TRUE(
836       performer_.Write(&major_version, PayloadMetadata::kDeltaVersionSize));
837 
838   uint64_t manifest_size = rand_r(&seed) % 256;
839   uint32_t metadata_signature_size = rand_r(&seed) % 256;
840 
841   // The payload size has to be bigger than the |metadata_size| and
842   // |metadata_signature_size|
843   payload_.size = PayloadMetadata::kDeltaManifestSizeOffset +
844                   PayloadMetadata::kDeltaManifestSizeSize +
845                   PayloadMetadata::kDeltaMetadataSignatureSizeSize +
846                   manifest_size + metadata_signature_size + 1;
847 
848   uint64_t manifest_size_be = htobe64(manifest_size);
849   EXPECT_TRUE(performer_.Write(&manifest_size_be,
850                                PayloadMetadata::kDeltaManifestSizeSize));
851 
852   uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
853   EXPECT_TRUE(
854       performer_.Write(&metadata_signature_size_be,
855                        PayloadMetadata::kDeltaMetadataSignatureSizeSize));
856 
857   EXPECT_LT(performer_.Close(), 0);
858 
859   EXPECT_TRUE(performer_.IsHeaderParsed());
860   EXPECT_EQ(kBrilloMajorPayloadVersion, performer_.major_payload_version_);
861   EXPECT_EQ(24 + manifest_size, performer_.metadata_size_);  // 4 + 8 + 8 + 4
862   EXPECT_EQ(metadata_signature_size, performer_.metadata_signature_size_);
863 }
864 
TEST_F(DeltaPerformerTest,BrilloMetadataSizeNOKTest)865 TEST_F(DeltaPerformerTest, BrilloMetadataSizeNOKTest) {
866   unsigned int seed = time(nullptr);
867   EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
868 
869   uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
870   EXPECT_TRUE(
871       performer_.Write(&major_version, PayloadMetadata::kDeltaVersionSize));
872 
873   uint64_t manifest_size = UINT64_MAX - 600;  // Subtract to avoid wrap around.
874   uint64_t manifest_offset = PayloadMetadata::kDeltaManifestSizeOffset +
875                              PayloadMetadata::kDeltaManifestSizeSize +
876                              PayloadMetadata::kDeltaMetadataSignatureSizeSize;
877   payload_.metadata_size = manifest_offset + manifest_size;
878   uint32_t metadata_signature_size = rand_r(&seed) % 256;
879 
880   // The payload size is greater than the payload header but smaller than
881   // |metadata_signature_size| + |metadata_size|
882   payload_.size = manifest_offset + metadata_signature_size + 1;
883 
884   uint64_t manifest_size_be = htobe64(manifest_size);
885   EXPECT_TRUE(performer_.Write(&manifest_size_be,
886                                PayloadMetadata::kDeltaManifestSizeSize));
887   uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
888 
889   ErrorCode error;
890   EXPECT_FALSE(
891       performer_.Write(&metadata_signature_size_be,
892                        PayloadMetadata::kDeltaMetadataSignatureSizeSize + 1,
893                        &error));
894 
895   EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error);
896 }
897 
TEST_F(DeltaPerformerTest,BrilloMetadataSignatureSizeNOKTest)898 TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeNOKTest) {
899   unsigned int seed = time(nullptr);
900   EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
901 
902   uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
903   EXPECT_TRUE(
904       performer_.Write(&major_version, PayloadMetadata::kDeltaVersionSize));
905 
906   uint64_t manifest_size = rand_r(&seed) % 256;
907   // Subtract from UINT32_MAX to avoid wrap around.
908   uint32_t metadata_signature_size = UINT32_MAX - 600;
909 
910   // The payload size is greater than |manifest_size| but smaller than
911   // |metadata_signature_size|
912   payload_.size = manifest_size + 1;
913 
914   uint64_t manifest_size_be = htobe64(manifest_size);
915   EXPECT_TRUE(performer_.Write(&manifest_size_be,
916                                PayloadMetadata::kDeltaManifestSizeSize));
917 
918   uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
919   ErrorCode error;
920   EXPECT_FALSE(
921       performer_.Write(&metadata_signature_size_be,
922                        PayloadMetadata::kDeltaMetadataSignatureSizeSize + 1,
923                        &error));
924 
925   EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error);
926 }
927 
TEST_F(DeltaPerformerTest,BrilloParsePayloadMetadataTest)928 TEST_F(DeltaPerformerTest, BrilloParsePayloadMetadataTest) {
929   brillo::Blob payload_data = GeneratePayload(
930       {}, {}, true, kBrilloMajorPayloadVersion, kSourceMinorPayloadVersion);
931   install_plan_.hash_checks_mandatory = true;
932   payload_.size = payload_data.size();
933   ErrorCode error;
934   EXPECT_EQ(MetadataParseResult::kSuccess,
935             performer_.ParsePayloadMetadata(payload_data, &error));
936   EXPECT_EQ(ErrorCode::kSuccess, error);
937 }
938 
TEST_F(DeltaPerformerTest,BadDeltaMagicTest)939 TEST_F(DeltaPerformerTest, BadDeltaMagicTest) {
940   EXPECT_TRUE(performer_.Write("junk", 4));
941   EXPECT_FALSE(performer_.Write("morejunk", 8));
942   EXPECT_LT(performer_.Close(), 0);
943 }
944 
TEST_F(DeltaPerformerTest,MissingMandatoryMetadataSizeTest)945 TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
946   DoMetadataSizeTest(0, 75456, true);
947 }
948 
TEST_F(DeltaPerformerTest,MissingNonMandatoryMetadataSizeTest)949 TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
950   DoMetadataSizeTest(0, 123456, false);
951 }
952 
TEST_F(DeltaPerformerTest,InvalidMandatoryMetadataSizeTest)953 TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
954   DoMetadataSizeTest(13000, 140000, true);
955 }
956 
TEST_F(DeltaPerformerTest,InvalidNonMandatoryMetadataSizeTest)957 TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
958   DoMetadataSizeTest(40000, 50000, false);
959 }
960 
TEST_F(DeltaPerformerTest,ValidMandatoryMetadataSizeTest)961 TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
962   DoMetadataSizeTest(85376, 85376, true);
963 }
964 
TEST_F(DeltaPerformerTest,MandatoryEmptyMetadataSignatureTest)965 TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) {
966   DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
967 }
968 
TEST_F(DeltaPerformerTest,NonMandatoryEmptyMetadataSignatureTest)969 TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) {
970   DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
971 }
972 
TEST_F(DeltaPerformerTest,MandatoryInvalidMetadataSignatureTest)973 TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) {
974   DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
975 }
976 
TEST_F(DeltaPerformerTest,NonMandatoryInvalidMetadataSignatureTest)977 TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) {
978   DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
979 }
980 
TEST_F(DeltaPerformerTest,MandatoryValidMetadataSignature1Test)981 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) {
982   DoMetadataSignatureTest(kValidMetadataSignature, false, true);
983 }
984 
TEST_F(DeltaPerformerTest,MandatoryValidMetadataSignature2Test)985 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) {
986   DoMetadataSignatureTest(kValidMetadataSignature, true, true);
987 }
988 
TEST_F(DeltaPerformerTest,NonMandatoryValidMetadataSignatureTest)989 TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) {
990   DoMetadataSignatureTest(kValidMetadataSignature, true, false);
991 }
992 
TEST_F(DeltaPerformerTest,UsePublicKeyFromResponse)993 TEST_F(DeltaPerformerTest, UsePublicKeyFromResponse) {
994   // The result of the GetPublicKeyResponse() method is based on three things
995   //
996   //  1. Whether it's an official build; and
997   //  2. Whether the Public RSA key to be used is in the root filesystem; and
998   //  3. Whether the response has a public key
999   //
1000   // We test all eight combinations to ensure that we only use the
1001   // public key in the response if
1002   //
1003   //  a. it's not an official build; and
1004   //  b. there is no key in the root filesystem.
1005 
1006   base::ScopedTempDir temp_dir;
1007   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1008   string non_existing_file = temp_dir.GetPath().Append("non-existing").value();
1009   string existing_file = temp_dir.GetPath().Append("existing").value();
1010   constexpr char kExistingKey[] = "Existing";
1011   ASSERT_TRUE(test_utils::WriteFileString(existing_file, kExistingKey));
1012 
1013   // Non-official build, non-existing public-key, key in response ->
1014   // kResponseKey
1015   fake_hardware_.SetIsOfficialBuild(false);
1016   performer_.public_key_path_ = non_existing_file;
1017   // This is the result of 'echo -n "Response" | base64' and is not meant to be
1018   // a valid public key, but it is valid base-64.
1019   constexpr char kResponseKey[] = "Response";
1020   constexpr char kBase64ResponseKey[] = "UmVzcG9uc2U=";
1021   install_plan_.public_key_rsa = kBase64ResponseKey;
1022   string public_key;
1023   EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1024   EXPECT_EQ(public_key, kResponseKey);
1025   // Same with official build -> no key
1026   fake_hardware_.SetIsOfficialBuild(true);
1027   EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1028   EXPECT_TRUE(public_key.empty());
1029 
1030   // Non-official build, existing public-key, key in response -> kExistingKey
1031   fake_hardware_.SetIsOfficialBuild(false);
1032   performer_.public_key_path_ = existing_file;
1033   install_plan_.public_key_rsa = kBase64ResponseKey;
1034   EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1035   EXPECT_EQ(public_key, kExistingKey);
1036   // Same with official build -> kExistingKey
1037   fake_hardware_.SetIsOfficialBuild(true);
1038   EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1039   EXPECT_EQ(public_key, kExistingKey);
1040 
1041   // Non-official build, non-existing public-key, no key in response -> no key
1042   fake_hardware_.SetIsOfficialBuild(false);
1043   performer_.public_key_path_ = non_existing_file;
1044   install_plan_.public_key_rsa = "";
1045   EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1046   EXPECT_TRUE(public_key.empty());
1047   // Same with official build -> no key
1048   fake_hardware_.SetIsOfficialBuild(true);
1049   EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1050   EXPECT_TRUE(public_key.empty());
1051 
1052   // Non-official build, existing public-key, no key in response -> kExistingKey
1053   fake_hardware_.SetIsOfficialBuild(false);
1054   performer_.public_key_path_ = existing_file;
1055   install_plan_.public_key_rsa = "";
1056   EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1057   EXPECT_EQ(public_key, kExistingKey);
1058   // Same with official build -> kExistingKey
1059   fake_hardware_.SetIsOfficialBuild(true);
1060   EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1061   EXPECT_EQ(public_key, kExistingKey);
1062 
1063   // Non-official build, non-existing public-key, key in response
1064   // but invalid base64 -> false
1065   fake_hardware_.SetIsOfficialBuild(false);
1066   performer_.public_key_path_ = non_existing_file;
1067   install_plan_.public_key_rsa = "not-valid-base64";
1068   EXPECT_FALSE(performer_.GetPublicKey(&public_key));
1069 }
1070 
1071 // TODO(197361113) re-enable the test after we bump the version in config.
TEST(DISABLED_ConfVersionTest,ConfVersionsMatch)1072 TEST(DISABLED_ConfVersionTest, ConfVersionsMatch) {
1073   // Test that the versions in update_engine.conf that is installed to the
1074   // image match the maximum supported delta versions in the update engine.
1075   uint32_t minor_version;
1076   brillo::KeyValueStore store;
1077   EXPECT_TRUE(store.Load(GetBuildArtifactsPath().Append("update_engine.conf")));
1078   EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
1079   EXPECT_EQ(kMaxSupportedMinorPayloadVersion, minor_version);
1080 
1081   string major_version_str;
1082   uint64_t major_version;
1083   EXPECT_TRUE(store.GetString("PAYLOAD_MAJOR_VERSION", &major_version_str));
1084   EXPECT_TRUE(base::StringToUint64(major_version_str, &major_version));
1085   EXPECT_EQ(kMaxSupportedMajorPayloadVersion, major_version);
1086 }
1087 
TEST_F(DeltaPerformerTest,FullPayloadCanResumeTest)1088 TEST_F(DeltaPerformerTest, FullPayloadCanResumeTest) {
1089   payload_.type = InstallPayloadType::kFull;
1090   brillo::Blob expected_data =
1091       brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
1092   expected_data.resize(4096);  // block size
1093   vector<AnnotatedOperation> aops;
1094   AnnotatedOperation aop;
1095   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
1096   aop.op.set_data_offset(0);
1097   aop.op.set_data_length(expected_data.size());
1098   aop.op.set_type(InstallOperation::REPLACE);
1099   aops.push_back(aop);
1100 
1101   brillo::Blob payload_data = GeneratePayload(expected_data,
1102                                               aops,
1103                                               false,
1104                                               kBrilloMajorPayloadVersion,
1105                                               kFullPayloadMinorVersion);
1106 
1107   ASSERT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
1108   performer_.CheckpointUpdateProgress(true);
1109   const std::string payload_id = "12345";
1110   prefs_.SetString(kPrefsUpdateCheckResponseHash, payload_id);
1111   ASSERT_TRUE(DeltaPerformer::CanResumeUpdate(&prefs_, payload_id));
1112 }
1113 
1114 class TestDeltaPerformer : public DeltaPerformer {
1115  public:
1116   using DeltaPerformer::DeltaPerformer;
1117 
CreatePartitionWriter(const PartitionUpdate & partition_update,const InstallPlan::Partition & install_part,DynamicPartitionControlInterface * dynamic_control,size_t block_size,bool is_interactive,bool is_dynamic_partition)1118   std::unique_ptr<PartitionWriterInterface> CreatePartitionWriter(
1119       const PartitionUpdate& partition_update,
1120       const InstallPlan::Partition& install_part,
1121       DynamicPartitionControlInterface* dynamic_control,
1122       size_t block_size,
1123       bool is_interactive,
1124       bool is_dynamic_partition) {
1125     LOG(INFO) << __FUNCTION__ << ": " << install_part.name;
1126     auto node = partition_writers_.extract(install_part.name);
1127     return std::move(node.mapped());
1128   }
1129 
ShouldCheckpoint()1130   bool ShouldCheckpoint() override { return true; }
1131 
1132   std::map<std::string, std::unique_ptr<MockPartitionWriter>>
1133       partition_writers_;
1134 };
1135 
1136 namespace {
GetSourceCopyOp(uint32_t src_block,uint32_t dst_block,const void * data,size_t length)1137 AnnotatedOperation GetSourceCopyOp(uint32_t src_block,
1138                                    uint32_t dst_block,
1139                                    const void* data,
1140                                    size_t length) {
1141   AnnotatedOperation aop;
1142   *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
1143   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
1144   aop.op.set_type(InstallOperation::SOURCE_COPY);
1145   brillo::Blob src_hash;
1146   HashCalculator::RawHashOfBytes(data, length, &src_hash);
1147   aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
1148   return aop;
1149 }
1150 }  // namespace
1151 
TEST_F(DeltaPerformerTest,SetNextOpIndex)1152 TEST_F(DeltaPerformerTest, SetNextOpIndex) {
1153   TestDeltaPerformer delta_performer{&prefs_,
1154                                      &fake_boot_control_,
1155                                      &fake_hardware_,
1156                                      &mock_delegate_,
1157                                      &install_plan_,
1158                                      &payload_,
1159                                      false};
1160   brillo::Blob expected_data(std::begin(kRandomString),
1161                              std::end(kRandomString));
1162   expected_data.resize(4096 * 2);  // block size
1163   AnnotatedOperation aop;
1164 
1165   ScopedTempFile source("Source-XXXXXX");
1166   EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
1167 
1168   PartitionConfig old_part(kPartitionNameRoot);
1169   old_part.path = source.path();
1170   old_part.size = expected_data.size();
1171 
1172   delta_performer.partition_writers_[kPartitionNameRoot] =
1173       std::make_unique<MockPartitionWriter>();
1174   auto& writer1 = *delta_performer.partition_writers_[kPartitionNameRoot];
1175 
1176   Sequence seq;
1177   std::vector<size_t> indices;
1178   EXPECT_CALL(writer1, CheckpointUpdateProgress(_))
1179       .WillRepeatedly(
1180           [&indices](size_t index) mutable { indices.emplace_back(index); });
1181   EXPECT_CALL(writer1, Init(_, true, _)).Times(1).WillOnce(Return(true));
1182   EXPECT_CALL(writer1, PerformSourceCopyOperation(_, _))
1183       .Times(2)
1184       .WillRepeatedly(Return(true));
1185 
1186   brillo::Blob payload_data = GeneratePayload(
1187       brillo::Blob(),
1188       {GetSourceCopyOp(0, 0, expected_data.data(), 4096),
1189        GetSourceCopyOp(1, 1, expected_data.data() + 4096, 4096)},
1190       false,
1191       &old_part);
1192 
1193   ApplyPayloadToData(&delta_performer, payload_data, source.path(), {}, true);
1194   ASSERT_TRUE(std::is_sorted(indices.begin(), indices.end()));
1195   ASSERT_GT(indices.size(), 0UL);
1196 
1197   // Should be equal to number of operations
1198   ASSERT_EQ(indices[indices.size() - 1], 2UL);
1199 }
1200 
1201 }  // namespace chromeos_update_engine
1202