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