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