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