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 
22 #include <string>
23 #include <vector>
24 
25 #include <base/files/file_path.h>
26 #include <base/files/file_util.h>
27 #include <base/strings/string_number_conversions.h>
28 #include <base/strings/string_util.h>
29 #include <base/strings/stringprintf.h>
30 #include <gmock/gmock.h>
31 #include <google/protobuf/repeated_field.h>
32 #include <gtest/gtest.h>
33 
34 #include "update_engine/common/constants.h"
35 #include "update_engine/common/fake_boot_control.h"
36 #include "update_engine/common/fake_hardware.h"
37 #include "update_engine/common/fake_prefs.h"
38 #include "update_engine/common/test_utils.h"
39 #include "update_engine/common/utils.h"
40 #include "update_engine/payload_consumer/mock_download_action.h"
41 #include "update_engine/payload_consumer/payload_constants.h"
42 #include "update_engine/payload_generator/bzip.h"
43 #include "update_engine/payload_generator/extent_ranges.h"
44 #include "update_engine/payload_generator/payload_file.h"
45 #include "update_engine/payload_generator/payload_signer.h"
46 #include "update_engine/update_metadata.pb.h"
47 
48 namespace chromeos_update_engine {
49 
50 using std::string;
51 using std::vector;
52 using test_utils::System;
53 using test_utils::kRandomString;
54 using testing::_;
55 
56 extern const char* kUnittestPrivateKeyPath;
57 extern const char* kUnittestPublicKeyPath;
58 
59 namespace {
60 
61 const char kBogusMetadataSignature1[] =
62     "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
63     "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
64     "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
65     "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
66     "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
67     "pLRtClp97kN2+tXGNBQqkA==";
68 
69 #ifdef __ANDROID__
70 const char kZlibFingerprintPath[] =
71     "/data/nativetest/update_engine_unittests/zlib_fingerprint";
72 #else
73 const char kZlibFingerprintPath[] = "/etc/zlib_fingerprint";
74 #endif  // __ANDROID__
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 | xz -9 --check=none | hexdump -v -e '"    " 12/1 "0x%02x, " "\n"'
87 const uint8_t kXzCompressedData[] = {
88     0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x00, 0xff, 0x12, 0xd9, 0x41,
89     0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc,
90     0x01, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x01,
91     0xad, 0xa6, 0x58, 0x04, 0x06, 0x72, 0x9e, 0x7a, 0x01, 0x00, 0x00, 0x00,
92     0x00, 0x00, 0x59, 0x5a,
93 };
94 
95 }  // namespace
96 
97 class DeltaPerformerTest : public ::testing::Test {
98  protected:
SetUp()99   void SetUp() override {
100     install_plan_.source_slot = 0;
101     install_plan_.target_slot = 1;
102     EXPECT_CALL(mock_delegate_, ShouldCancel(_))
103         .WillRepeatedly(testing::Return(false));
104   }
105 
106   // Test helper placed where it can easily be friended from DeltaPerformer.
RunManifestValidation(const DeltaArchiveManifest & manifest,uint64_t major_version,InstallPayloadType payload_type,ErrorCode expected)107   void RunManifestValidation(const DeltaArchiveManifest& manifest,
108                              uint64_t major_version,
109                              InstallPayloadType payload_type,
110                              ErrorCode expected) {
111     install_plan_.payload_type = payload_type;
112 
113     // The Manifest we are validating.
114     performer_.manifest_.CopyFrom(manifest);
115     performer_.major_payload_version_ = major_version;
116 
117     EXPECT_EQ(expected, performer_.ValidateManifest());
118   }
119 
GeneratePayload(const brillo::Blob & blob_data,const vector<AnnotatedOperation> & aops,bool sign_payload)120   brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
121                                const vector<AnnotatedOperation>& aops,
122                                bool sign_payload) {
123     return GeneratePayload(blob_data, aops, sign_payload,
124                            DeltaPerformer::kSupportedMajorPayloadVersion,
125                            DeltaPerformer::kSupportedMinorPayloadVersion);
126   }
127 
GeneratePayload(const brillo::Blob & blob_data,const vector<AnnotatedOperation> & aops,bool sign_payload,uint64_t major_version,uint32_t minor_version)128   brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
129                                const vector<AnnotatedOperation>& aops,
130                                bool sign_payload,
131                                uint64_t major_version,
132                                uint32_t minor_version) {
133     string blob_path;
134     EXPECT_TRUE(utils::MakeTempFile("Blob-XXXXXX", &blob_path, nullptr));
135     ScopedPathUnlinker blob_unlinker(blob_path);
136     EXPECT_TRUE(utils::WriteFile(blob_path.c_str(),
137                                  blob_data.data(),
138                                  blob_data.size()));
139 
140     PayloadGenerationConfig config;
141     config.version.major = major_version;
142     config.version.minor = minor_version;
143 
144     PayloadFile payload;
145     EXPECT_TRUE(payload.Init(config));
146 
147     PartitionConfig old_part(kLegacyPartitionNameRoot);
148     if (minor_version != kFullPayloadMinorVersion) {
149       // When generating a delta payload we need to include the old partition
150       // information to mark it as a delta payload.
151       old_part.path = "/dev/null";
152       old_part.size = 0;
153     }
154     PartitionConfig new_part(kLegacyPartitionNameRoot);
155     new_part.path = "/dev/zero";
156     new_part.size = 1234;
157 
158     payload.AddPartition(old_part, new_part, aops);
159 
160     // We include a kernel partition without operations.
161     old_part.name = kLegacyPartitionNameKernel;
162     new_part.name = kLegacyPartitionNameKernel;
163     new_part.size = 0;
164     payload.AddPartition(old_part, new_part, {});
165 
166     string payload_path;
167     EXPECT_TRUE(utils::MakeTempFile("Payload-XXXXXX", &payload_path, nullptr));
168     ScopedPathUnlinker payload_unlinker(payload_path);
169     EXPECT_TRUE(payload.WritePayload(payload_path, blob_path,
170         sign_payload ? kUnittestPrivateKeyPath : "",
171         &install_plan_.metadata_size));
172 
173     brillo::Blob payload_data;
174     EXPECT_TRUE(utils::ReadFile(payload_path, &payload_data));
175     return payload_data;
176   }
177 
178   // Apply |payload_data| on partition specified in |source_path|.
179   // Expect result of performer_.Write() to be |expect_success|.
180   // Returns the result of the payload application.
ApplyPayload(const brillo::Blob & payload_data,const string & source_path,bool expect_success)181   brillo::Blob ApplyPayload(const brillo::Blob& payload_data,
182                             const string& source_path,
183                             bool expect_success) {
184     return ApplyPayloadToData(payload_data, source_path, brillo::Blob(),
185                               expect_success);
186   }
187 
188   // Apply the payload provided in |payload_data| reading from the |source_path|
189   // file and writing the contents to a new partition. The existing data in the
190   // new target file are set to |target_data| before applying the payload.
191   // Expect result of performer_.Write() to be |expect_success|.
192   // 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)193   brillo::Blob ApplyPayloadToData(const brillo::Blob& payload_data,
194                                   const string& source_path,
195                                   const brillo::Blob& target_data,
196                                   bool expect_success) {
197     string new_part;
198     EXPECT_TRUE(utils::MakeTempFile("Partition-XXXXXX", &new_part, nullptr));
199     ScopedPathUnlinker partition_unlinker(new_part);
200     EXPECT_TRUE(utils::WriteFile(new_part.c_str(), target_data.data(),
201                                  target_data.size()));
202 
203     // We installed the operations only in the rootfs partition, but the
204     // delta performer needs to access all the partitions.
205     fake_boot_control_.SetPartitionDevice(
206         kLegacyPartitionNameRoot, install_plan_.target_slot, new_part);
207     fake_boot_control_.SetPartitionDevice(
208         kLegacyPartitionNameRoot, install_plan_.source_slot, source_path);
209     fake_boot_control_.SetPartitionDevice(
210         kLegacyPartitionNameKernel, install_plan_.target_slot, "/dev/null");
211     fake_boot_control_.SetPartitionDevice(
212         kLegacyPartitionNameKernel, install_plan_.source_slot, "/dev/null");
213 
214     EXPECT_EQ(expect_success,
215               performer_.Write(payload_data.data(), payload_data.size()));
216     EXPECT_EQ(0, performer_.Close());
217 
218     brillo::Blob partition_data;
219     EXPECT_TRUE(utils::ReadFile(new_part, &partition_data));
220     return partition_data;
221   }
222 
223   // Calls delta performer's Write method by pretending to pass in bytes from a
224   // delta file whose metadata size is actual_metadata_size and tests if all
225   // checks are correctly performed if the install plan contains
226   // expected_metadata_size and that the result of the parsing are as per
227   // hash_checks_mandatory flag.
DoMetadataSizeTest(uint64_t expected_metadata_size,uint64_t actual_metadata_size,bool hash_checks_mandatory)228   void DoMetadataSizeTest(uint64_t expected_metadata_size,
229                           uint64_t actual_metadata_size,
230                           bool hash_checks_mandatory) {
231     install_plan_.hash_checks_mandatory = hash_checks_mandatory;
232 
233     // Set a valid magic string and version number 1.
234     EXPECT_TRUE(performer_.Write("CrAU", 4));
235     uint64_t version = htobe64(kChromeOSMajorPayloadVersion);
236     EXPECT_TRUE(performer_.Write(&version, 8));
237 
238     install_plan_.metadata_size = expected_metadata_size;
239     ErrorCode error_code;
240     // When filling in size in manifest, exclude the size of the 20-byte header.
241     uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
242     bool result = performer_.Write(&size_in_manifest, 8, &error_code);
243     if (expected_metadata_size == actual_metadata_size ||
244         !hash_checks_mandatory) {
245       EXPECT_TRUE(result);
246     } else {
247       EXPECT_FALSE(result);
248       EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
249     }
250 
251     EXPECT_LT(performer_.Close(), 0);
252   }
253 
254   // Generates a valid delta file but tests the delta performer by suppling
255   // different metadata signatures as per metadata_signature_test flag and
256   // 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)257   void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
258                                bool sign_payload,
259                                bool hash_checks_mandatory) {
260 
261     // Loads the payload and parses the manifest.
262     brillo::Blob payload = GeneratePayload(brillo::Blob(),
263         vector<AnnotatedOperation>(), sign_payload,
264         kChromeOSMajorPayloadVersion, kFullPayloadMinorVersion);
265 
266     LOG(INFO) << "Payload size: " << payload.size();
267 
268     install_plan_.hash_checks_mandatory = hash_checks_mandatory;
269 
270     DeltaPerformer::MetadataParseResult expected_result, actual_result;
271     ErrorCode expected_error, actual_error;
272 
273     // Fill up the metadata signature in install plan according to the test.
274     switch (metadata_signature_test) {
275       case kEmptyMetadataSignature:
276         install_plan_.metadata_signature.clear();
277         expected_result = DeltaPerformer::kMetadataParseError;
278         expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
279         break;
280 
281       case kInvalidMetadataSignature:
282         install_plan_.metadata_signature = kBogusMetadataSignature1;
283         expected_result = DeltaPerformer::kMetadataParseError;
284         expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
285         break;
286 
287       case kValidMetadataSignature:
288       default:
289         // Set the install plan's metadata size to be the same as the one
290         // in the manifest so that we pass the metadata size checks. Only
291         // then we can get to manifest signature checks.
292         ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
293             payload.data(),
294             install_plan_.metadata_size,
295             kUnittestPrivateKeyPath,
296             &install_plan_.metadata_signature));
297         EXPECT_FALSE(install_plan_.metadata_signature.empty());
298         expected_result = DeltaPerformer::kMetadataParseSuccess;
299         expected_error = ErrorCode::kSuccess;
300         break;
301     }
302 
303     // Ignore the expected result/error if hash checks are not mandatory.
304     if (!hash_checks_mandatory) {
305       expected_result = DeltaPerformer::kMetadataParseSuccess;
306       expected_error = ErrorCode::kSuccess;
307     }
308 
309     // Use the public key corresponding to the private key used above to
310     // sign the metadata.
311     EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
312     performer_.set_public_key_path(kUnittestPublicKeyPath);
313 
314     // Init actual_error with an invalid value so that we make sure
315     // ParsePayloadMetadata properly populates it in all cases.
316     actual_error = ErrorCode::kUmaReportedMax;
317     actual_result = performer_.ParsePayloadMetadata(payload, &actual_error);
318 
319     EXPECT_EQ(expected_result, actual_result);
320     EXPECT_EQ(expected_error, actual_error);
321 
322     // Check that the parsed metadata size is what's expected. This test
323     // implicitly confirms that the metadata signature is valid, if required.
324     EXPECT_EQ(install_plan_.metadata_size, performer_.GetMetadataSize());
325   }
326 
SetSupportedMajorVersion(uint64_t major_version)327   void SetSupportedMajorVersion(uint64_t major_version) {
328     performer_.supported_major_version_ = major_version;
329   }
330   FakePrefs prefs_;
331   InstallPlan install_plan_;
332   FakeBootControl fake_boot_control_;
333   FakeHardware fake_hardware_;
334   MockDownloadActionDelegate mock_delegate_;
335   DeltaPerformer performer_{
336       &prefs_, &fake_boot_control_, &fake_hardware_, &mock_delegate_, &install_plan_};
337 };
338 
TEST_F(DeltaPerformerTest,FullPayloadWriteTest)339 TEST_F(DeltaPerformerTest, FullPayloadWriteTest) {
340   install_plan_.payload_type = InstallPayloadType::kFull;
341   brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
342                                             std::end(kRandomString));
343   expected_data.resize(4096);  // block size
344   vector<AnnotatedOperation> aops;
345   AnnotatedOperation aop;
346   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
347   aop.op.set_data_offset(0);
348   aop.op.set_data_length(expected_data.size());
349   aop.op.set_type(InstallOperation::REPLACE);
350   aops.push_back(aop);
351 
352   brillo::Blob payload_data = GeneratePayload(expected_data, aops, false,
353       kChromeOSMajorPayloadVersion, kFullPayloadMinorVersion);
354 
355   EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
356 }
357 
TEST_F(DeltaPerformerTest,ShouldCancelTest)358 TEST_F(DeltaPerformerTest, ShouldCancelTest) {
359   install_plan_.payload_type = InstallPayloadType::kFull;
360   brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
361                                             std::end(kRandomString));
362   expected_data.resize(4096);  // block size
363   vector<AnnotatedOperation> aops;
364   AnnotatedOperation aop;
365   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
366   aop.op.set_data_offset(0);
367   aop.op.set_data_length(expected_data.size());
368   aop.op.set_type(InstallOperation::REPLACE);
369   aops.push_back(aop);
370 
371   brillo::Blob payload_data = GeneratePayload(expected_data, aops, false,
372       kChromeOSMajorPayloadVersion, kFullPayloadMinorVersion);
373 
374   testing::Mock::VerifyAndClearExpectations(&mock_delegate_);
375   EXPECT_CALL(mock_delegate_, ShouldCancel(_))
376       .WillOnce(
377           testing::DoAll(testing::SetArgumentPointee<0>(ErrorCode::kError),
378                          testing::Return(true)));
379 
380   ApplyPayload(payload_data, "/dev/null", false);
381 }
382 
TEST_F(DeltaPerformerTest,ReplaceOperationTest)383 TEST_F(DeltaPerformerTest, ReplaceOperationTest) {
384   brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
385                                             std::end(kRandomString));
386   expected_data.resize(4096);  // block size
387   vector<AnnotatedOperation> aops;
388   AnnotatedOperation aop;
389   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
390   aop.op.set_data_offset(0);
391   aop.op.set_data_length(expected_data.size());
392   aop.op.set_type(InstallOperation::REPLACE);
393   aops.push_back(aop);
394 
395   brillo::Blob payload_data = GeneratePayload(expected_data, aops, false);
396 
397   EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
398 }
399 
TEST_F(DeltaPerformerTest,ReplaceBzOperationTest)400 TEST_F(DeltaPerformerTest, ReplaceBzOperationTest) {
401   brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
402                                             std::end(kRandomString));
403   expected_data.resize(4096);  // block size
404   brillo::Blob bz_data;
405   EXPECT_TRUE(BzipCompress(expected_data, &bz_data));
406 
407   vector<AnnotatedOperation> aops;
408   AnnotatedOperation aop;
409   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
410   aop.op.set_data_offset(0);
411   aop.op.set_data_length(bz_data.size());
412   aop.op.set_type(InstallOperation::REPLACE_BZ);
413   aops.push_back(aop);
414 
415   brillo::Blob payload_data = GeneratePayload(bz_data, aops, false);
416 
417   EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
418 }
419 
TEST_F(DeltaPerformerTest,ReplaceXzOperationTest)420 TEST_F(DeltaPerformerTest, ReplaceXzOperationTest) {
421   brillo::Blob xz_data(std::begin(kXzCompressedData),
422                          std::end(kXzCompressedData));
423   // The compressed xz data contains only a single "a", but the operation should
424   // pad the rest of the two blocks with zeros.
425   brillo::Blob expected_data = brillo::Blob(4096, 0);
426   expected_data[0] = 'a';
427 
428   AnnotatedOperation aop;
429   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
430   aop.op.set_data_offset(0);
431   aop.op.set_data_length(xz_data.size());
432   aop.op.set_type(InstallOperation::REPLACE_XZ);
433   vector<AnnotatedOperation> aops = {aop};
434 
435   brillo::Blob payload_data = GeneratePayload(xz_data, aops, false);
436 
437   EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
438 }
439 
TEST_F(DeltaPerformerTest,ZeroOperationTest)440 TEST_F(DeltaPerformerTest, ZeroOperationTest) {
441   brillo::Blob existing_data = brillo::Blob(4096 * 10, 'a');
442   brillo::Blob expected_data = existing_data;
443   // Blocks 4, 5 and 7 should have zeros instead of 'a' after the operation is
444   // applied.
445   std::fill(expected_data.data() + 4096 * 4, expected_data.data() + 4096 * 6,
446             0);
447   std::fill(expected_data.data() + 4096 * 7, expected_data.data() + 4096 * 8,
448             0);
449 
450   AnnotatedOperation aop;
451   *(aop.op.add_dst_extents()) = ExtentForRange(4, 2);
452   *(aop.op.add_dst_extents()) = ExtentForRange(7, 1);
453   aop.op.set_type(InstallOperation::ZERO);
454   vector<AnnotatedOperation> aops = {aop};
455 
456   brillo::Blob payload_data = GeneratePayload(brillo::Blob(), aops, false);
457 
458   EXPECT_EQ(expected_data,
459             ApplyPayloadToData(payload_data, "/dev/null", existing_data, true));
460 }
461 
TEST_F(DeltaPerformerTest,SourceCopyOperationTest)462 TEST_F(DeltaPerformerTest, SourceCopyOperationTest) {
463   brillo::Blob expected_data(std::begin(kRandomString),
464                              std::end(kRandomString));
465   expected_data.resize(4096);  // block size
466   AnnotatedOperation aop;
467   *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
468   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
469   aop.op.set_type(InstallOperation::SOURCE_COPY);
470   brillo::Blob src_hash;
471   EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
472   aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
473 
474   brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
475 
476   string source_path;
477   EXPECT_TRUE(utils::MakeTempFile("Source-XXXXXX",
478                                   &source_path, nullptr));
479   ScopedPathUnlinker path_unlinker(source_path);
480   EXPECT_TRUE(utils::WriteFile(source_path.c_str(),
481                                expected_data.data(),
482                                expected_data.size()));
483 
484   EXPECT_EQ(expected_data, ApplyPayload(payload_data, source_path, true));
485 }
486 
TEST_F(DeltaPerformerTest,SourceHashMismatchTest)487 TEST_F(DeltaPerformerTest, SourceHashMismatchTest) {
488   brillo::Blob expected_data = {'f', 'o', 'o'};
489   brillo::Blob actual_data = {'b', 'a', 'r'};
490   expected_data.resize(4096);  // block size
491   actual_data.resize(4096);    // block size
492 
493   AnnotatedOperation aop;
494   *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
495   *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
496   aop.op.set_type(InstallOperation::SOURCE_COPY);
497   brillo::Blob src_hash;
498   EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
499   aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
500 
501   brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
502 
503   string source_path;
504   EXPECT_TRUE(utils::MakeTempFile("Source-XXXXXX", &source_path, nullptr));
505   ScopedPathUnlinker path_unlinker(source_path);
506   EXPECT_TRUE(utils::WriteFile(source_path.c_str(), actual_data.data(),
507                                actual_data.size()));
508 
509   EXPECT_EQ(actual_data, ApplyPayload(payload_data, source_path, false));
510 }
511 
TEST_F(DeltaPerformerTest,ExtentsToByteStringTest)512 TEST_F(DeltaPerformerTest, ExtentsToByteStringTest) {
513   uint64_t test[] = {1, 1, 4, 2, 0, 1};
514   static_assert(arraysize(test) % 2 == 0, "Array size uneven");
515   const uint64_t block_size = 4096;
516   const uint64_t file_length = 4 * block_size - 13;
517 
518   google::protobuf::RepeatedPtrField<Extent> extents;
519   for (size_t i = 0; i < arraysize(test); i += 2) {
520     *(extents.Add()) = ExtentForRange(test[i], test[i + 1]);
521   }
522 
523   string expected_output = "4096:4096,16384:8192,0:4083";
524   string actual_output;
525   EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
526                                                              block_size,
527                                                              file_length,
528                                                              &actual_output));
529   EXPECT_EQ(expected_output, actual_output);
530 }
531 
TEST_F(DeltaPerformerTest,ValidateManifestFullGoodTest)532 TEST_F(DeltaPerformerTest, ValidateManifestFullGoodTest) {
533   // The Manifest we are validating.
534   DeltaArchiveManifest manifest;
535   manifest.mutable_new_kernel_info();
536   manifest.mutable_new_rootfs_info();
537   manifest.set_minor_version(kFullPayloadMinorVersion);
538 
539   RunManifestValidation(manifest,
540                         kChromeOSMajorPayloadVersion,
541                         InstallPayloadType::kFull,
542                         ErrorCode::kSuccess);
543 }
544 
TEST_F(DeltaPerformerTest,ValidateManifestDeltaGoodTest)545 TEST_F(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
546   // The Manifest we are validating.
547   DeltaArchiveManifest manifest;
548   manifest.mutable_old_kernel_info();
549   manifest.mutable_old_rootfs_info();
550   manifest.mutable_new_kernel_info();
551   manifest.mutable_new_rootfs_info();
552   manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
553 
554   RunManifestValidation(manifest,
555                         kChromeOSMajorPayloadVersion,
556                         InstallPayloadType::kDelta,
557                         ErrorCode::kSuccess);
558 }
559 
TEST_F(DeltaPerformerTest,ValidateManifestFullUnsetMinorVersion)560 TEST_F(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
561   // The Manifest we are validating.
562   DeltaArchiveManifest manifest;
563 
564   RunManifestValidation(manifest,
565                         DeltaPerformer::kSupportedMajorPayloadVersion,
566                         InstallPayloadType::kFull,
567                         ErrorCode::kSuccess);
568 }
569 
TEST_F(DeltaPerformerTest,ValidateManifestDeltaUnsetMinorVersion)570 TEST_F(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
571   // The Manifest we are validating.
572   DeltaArchiveManifest manifest;
573   // Add an empty old_rootfs_info() to trick the DeltaPerformer into think that
574   // this is a delta payload manifest with a missing minor version.
575   manifest.mutable_old_rootfs_info();
576 
577   RunManifestValidation(manifest,
578                         DeltaPerformer::kSupportedMajorPayloadVersion,
579                         InstallPayloadType::kDelta,
580                         ErrorCode::kUnsupportedMinorPayloadVersion);
581 }
582 
TEST_F(DeltaPerformerTest,ValidateManifestFullOldKernelTest)583 TEST_F(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
584   // The Manifest we are validating.
585   DeltaArchiveManifest manifest;
586   manifest.mutable_old_kernel_info();
587   manifest.mutable_new_kernel_info();
588   manifest.mutable_new_rootfs_info();
589   manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
590 
591   RunManifestValidation(manifest,
592                         kChromeOSMajorPayloadVersion,
593                         InstallPayloadType::kFull,
594                         ErrorCode::kPayloadMismatchedType);
595 }
596 
TEST_F(DeltaPerformerTest,ValidateManifestFullOldRootfsTest)597 TEST_F(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
598   // The Manifest we are validating.
599   DeltaArchiveManifest manifest;
600   manifest.mutable_old_rootfs_info();
601   manifest.mutable_new_kernel_info();
602   manifest.mutable_new_rootfs_info();
603   manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
604 
605   RunManifestValidation(manifest,
606                         kChromeOSMajorPayloadVersion,
607                         InstallPayloadType::kFull,
608                         ErrorCode::kPayloadMismatchedType);
609 }
610 
TEST_F(DeltaPerformerTest,ValidateManifestFullPartitionUpdateTest)611 TEST_F(DeltaPerformerTest, ValidateManifestFullPartitionUpdateTest) {
612   // The Manifest we are validating.
613   DeltaArchiveManifest manifest;
614   PartitionUpdate* partition = manifest.add_partitions();
615   partition->mutable_old_partition_info();
616   partition->mutable_new_partition_info();
617   manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
618 
619   RunManifestValidation(manifest,
620                         kBrilloMajorPayloadVersion,
621                         InstallPayloadType::kFull,
622                         ErrorCode::kPayloadMismatchedType);
623 }
624 
TEST_F(DeltaPerformerTest,ValidateManifestBadMinorVersion)625 TEST_F(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
626   // The Manifest we are validating.
627   DeltaArchiveManifest manifest;
628 
629   // Generate a bad version number.
630   manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
631                              10000);
632   // Mark the manifest as a delta payload by setting old_rootfs_info.
633   manifest.mutable_old_rootfs_info();
634 
635   RunManifestValidation(manifest,
636                         DeltaPerformer::kSupportedMajorPayloadVersion,
637                         InstallPayloadType::kDelta,
638                         ErrorCode::kUnsupportedMinorPayloadVersion);
639 }
640 
TEST_F(DeltaPerformerTest,BrilloMetadataSignatureSizeTest)641 TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeTest) {
642   EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
643 
644   uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
645   EXPECT_TRUE(performer_.Write(&major_version, 8));
646 
647   uint64_t manifest_size = rand() % 256;
648   uint64_t manifest_size_be = htobe64(manifest_size);
649   EXPECT_TRUE(performer_.Write(&manifest_size_be, 8));
650 
651   uint32_t metadata_signature_size = rand() % 256;
652   uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
653   EXPECT_TRUE(performer_.Write(&metadata_signature_size_be, 4));
654 
655   EXPECT_LT(performer_.Close(), 0);
656 
657   EXPECT_TRUE(performer_.IsHeaderParsed());
658   EXPECT_EQ(kBrilloMajorPayloadVersion, performer_.GetMajorVersion());
659   uint64_t manifest_offset;
660   EXPECT_TRUE(performer_.GetManifestOffset(&manifest_offset));
661   EXPECT_EQ(24U, manifest_offset);  // 4 + 8 + 8 + 4
662   EXPECT_EQ(manifest_offset + manifest_size, performer_.GetMetadataSize());
663   EXPECT_EQ(metadata_signature_size, performer_.metadata_signature_size_);
664 }
665 
TEST_F(DeltaPerformerTest,BrilloVerifyMetadataSignatureTest)666 TEST_F(DeltaPerformerTest, BrilloVerifyMetadataSignatureTest) {
667   brillo::Blob payload_data = GeneratePayload({}, {}, true,
668                                               kBrilloMajorPayloadVersion,
669                                               kSourceMinorPayloadVersion);
670   install_plan_.hash_checks_mandatory = true;
671   // Just set these value so that we can use ValidateMetadataSignature directly.
672   performer_.major_payload_version_ = kBrilloMajorPayloadVersion;
673   performer_.metadata_size_ = install_plan_.metadata_size;
674   uint64_t signature_length;
675   EXPECT_TRUE(PayloadSigner::SignatureBlobLength({kUnittestPrivateKeyPath},
676                                                  &signature_length));
677   performer_.metadata_signature_size_ = signature_length;
678   performer_.set_public_key_path(kUnittestPublicKeyPath);
679   EXPECT_EQ(ErrorCode::kSuccess,
680             performer_.ValidateMetadataSignature(payload_data));
681 }
682 
TEST_F(DeltaPerformerTest,BadDeltaMagicTest)683 TEST_F(DeltaPerformerTest, BadDeltaMagicTest) {
684   EXPECT_TRUE(performer_.Write("junk", 4));
685   EXPECT_FALSE(performer_.Write("morejunk", 8));
686   EXPECT_LT(performer_.Close(), 0);
687 }
688 
TEST_F(DeltaPerformerTest,MissingMandatoryMetadataSizeTest)689 TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
690   DoMetadataSizeTest(0, 75456, true);
691 }
692 
TEST_F(DeltaPerformerTest,MissingNonMandatoryMetadataSizeTest)693 TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
694   DoMetadataSizeTest(0, 123456, false);
695 }
696 
TEST_F(DeltaPerformerTest,InvalidMandatoryMetadataSizeTest)697 TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
698   DoMetadataSizeTest(13000, 140000, true);
699 }
700 
TEST_F(DeltaPerformerTest,InvalidNonMandatoryMetadataSizeTest)701 TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
702   DoMetadataSizeTest(40000, 50000, false);
703 }
704 
TEST_F(DeltaPerformerTest,ValidMandatoryMetadataSizeTest)705 TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
706   DoMetadataSizeTest(85376, 85376, true);
707 }
708 
TEST_F(DeltaPerformerTest,MandatoryEmptyMetadataSignatureTest)709 TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) {
710   DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
711 }
712 
TEST_F(DeltaPerformerTest,NonMandatoryEmptyMetadataSignatureTest)713 TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) {
714   DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
715 }
716 
TEST_F(DeltaPerformerTest,MandatoryInvalidMetadataSignatureTest)717 TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) {
718   DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
719 }
720 
TEST_F(DeltaPerformerTest,NonMandatoryInvalidMetadataSignatureTest)721 TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) {
722   DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
723 }
724 
TEST_F(DeltaPerformerTest,MandatoryValidMetadataSignature1Test)725 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) {
726   DoMetadataSignatureTest(kValidMetadataSignature, false, true);
727 }
728 
TEST_F(DeltaPerformerTest,MandatoryValidMetadataSignature2Test)729 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) {
730   DoMetadataSignatureTest(kValidMetadataSignature, true, true);
731 }
732 
TEST_F(DeltaPerformerTest,NonMandatoryValidMetadataSignatureTest)733 TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) {
734   DoMetadataSignatureTest(kValidMetadataSignature, true, false);
735 }
736 
TEST_F(DeltaPerformerTest,UsePublicKeyFromResponse)737 TEST_F(DeltaPerformerTest, UsePublicKeyFromResponse) {
738   base::FilePath key_path;
739 
740   // The result of the GetPublicKeyResponse() method is based on three things
741   //
742   //  1. Whether it's an official build; and
743   //  2. Whether the Public RSA key to be used is in the root filesystem; and
744   //  3. Whether the response has a public key
745   //
746   // We test all eight combinations to ensure that we only use the
747   // public key in the response if
748   //
749   //  a. it's not an official build; and
750   //  b. there is no key in the root filesystem.
751 
752   string temp_dir;
753   EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
754                                        &temp_dir));
755   string non_existing_file = temp_dir + "/non-existing";
756   string existing_file = temp_dir + "/existing";
757   EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
758 
759   // Non-official build, non-existing public-key, key in response -> true
760   fake_hardware_.SetIsOfficialBuild(false);
761   performer_.public_key_path_ = non_existing_file;
762   install_plan_.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
763   EXPECT_TRUE(performer_.GetPublicKeyFromResponse(&key_path));
764   EXPECT_FALSE(key_path.empty());
765   EXPECT_EQ(unlink(key_path.value().c_str()), 0);
766   // Same with official build -> false
767   fake_hardware_.SetIsOfficialBuild(true);
768   EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
769 
770   // Non-official build, existing public-key, key in response -> false
771   fake_hardware_.SetIsOfficialBuild(false);
772   performer_.public_key_path_ = existing_file;
773   install_plan_.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
774   EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
775   // Same with official build -> false
776   fake_hardware_.SetIsOfficialBuild(true);
777   EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
778 
779   // Non-official build, non-existing public-key, no key in response -> false
780   fake_hardware_.SetIsOfficialBuild(false);
781   performer_.public_key_path_ = non_existing_file;
782   install_plan_.public_key_rsa = "";
783   EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
784   // Same with official build -> false
785   fake_hardware_.SetIsOfficialBuild(true);
786   EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
787 
788   // Non-official build, existing public-key, no key in response -> false
789   fake_hardware_.SetIsOfficialBuild(false);
790   performer_.public_key_path_ = existing_file;
791   install_plan_.public_key_rsa = "";
792   EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
793   // Same with official build -> false
794   fake_hardware_.SetIsOfficialBuild(true);
795   EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
796 
797   // Non-official build, non-existing public-key, key in response
798   // but invalid base64 -> false
799   fake_hardware_.SetIsOfficialBuild(false);
800   performer_.public_key_path_ = non_existing_file;
801   install_plan_.public_key_rsa = "not-valid-base64";
802   EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
803 
804   EXPECT_TRUE(base::DeleteFile(base::FilePath(temp_dir), true));
805 }
806 
TEST_F(DeltaPerformerTest,ConfVersionsMatch)807 TEST_F(DeltaPerformerTest, ConfVersionsMatch) {
808   // Test that the versions in update_engine.conf that is installed to the
809   // image match the supported delta versions in the update engine.
810   uint32_t minor_version;
811   brillo::KeyValueStore store;
812   EXPECT_TRUE(store.Load(base::FilePath("update_engine.conf")));
813   EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
814   EXPECT_EQ(DeltaPerformer::kSupportedMinorPayloadVersion, minor_version);
815 
816   string major_version_str;
817   uint64_t major_version;
818   EXPECT_TRUE(store.GetString("PAYLOAD_MAJOR_VERSION", &major_version_str));
819   EXPECT_TRUE(base::StringToUint64(major_version_str, &major_version));
820   EXPECT_EQ(DeltaPerformer::kSupportedMajorPayloadVersion, major_version);
821 }
822 
823 // Test that we recognize our own zlib compressor implementation as supported.
824 // All other equivalent implementations should be added to
825 // kCompatibleZlibFingerprint.
TEST_F(DeltaPerformerTest,ZlibFingerprintMatch)826 TEST_F(DeltaPerformerTest, ZlibFingerprintMatch) {
827   string fingerprint;
828   EXPECT_TRUE(base::ReadFileToString(base::FilePath(kZlibFingerprintPath),
829                                      &fingerprint));
830   EXPECT_TRUE(utils::IsZlibCompatible(fingerprint));
831 }
832 
833 }  // namespace chromeos_update_engine
834