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