Home | History | Annotate | Download | only in payload_consumer
      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:
     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.
    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 
    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 
    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.
    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.
    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.
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    689 TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
    690   DoMetadataSizeTest(0, 75456, true);
    691 }
    692 
    693 TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
    694   DoMetadataSizeTest(0, 123456, false);
    695 }
    696 
    697 TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
    698   DoMetadataSizeTest(13000, 140000, true);
    699 }
    700 
    701 TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
    702   DoMetadataSizeTest(40000, 50000, false);
    703 }
    704 
    705 TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
    706   DoMetadataSizeTest(85376, 85376, true);
    707 }
    708 
    709 TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) {
    710   DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
    711 }
    712 
    713 TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) {
    714   DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
    715 }
    716 
    717 TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) {
    718   DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
    719 }
    720 
    721 TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) {
    722   DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
    723 }
    724 
    725 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) {
    726   DoMetadataSignatureTest(kValidMetadataSignature, false, true);
    727 }
    728 
    729 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) {
    730   DoMetadataSignatureTest(kValidMetadataSignature, true, true);
    731 }
    732 
    733 TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) {
    734   DoMetadataSignatureTest(kValidMetadataSignature, true, false);
    735 }
    736 
    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 
    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.
    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