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