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