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