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 <inttypes.h> 20 #include <sys/mount.h> 21 22 #include <algorithm> 23 #include <string> 24 #include <vector> 25 26 #include <base/files/file_path.h> 27 #include <base/files/file_util.h> 28 #include <base/strings/string_util.h> 29 #include <base/strings/stringprintf.h> 30 #include <google/protobuf/repeated_field.h> 31 #include <gtest/gtest.h> 32 #include <openssl/pem.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/mock_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_consumer/payload_metadata.h" 43 #include "update_engine/payload_consumer/payload_verifier.h" 44 #include "update_engine/payload_generator/delta_diff_generator.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::GetBuildArtifactsPath; 53 using test_utils::kRandomString; 54 using test_utils::ScopedLoopMounter; 55 using test_utils::System; 56 using testing::_; 57 using testing::Return; 58 59 extern const char* kUnittestPrivateKeyPath; 60 extern const char* kUnittestPublicKeyPath; 61 extern const char* kUnittestPrivateKey2Path; 62 extern const char* kUnittestPublicKey2Path; 63 extern const char* kUnittestPrivateKeyECPath; 64 extern const char* kUnittestPublicKeyECPath; 65 66 static const uint32_t kDefaultKernelSize = 4096; // Something small for a test 67 // clang-format off 68 static const uint8_t kNewData[] = {'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 69 'n', 'e', 'w', ' ', 'd', 'a', 't', 'a', '.'}; 70 // clang-format on 71 72 namespace { 73 struct DeltaState { 74 string a_img; 75 string b_img; 76 string result_img; 77 size_t image_size; 78 79 string delta_path; 80 uint64_t metadata_size; 81 82 string old_kernel; 83 brillo::Blob old_kernel_data; 84 85 string new_kernel; 86 brillo::Blob new_kernel_data; 87 88 string result_kernel; 89 brillo::Blob result_kernel_data; 90 size_t kernel_size; 91 92 // The InstallPlan referenced by the DeltaPerformer. This needs to outlive 93 // the DeltaPerformer. 94 InstallPlan install_plan; 95 96 // The in-memory copy of delta file. 97 brillo::Blob delta; 98 99 // Mock and fake instances used by the delta performer. 100 FakeBootControl fake_boot_control_; 101 FakeHardware fake_hardware_; 102 MockDownloadActionDelegate mock_delegate_; 103 }; 104 105 enum SignatureTest { 106 kSignatureNone, // No payload signing. 107 kSignatureGenerator, // Sign the payload at generation time. 108 kSignatureGenerated, // Sign the payload after it's generated. 109 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real. 110 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder. 111 kSignatureGeneratedShell, // Sign the generated payload through shell cmds. 112 kSignatureGeneratedShellECKey, // Sign with a EC key through shell cmds. 113 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds. 114 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1 115 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2 116 }; 117 118 enum OperationHashTest { 119 kInvalidOperationData, 120 kValidOperationData, 121 }; 122 123 } // namespace 124 125 class DeltaPerformerIntegrationTest : public ::testing::Test {}; 126 127 static void CompareFilesByBlock(const string& a_file, 128 const string& b_file, 129 size_t image_size) { 130 EXPECT_EQ(0U, image_size % kBlockSize); 131 132 brillo::Blob a_data, b_data; 133 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file; 134 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file; 135 136 EXPECT_GE(a_data.size(), image_size); 137 EXPECT_GE(b_data.size(), image_size); 138 for (size_t i = 0; i < image_size; i += kBlockSize) { 139 EXPECT_EQ(0U, i % kBlockSize); 140 brillo::Blob a_sub(&a_data[i], &a_data[i + kBlockSize]); 141 brillo::Blob b_sub(&b_data[i], &b_data[i + kBlockSize]); 142 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i / kBlockSize) << " differs"; 143 } 144 if (::testing::Test::HasNonfatalFailure()) { 145 LOG(INFO) << "Compared filesystems with size " << image_size 146 << ", partition A " << a_file << " size: " << a_data.size() 147 << ", partition B " << b_file << " size: " << b_data.size(); 148 } 149 } 150 151 static bool WriteSparseFile(const string& path, off_t size) { 152 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644); 153 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); 154 ScopedFdCloser fd_closer(&fd); 155 off_t rc = lseek(fd, size + 1, SEEK_SET); 156 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1)); 157 int return_code = ftruncate(fd, size); 158 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0); 159 return true; 160 } 161 162 static bool WriteByteAtOffset(const string& path, off_t offset) { 163 int fd = open(path.c_str(), O_CREAT | O_WRONLY, 0644); 164 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); 165 ScopedFdCloser fd_closer(&fd); 166 EXPECT_TRUE(utils::PWriteAll(fd, "\0", 1, offset)); 167 return true; 168 } 169 170 static bool InsertSignaturePlaceholder(size_t signature_size, 171 const string& payload_path, 172 uint64_t* out_metadata_size) { 173 vector<brillo::Blob> signatures; 174 signatures.push_back(brillo::Blob(signature_size, 0)); 175 176 return PayloadSigner::AddSignatureToPayload(payload_path, 177 {signature_size}, 178 signatures, 179 {}, 180 payload_path, 181 out_metadata_size); 182 } 183 184 static void SignGeneratedPayload(const string& payload_path, 185 uint64_t* out_metadata_size) { 186 string private_key_path = GetBuildArtifactsPath(kUnittestPrivateKeyPath); 187 size_t signature_size; 188 ASSERT_TRUE(PayloadSigner::GetMaximumSignatureSize(private_key_path, 189 &signature_size)); 190 brillo::Blob hash; 191 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning( 192 payload_path, {signature_size}, &hash, nullptr)); 193 brillo::Blob signature; 194 ASSERT_TRUE(PayloadSigner::SignHash(hash, private_key_path, &signature)); 195 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(payload_path, 196 {signature_size}, 197 {signature}, 198 {}, 199 payload_path, 200 out_metadata_size)); 201 EXPECT_TRUE(PayloadSigner::VerifySignedPayload( 202 payload_path, GetBuildArtifactsPath(kUnittestPublicKeyPath))); 203 } 204 205 static void SignGeneratedShellPayloadWithKeys( 206 const string& payload_path, 207 const vector<string>& private_key_paths, 208 const string& public_key_path, 209 bool verification_success) { 210 vector<string> signature_size_strings; 211 for (const auto& key_path : private_key_paths) { 212 size_t signature_size; 213 ASSERT_TRUE( 214 PayloadSigner::GetMaximumSignatureSize(key_path, &signature_size)); 215 signature_size_strings.push_back(base::StringPrintf("%zu", signature_size)); 216 } 217 string signature_size_string = base::JoinString(signature_size_strings, ":"); 218 219 test_utils::ScopedTempFile hash_file("hash.XXXXXX"); 220 string delta_generator_path = GetBuildArtifactsPath("delta_generator"); 221 ASSERT_EQ(0, 222 System(base::StringPrintf( 223 "%s -in_file=%s -signature_size=%s -out_hash_file=%s", 224 delta_generator_path.c_str(), 225 payload_path.c_str(), 226 signature_size_string.c_str(), 227 hash_file.path().c_str()))); 228 229 // Sign the hash with all private keys. 230 vector<test_utils::ScopedTempFile> sig_files; 231 vector<string> sig_file_paths; 232 for (const auto& key_path : private_key_paths) { 233 brillo::Blob hash, signature; 234 ASSERT_TRUE(utils::ReadFile(hash_file.path(), &hash)); 235 ASSERT_TRUE(PayloadSigner::SignHash(hash, key_path, &signature)); 236 237 test_utils::ScopedTempFile sig_file("signature.XXXXXX"); 238 ASSERT_TRUE(test_utils::WriteFileVector(sig_file.path(), signature)); 239 sig_file_paths.push_back(sig_file.path()); 240 sig_files.push_back(std::move(sig_file)); 241 } 242 string sig_files_string = base::JoinString(sig_file_paths, ":"); 243 244 // Add the signature to the payload. 245 ASSERT_EQ(0, 246 System(base::StringPrintf("%s --signature_size=%s -in_file=%s " 247 "-payload_signature_file=%s -out_file=%s", 248 delta_generator_path.c_str(), 249 signature_size_string.c_str(), 250 payload_path.c_str(), 251 sig_files_string.c_str(), 252 payload_path.c_str()))); 253 254 int verify_result = System(base::StringPrintf("%s -in_file=%s -public_key=%s", 255 delta_generator_path.c_str(), 256 payload_path.c_str(), 257 public_key_path.c_str())); 258 259 if (verification_success) { 260 ASSERT_EQ(0, verify_result); 261 } else { 262 ASSERT_NE(0, verify_result); 263 } 264 } 265 266 static void SignGeneratedShellPayload(SignatureTest signature_test, 267 const string& payload_path) { 268 vector<SignatureTest> supported_test = { 269 kSignatureGeneratedShell, 270 kSignatureGeneratedShellBadKey, 271 kSignatureGeneratedShellECKey, 272 kSignatureGeneratedShellRotateCl1, 273 kSignatureGeneratedShellRotateCl2, 274 }; 275 ASSERT_TRUE(std::find(supported_test.begin(), 276 supported_test.end(), 277 signature_test) != supported_test.end()); 278 279 string private_key_path; 280 if (signature_test == kSignatureGeneratedShellBadKey) { 281 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX", &private_key_path, nullptr)); 282 } else if (signature_test == kSignatureGeneratedShellECKey) { 283 private_key_path = GetBuildArtifactsPath(kUnittestPrivateKeyECPath); 284 } else { 285 private_key_path = GetBuildArtifactsPath(kUnittestPrivateKeyPath); 286 } 287 ScopedPathUnlinker key_unlinker(private_key_path); 288 key_unlinker.set_should_remove(signature_test == 289 kSignatureGeneratedShellBadKey); 290 291 // Generates a new private key that will not match the public key. 292 if (signature_test == kSignatureGeneratedShellBadKey) { 293 LOG(INFO) << "Generating a mismatched private key."; 294 // The code below executes the equivalent of: 295 // openssl genrsa -out <private_key_path> 2048 296 RSA* rsa = RSA_new(); 297 BIGNUM* e = BN_new(); 298 EXPECT_EQ(1, BN_set_word(e, RSA_F4)); 299 EXPECT_EQ(1, RSA_generate_key_ex(rsa, 2048, e, nullptr)); 300 BN_free(e); 301 FILE* fprikey = fopen(private_key_path.c_str(), "w"); 302 EXPECT_NE(nullptr, fprikey); 303 EXPECT_EQ(1, 304 PEM_write_RSAPrivateKey( 305 fprikey, rsa, nullptr, nullptr, 0, nullptr, nullptr)); 306 fclose(fprikey); 307 RSA_free(rsa); 308 } 309 310 vector<string> private_key_paths = {private_key_path}; 311 if (signature_test == kSignatureGeneratedShellRotateCl1 || 312 signature_test == kSignatureGeneratedShellRotateCl2) { 313 private_key_paths.push_back( 314 GetBuildArtifactsPath(kUnittestPrivateKey2Path)); 315 } 316 317 std::string public_key; 318 if (signature_test == kSignatureGeneratedShellRotateCl2) { 319 public_key = GetBuildArtifactsPath(kUnittestPublicKey2Path); 320 } else if (signature_test == kSignatureGeneratedShellECKey) { 321 public_key = GetBuildArtifactsPath(kUnittestPublicKeyECPath); 322 } else { 323 public_key = GetBuildArtifactsPath(kUnittestPublicKeyPath); 324 } 325 326 bool verification_success = signature_test != kSignatureGeneratedShellBadKey; 327 SignGeneratedShellPayloadWithKeys( 328 payload_path, private_key_paths, public_key, verification_success); 329 } 330 331 static void GenerateDeltaFile(bool full_kernel, 332 bool full_rootfs, 333 bool noop, 334 ssize_t chunk_size, 335 SignatureTest signature_test, 336 DeltaState* state, 337 uint32_t minor_version) { 338 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr)); 339 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr)); 340 341 // result_img is used in minor version 2. Instead of applying the update 342 // in-place on A, we apply it to a new image, result_img. 343 EXPECT_TRUE( 344 utils::MakeTempFile("result_img.XXXXXX", &state->result_img, nullptr)); 345 346 EXPECT_TRUE( 347 base::CopyFile(GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"), 348 base::FilePath(state->a_img))); 349 350 state->image_size = utils::FileSize(state->a_img); 351 352 // Create ImageInfo A & B 353 ImageInfo old_image_info; 354 ImageInfo new_image_info; 355 356 if (!full_rootfs) { 357 old_image_info.set_channel("src-channel"); 358 old_image_info.set_board("src-board"); 359 old_image_info.set_version("src-version"); 360 old_image_info.set_key("src-key"); 361 old_image_info.set_build_channel("src-build-channel"); 362 old_image_info.set_build_version("src-build-version"); 363 } 364 365 new_image_info.set_channel("test-channel"); 366 new_image_info.set_board("test-board"); 367 new_image_info.set_version("test-version"); 368 new_image_info.set_key("test-key"); 369 new_image_info.set_build_channel("test-build-channel"); 370 new_image_info.set_build_version("test-build-version"); 371 372 // Make some changes to the A image. 373 { 374 string a_mnt; 375 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0); 376 377 brillo::Blob hardtocompress; 378 while (hardtocompress.size() < 3 * kBlockSize) { 379 hardtocompress.insert(hardtocompress.end(), 380 std::begin(kRandomString), 381 std::end(kRandomString)); 382 } 383 EXPECT_TRUE(utils::WriteFile( 384 base::StringPrintf("%s/hardtocompress", a_mnt.c_str()).c_str(), 385 hardtocompress.data(), 386 hardtocompress.size())); 387 388 brillo::Blob zeros(16 * 1024, 0); 389 EXPECT_EQ(static_cast<int>(zeros.size()), 390 base::WriteFile(base::FilePath(base::StringPrintf( 391 "%s/move-to-sparse", a_mnt.c_str())), 392 reinterpret_cast<const char*>(zeros.data()), 393 zeros.size())); 394 395 EXPECT_TRUE(WriteSparseFile( 396 base::StringPrintf("%s/move-from-sparse", a_mnt.c_str()), 16 * 1024)); 397 398 EXPECT_TRUE(WriteByteAtOffset( 399 base::StringPrintf("%s/move-semi-sparse", a_mnt.c_str()), 4096)); 400 401 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff 402 // patch fails to zero out the final block. 403 brillo::Blob ones(1024 * 1024, 0xff); 404 EXPECT_TRUE( 405 utils::WriteFile(base::StringPrintf("%s/ones", a_mnt.c_str()).c_str(), 406 ones.data(), 407 ones.size())); 408 } 409 410 if (noop) { 411 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img), 412 base::FilePath(state->b_img))); 413 old_image_info = new_image_info; 414 } else { 415 if (minor_version == kSourceMinorPayloadVersion) { 416 // Create a result image with image_size bytes of garbage. 417 brillo::Blob ones(state->image_size, 0xff); 418 EXPECT_TRUE(utils::WriteFile( 419 state->result_img.c_str(), ones.data(), ones.size())); 420 EXPECT_EQ(utils::FileSize(state->a_img), 421 utils::FileSize(state->result_img)); 422 } 423 424 EXPECT_TRUE( 425 base::CopyFile(GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"), 426 base::FilePath(state->b_img))); 427 428 // Make some changes to the B image. 429 string b_mnt; 430 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0); 431 base::FilePath mnt_path(b_mnt); 432 433 EXPECT_TRUE(base::CopyFile(mnt_path.Append("regular-small"), 434 mnt_path.Append("regular-small2"))); 435 EXPECT_TRUE(base::DeleteFile(mnt_path.Append("regular-small"), false)); 436 EXPECT_TRUE(base::Move(mnt_path.Append("regular-small2"), 437 mnt_path.Append("regular-small"))); 438 EXPECT_TRUE( 439 test_utils::WriteFileString(mnt_path.Append("foo").value(), "foo")); 440 EXPECT_EQ(0, base::WriteFile(mnt_path.Append("emptyfile"), "", 0)); 441 442 EXPECT_TRUE( 443 WriteSparseFile(mnt_path.Append("fullsparse").value(), 1024 * 1024)); 444 EXPECT_TRUE( 445 WriteSparseFile(mnt_path.Append("move-to-sparse").value(), 16 * 1024)); 446 447 brillo::Blob zeros(16 * 1024, 0); 448 EXPECT_EQ(static_cast<int>(zeros.size()), 449 base::WriteFile(mnt_path.Append("move-from-sparse"), 450 reinterpret_cast<const char*>(zeros.data()), 451 zeros.size())); 452 453 EXPECT_TRUE( 454 WriteByteAtOffset(mnt_path.Append("move-semi-sparse").value(), 4096)); 455 EXPECT_TRUE(WriteByteAtOffset(mnt_path.Append("partsparse").value(), 4096)); 456 457 EXPECT_TRUE( 458 base::CopyFile(mnt_path.Append("regular-16k"), mnt_path.Append("tmp"))); 459 EXPECT_TRUE(base::Move(mnt_path.Append("tmp"), 460 mnt_path.Append("link-hard-regular-16k"))); 461 462 EXPECT_TRUE(base::DeleteFile(mnt_path.Append("link-short_symlink"), false)); 463 EXPECT_TRUE(test_utils::WriteFileString( 464 mnt_path.Append("link-short_symlink").value(), "foobar")); 465 466 brillo::Blob hardtocompress; 467 while (hardtocompress.size() < 3 * kBlockSize) { 468 hardtocompress.insert(hardtocompress.end(), 469 std::begin(kRandomString), 470 std::end(kRandomString)); 471 } 472 EXPECT_TRUE(utils::WriteFile( 473 base::StringPrintf("%s/hardtocompress", b_mnt.c_str()).c_str(), 474 hardtocompress.data(), 475 hardtocompress.size())); 476 } 477 478 string old_kernel; 479 EXPECT_TRUE( 480 utils::MakeTempFile("old_kernel.XXXXXX", &state->old_kernel, nullptr)); 481 482 string new_kernel; 483 EXPECT_TRUE( 484 utils::MakeTempFile("new_kernel.XXXXXX", &state->new_kernel, nullptr)); 485 486 string result_kernel; 487 EXPECT_TRUE(utils::MakeTempFile( 488 "result_kernel.XXXXXX", &state->result_kernel, nullptr)); 489 490 state->kernel_size = kDefaultKernelSize; 491 state->old_kernel_data.resize(kDefaultKernelSize); 492 state->new_kernel_data.resize(state->old_kernel_data.size()); 493 state->result_kernel_data.resize(state->old_kernel_data.size()); 494 test_utils::FillWithData(&state->old_kernel_data); 495 test_utils::FillWithData(&state->new_kernel_data); 496 test_utils::FillWithData(&state->result_kernel_data); 497 498 // change the new kernel data 499 std::copy( 500 std::begin(kNewData), std::end(kNewData), state->new_kernel_data.begin()); 501 502 if (noop) { 503 state->old_kernel_data = state->new_kernel_data; 504 } 505 506 // Write kernels to disk 507 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(), 508 state->old_kernel_data.data(), 509 state->old_kernel_data.size())); 510 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(), 511 state->new_kernel_data.data(), 512 state->new_kernel_data.size())); 513 EXPECT_TRUE(utils::WriteFile(state->result_kernel.c_str(), 514 state->result_kernel_data.data(), 515 state->result_kernel_data.size())); 516 517 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX", &state->delta_path, nullptr)); 518 LOG(INFO) << "delta path: " << state->delta_path; 519 { 520 const string private_key = 521 signature_test == kSignatureGenerator 522 ? GetBuildArtifactsPath(kUnittestPrivateKeyPath) 523 : ""; 524 525 PayloadGenerationConfig payload_config; 526 payload_config.is_delta = !full_rootfs; 527 payload_config.hard_chunk_size = chunk_size; 528 payload_config.rootfs_partition_size = kRootFSPartitionSize; 529 payload_config.version.major = kChromeOSMajorPayloadVersion; 530 payload_config.version.minor = minor_version; 531 if (!full_rootfs) { 532 payload_config.source.partitions.emplace_back(kPartitionNameRoot); 533 payload_config.source.partitions.emplace_back(kPartitionNameKernel); 534 payload_config.source.partitions.front().path = state->a_img; 535 if (!full_kernel) 536 payload_config.source.partitions.back().path = state->old_kernel; 537 payload_config.source.image_info = old_image_info; 538 EXPECT_TRUE(payload_config.source.LoadImageSize()); 539 for (PartitionConfig& part : payload_config.source.partitions) 540 EXPECT_TRUE(part.OpenFilesystem()); 541 } else { 542 if (payload_config.hard_chunk_size == -1) 543 // Use 1 MiB chunk size for the full unittests. 544 payload_config.hard_chunk_size = 1024 * 1024; 545 } 546 payload_config.target.partitions.emplace_back(kPartitionNameRoot); 547 payload_config.target.partitions.back().path = state->b_img; 548 payload_config.target.partitions.emplace_back(kPartitionNameKernel); 549 payload_config.target.partitions.back().path = state->new_kernel; 550 payload_config.target.image_info = new_image_info; 551 EXPECT_TRUE(payload_config.target.LoadImageSize()); 552 for (PartitionConfig& part : payload_config.target.partitions) 553 EXPECT_TRUE(part.OpenFilesystem()); 554 555 EXPECT_TRUE(payload_config.Validate()); 556 EXPECT_TRUE(GenerateUpdatePayloadFile( 557 payload_config, state->delta_path, private_key, &state->metadata_size)); 558 } 559 // Extend the "partitions" holding the file system a bit. 560 EXPECT_EQ(0, 561 HANDLE_EINTR(truncate(state->a_img.c_str(), 562 state->image_size + 1024 * 1024))); 563 EXPECT_EQ(static_cast<off_t>(state->image_size + 1024 * 1024), 564 utils::FileSize(state->a_img)); 565 EXPECT_EQ(0, 566 HANDLE_EINTR(truncate(state->b_img.c_str(), 567 state->image_size + 1024 * 1024))); 568 EXPECT_EQ(static_cast<off_t>(state->image_size + 1024 * 1024), 569 utils::FileSize(state->b_img)); 570 571 if (signature_test == kSignatureGeneratedPlaceholder || 572 signature_test == kSignatureGeneratedPlaceholderMismatch) { 573 size_t signature_size; 574 ASSERT_TRUE(PayloadSigner::GetMaximumSignatureSize( 575 GetBuildArtifactsPath(kUnittestPrivateKeyPath), &signature_size)); 576 LOG(INFO) << "Inserting placeholder signature."; 577 ASSERT_TRUE(InsertSignaturePlaceholder( 578 signature_size, state->delta_path, &state->metadata_size)); 579 580 if (signature_test == kSignatureGeneratedPlaceholderMismatch) { 581 signature_size -= 1; 582 LOG(INFO) << "Inserting mismatched placeholder signature."; 583 ASSERT_FALSE(InsertSignaturePlaceholder( 584 signature_size, state->delta_path, &state->metadata_size)); 585 return; 586 } 587 } 588 589 if (signature_test == kSignatureGenerated || 590 signature_test == kSignatureGeneratedPlaceholder || 591 signature_test == kSignatureGeneratedPlaceholderMismatch) { 592 // Generate the signed payload and update the metadata size in state to 593 // reflect the new size after adding the signature operation to the 594 // manifest. 595 LOG(INFO) << "Signing payload."; 596 SignGeneratedPayload(state->delta_path, &state->metadata_size); 597 } else if (signature_test == kSignatureGeneratedShell || 598 signature_test == kSignatureGeneratedShellECKey || 599 signature_test == kSignatureGeneratedShellBadKey || 600 signature_test == kSignatureGeneratedShellRotateCl1 || 601 signature_test == kSignatureGeneratedShellRotateCl2) { 602 SignGeneratedShellPayload(signature_test, state->delta_path); 603 } 604 } 605 606 static void ApplyDeltaFile(bool full_kernel, 607 bool full_rootfs, 608 bool noop, 609 SignatureTest signature_test, 610 DeltaState* state, 611 bool hash_checks_mandatory, 612 OperationHashTest op_hash_test, 613 DeltaPerformer** performer, 614 uint32_t minor_version) { 615 // Check the metadata. 616 { 617 EXPECT_TRUE(utils::ReadFile(state->delta_path, &state->delta)); 618 PayloadMetadata payload_metadata; 619 EXPECT_TRUE(payload_metadata.ParsePayloadHeader(state->delta)); 620 state->metadata_size = payload_metadata.GetMetadataSize(); 621 LOG(INFO) << "Metadata size: " << state->metadata_size; 622 623 DeltaArchiveManifest manifest; 624 EXPECT_TRUE(payload_metadata.GetManifest(state->delta, &manifest)); 625 if (signature_test == kSignatureNone) { 626 EXPECT_FALSE(manifest.has_signatures_offset()); 627 EXPECT_FALSE(manifest.has_signatures_size()); 628 } else { 629 EXPECT_TRUE(manifest.has_signatures_offset()); 630 EXPECT_TRUE(manifest.has_signatures_size()); 631 Signatures sigs_message; 632 EXPECT_TRUE(sigs_message.ParseFromArray( 633 &state->delta[state->metadata_size + manifest.signatures_offset()], 634 manifest.signatures_size())); 635 if (signature_test == kSignatureGeneratedShellRotateCl1 || 636 signature_test == kSignatureGeneratedShellRotateCl2) 637 EXPECT_EQ(2, sigs_message.signatures_size()); 638 else 639 EXPECT_EQ(1, sigs_message.signatures_size()); 640 const Signatures::Signature& signature = sigs_message.signatures(0); 641 642 vector<string> key_paths{GetBuildArtifactsPath(kUnittestPrivateKeyPath)}; 643 if (signature_test == kSignatureGeneratedShellECKey) { 644 key_paths = {GetBuildArtifactsPath(kUnittestPrivateKeyECPath)}; 645 } else if (signature_test == kSignatureGeneratedShellRotateCl1 || 646 signature_test == kSignatureGeneratedShellRotateCl2) { 647 key_paths.push_back(GetBuildArtifactsPath(kUnittestPrivateKey2Path)); 648 } 649 uint64_t expected_sig_data_length = 0; 650 EXPECT_TRUE(PayloadSigner::SignatureBlobLength( 651 key_paths, &expected_sig_data_length)); 652 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size()); 653 EXPECT_FALSE(signature.data().empty()); 654 } 655 656 if (noop) { 657 EXPECT_EQ(0, manifest.install_operations_size()); 658 EXPECT_EQ(1, manifest.kernel_install_operations_size()); 659 } 660 661 if (full_kernel) { 662 EXPECT_FALSE(manifest.has_old_kernel_info()); 663 } else { 664 EXPECT_EQ(state->old_kernel_data.size(), 665 manifest.old_kernel_info().size()); 666 EXPECT_FALSE(manifest.old_kernel_info().hash().empty()); 667 } 668 669 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel"); 670 EXPECT_EQ(manifest.new_image_info().board(), "test-board"); 671 EXPECT_EQ(manifest.new_image_info().version(), "test-version"); 672 EXPECT_EQ(manifest.new_image_info().key(), "test-key"); 673 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel"); 674 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version"); 675 676 if (!full_rootfs) { 677 if (noop) { 678 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel"); 679 EXPECT_EQ(manifest.old_image_info().board(), "test-board"); 680 EXPECT_EQ(manifest.old_image_info().version(), "test-version"); 681 EXPECT_EQ(manifest.old_image_info().key(), "test-key"); 682 EXPECT_EQ(manifest.old_image_info().build_channel(), 683 "test-build-channel"); 684 EXPECT_EQ(manifest.old_image_info().build_version(), 685 "test-build-version"); 686 } else { 687 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel"); 688 EXPECT_EQ(manifest.old_image_info().board(), "src-board"); 689 EXPECT_EQ(manifest.old_image_info().version(), "src-version"); 690 EXPECT_EQ(manifest.old_image_info().key(), "src-key"); 691 EXPECT_EQ(manifest.old_image_info().build_channel(), 692 "src-build-channel"); 693 EXPECT_EQ(manifest.old_image_info().build_version(), 694 "src-build-version"); 695 } 696 } 697 698 if (full_rootfs) { 699 EXPECT_FALSE(manifest.has_old_rootfs_info()); 700 EXPECT_FALSE(manifest.has_old_image_info()); 701 EXPECT_TRUE(manifest.has_new_image_info()); 702 } else { 703 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size()); 704 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty()); 705 } 706 707 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size()); 708 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size()); 709 710 EXPECT_FALSE(manifest.new_kernel_info().hash().empty()); 711 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty()); 712 } 713 714 MockPrefs prefs; 715 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize, state->metadata_size)) 716 .WillOnce(Return(true)); 717 EXPECT_CALL(prefs, SetInt64(kPrefsManifestSignatureSize, 0)) 718 .WillOnce(Return(true)); 719 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _)) 720 .WillRepeatedly(Return(true)); 721 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _)) 722 .WillOnce(Return(false)); 723 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _)) 724 .WillRepeatedly(Return(true)); 725 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _)) 726 .WillRepeatedly(Return(true)); 727 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _)) 728 .WillRepeatedly(Return(true)); 729 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _)) 730 .WillRepeatedly(Return(true)); 731 EXPECT_CALL(prefs, SetString(kPrefsDynamicPartitionMetadataUpdated, _)) 732 .WillRepeatedly(Return(true)); 733 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) { 734 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _)) 735 .WillOnce(Return(true)); 736 } 737 738 EXPECT_CALL(state->mock_delegate_, ShouldCancel(_)) 739 .WillRepeatedly(Return(false)); 740 741 // Update the A image in place. 742 InstallPlan* install_plan = &state->install_plan; 743 install_plan->hash_checks_mandatory = hash_checks_mandatory; 744 install_plan->payloads = {{.metadata_size = state->metadata_size, 745 .type = (full_kernel && full_rootfs) 746 ? InstallPayloadType::kFull 747 : InstallPayloadType::kDelta}}; 748 install_plan->source_slot = 0; 749 install_plan->target_slot = 1; 750 751 InstallPlan::Partition root_part; 752 root_part.name = kPartitionNameRoot; 753 754 InstallPlan::Partition kernel_part; 755 kernel_part.name = kPartitionNameKernel; 756 757 LOG(INFO) << "Setting payload metadata size in Omaha = " 758 << state->metadata_size; 759 ASSERT_TRUE(PayloadSigner::GetMetadataSignature( 760 state->delta.data(), 761 state->metadata_size, 762 (signature_test == kSignatureGeneratedShellECKey) 763 ? GetBuildArtifactsPath(kUnittestPrivateKeyECPath) 764 : GetBuildArtifactsPath(kUnittestPrivateKeyPath), 765 &install_plan->payloads[0].metadata_signature)); 766 EXPECT_FALSE(install_plan->payloads[0].metadata_signature.empty()); 767 768 *performer = new DeltaPerformer(&prefs, 769 &state->fake_boot_control_, 770 &state->fake_hardware_, 771 &state->mock_delegate_, 772 install_plan, 773 &install_plan->payloads[0], 774 false /* interactive */); 775 string public_key_path = signature_test == kSignatureGeneratedShellECKey 776 ? GetBuildArtifactsPath(kUnittestPublicKeyECPath) 777 : GetBuildArtifactsPath(kUnittestPublicKeyPath); 778 EXPECT_TRUE(utils::FileExists(public_key_path.c_str())); 779 (*performer)->set_public_key_path(public_key_path); 780 (*performer)->set_update_certificates_path(""); 781 782 EXPECT_EQ(static_cast<off_t>(state->image_size), 783 HashCalculator::RawHashOfFile( 784 state->a_img, state->image_size, &root_part.source_hash)); 785 EXPECT_TRUE(HashCalculator::RawHashOfData(state->old_kernel_data, 786 &kernel_part.source_hash)); 787 788 // The partitions should be empty before DeltaPerformer. 789 install_plan->partitions.clear(); 790 791 // With minor version 2, we want the target to be the new image, result_img, 792 // but with version 1, we want to update A in place. 793 string target_root, target_kernel; 794 if (minor_version == kSourceMinorPayloadVersion) { 795 target_root = state->result_img; 796 target_kernel = state->result_kernel; 797 } else { 798 target_root = state->a_img; 799 target_kernel = state->old_kernel; 800 } 801 802 state->fake_boot_control_.SetPartitionDevice( 803 kPartitionNameRoot, install_plan->source_slot, state->a_img); 804 state->fake_boot_control_.SetPartitionDevice( 805 kPartitionNameKernel, install_plan->source_slot, state->old_kernel); 806 state->fake_boot_control_.SetPartitionDevice( 807 kPartitionNameRoot, install_plan->target_slot, target_root); 808 state->fake_boot_control_.SetPartitionDevice( 809 kPartitionNameKernel, install_plan->target_slot, target_kernel); 810 811 ErrorCode expected_error, actual_error; 812 bool continue_writing; 813 switch (op_hash_test) { 814 case kInvalidOperationData: { 815 // Muck with some random offset post the metadata size so that 816 // some operation hash will result in a mismatch. 817 int some_offset = state->metadata_size + 300; 818 LOG(INFO) << "Tampered value at offset: " << some_offset; 819 state->delta[some_offset]++; 820 expected_error = ErrorCode::kDownloadOperationHashMismatch; 821 continue_writing = false; 822 break; 823 } 824 825 case kValidOperationData: 826 default: 827 // no change. 828 expected_error = ErrorCode::kSuccess; 829 continue_writing = true; 830 break; 831 } 832 833 // Write at some number of bytes per operation. Arbitrarily chose 5. 834 const size_t kBytesPerWrite = 5; 835 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) { 836 size_t count = std::min(state->delta.size() - i, kBytesPerWrite); 837 bool write_succeeded = 838 ((*performer)->Write(&state->delta[i], count, &actual_error)); 839 // Normally write_succeeded should be true every time and 840 // actual_error should be ErrorCode::kSuccess. If so, continue the loop. 841 // But if we seeded an operation hash error above, then write_succeeded 842 // will be false. The failure may happen at any operation n. So, all 843 // Writes until n-1 should succeed and the nth operation will fail with 844 // actual_error. In this case, we should bail out of the loop because 845 // we cannot proceed applying the delta. 846 if (!write_succeeded) { 847 LOG(INFO) << "Write failed. Checking if it failed with expected error"; 848 EXPECT_EQ(expected_error, actual_error); 849 if (!continue_writing) { 850 LOG(INFO) << "Cannot continue writing. Bailing out."; 851 break; 852 } 853 } 854 855 EXPECT_EQ(ErrorCode::kSuccess, actual_error); 856 } 857 858 // If we had continued all the way through, Close should succeed. 859 // Otherwise, it should fail. Check appropriately. 860 bool close_result = (*performer)->Close(); 861 if (continue_writing) 862 EXPECT_EQ(0, close_result); 863 else 864 EXPECT_LE(0, close_result); 865 } 866 867 void VerifyPayloadResult(DeltaPerformer* performer, 868 DeltaState* state, 869 ErrorCode expected_result, 870 uint32_t minor_version) { 871 if (!performer) { 872 EXPECT_TRUE(!"Skipping payload verification since performer is null."); 873 return; 874 } 875 876 LOG(INFO) << "Verifying payload for expected result " << expected_result; 877 brillo::Blob expected_hash; 878 HashCalculator::RawHashOfData(state->delta, &expected_hash); 879 EXPECT_EQ(expected_result, 880 performer->VerifyPayload(expected_hash, state->delta.size())); 881 LOG(INFO) << "Verified payload."; 882 883 if (expected_result != ErrorCode::kSuccess) { 884 // no need to verify new partition if VerifyPayload failed. 885 return; 886 } 887 888 brillo::Blob updated_kernel_partition; 889 if (minor_version == kSourceMinorPayloadVersion) { 890 CompareFilesByBlock( 891 state->result_kernel, state->new_kernel, state->kernel_size); 892 CompareFilesByBlock(state->result_img, state->b_img, state->image_size); 893 EXPECT_TRUE( 894 utils::ReadFile(state->result_kernel, &updated_kernel_partition)); 895 } else { 896 CompareFilesByBlock( 897 state->old_kernel, state->new_kernel, state->kernel_size); 898 CompareFilesByBlock(state->a_img, state->b_img, state->image_size); 899 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition)); 900 } 901 902 ASSERT_GE(updated_kernel_partition.size(), arraysize(kNewData)); 903 EXPECT_TRUE(std::equal(std::begin(kNewData), 904 std::end(kNewData), 905 updated_kernel_partition.begin())); 906 907 const auto& partitions = state->install_plan.partitions; 908 EXPECT_EQ(2U, partitions.size()); 909 EXPECT_EQ(kPartitionNameRoot, partitions[0].name); 910 EXPECT_EQ(kPartitionNameKernel, partitions[1].name); 911 912 EXPECT_EQ(kDefaultKernelSize, partitions[1].target_size); 913 brillo::Blob expected_new_kernel_hash; 914 EXPECT_TRUE(HashCalculator::RawHashOfData(state->new_kernel_data, 915 &expected_new_kernel_hash)); 916 EXPECT_EQ(expected_new_kernel_hash, partitions[1].target_hash); 917 918 EXPECT_EQ(state->image_size, partitions[0].target_size); 919 brillo::Blob expected_new_rootfs_hash; 920 EXPECT_EQ(static_cast<off_t>(state->image_size), 921 HashCalculator::RawHashOfFile( 922 state->b_img, state->image_size, &expected_new_rootfs_hash)); 923 EXPECT_EQ(expected_new_rootfs_hash, partitions[0].target_hash); 924 } 925 926 void VerifyPayload(DeltaPerformer* performer, 927 DeltaState* state, 928 SignatureTest signature_test, 929 uint32_t minor_version) { 930 ErrorCode expected_result = ErrorCode::kSuccess; 931 switch (signature_test) { 932 case kSignatureNone: 933 expected_result = ErrorCode::kSignedDeltaPayloadExpectedError; 934 break; 935 case kSignatureGeneratedShellBadKey: 936 expected_result = ErrorCode::kDownloadPayloadPubKeyVerificationError; 937 break; 938 default: 939 break; // appease gcc 940 } 941 942 VerifyPayloadResult(performer, state, expected_result, minor_version); 943 } 944 945 void DoSmallImageTest(bool full_kernel, 946 bool full_rootfs, 947 bool noop, 948 ssize_t chunk_size, 949 SignatureTest signature_test, 950 bool hash_checks_mandatory, 951 uint32_t minor_version) { 952 DeltaState state; 953 DeltaPerformer* performer = nullptr; 954 GenerateDeltaFile(full_kernel, 955 full_rootfs, 956 noop, 957 chunk_size, 958 signature_test, 959 &state, 960 minor_version); 961 962 ScopedPathUnlinker a_img_unlinker(state.a_img); 963 ScopedPathUnlinker b_img_unlinker(state.b_img); 964 ScopedPathUnlinker new_img_unlinker(state.result_img); 965 ScopedPathUnlinker delta_unlinker(state.delta_path); 966 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel); 967 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel); 968 ScopedPathUnlinker result_kernel_unlinker(state.result_kernel); 969 ApplyDeltaFile(full_kernel, 970 full_rootfs, 971 noop, 972 signature_test, 973 &state, 974 hash_checks_mandatory, 975 kValidOperationData, 976 &performer, 977 minor_version); 978 VerifyPayload(performer, &state, signature_test, minor_version); 979 delete performer; 980 } 981 982 void DoOperationHashMismatchTest(OperationHashTest op_hash_test, 983 bool hash_checks_mandatory) { 984 DeltaState state; 985 uint64_t minor_version = kFullPayloadMinorVersion; 986 GenerateDeltaFile( 987 true, true, false, -1, kSignatureGenerated, &state, minor_version); 988 ScopedPathUnlinker a_img_unlinker(state.a_img); 989 ScopedPathUnlinker b_img_unlinker(state.b_img); 990 ScopedPathUnlinker delta_unlinker(state.delta_path); 991 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel); 992 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel); 993 DeltaPerformer* performer = nullptr; 994 ApplyDeltaFile(true, 995 true, 996 false, 997 kSignatureGenerated, 998 &state, 999 hash_checks_mandatory, 1000 op_hash_test, 1001 &performer, 1002 minor_version); 1003 delete performer; 1004 } 1005 1006 TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageTest) { 1007 DoSmallImageTest(false, 1008 false, 1009 false, 1010 -1, 1011 kSignatureGenerator, 1012 false, 1013 kInPlaceMinorPayloadVersion); 1014 } 1015 1016 TEST(DeltaPerformerIntegrationTest, 1017 RunAsRootSmallImageSignaturePlaceholderTest) { 1018 DoSmallImageTest(false, 1019 false, 1020 false, 1021 -1, 1022 kSignatureGeneratedPlaceholder, 1023 false, 1024 kInPlaceMinorPayloadVersion); 1025 } 1026 1027 TEST(DeltaPerformerIntegrationTest, 1028 RunAsRootSmallImageSignaturePlaceholderMismatchTest) { 1029 DeltaState state; 1030 GenerateDeltaFile(false, 1031 false, 1032 false, 1033 -1, 1034 kSignatureGeneratedPlaceholderMismatch, 1035 &state, 1036 kInPlaceMinorPayloadVersion); 1037 } 1038 1039 TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageChunksTest) { 1040 DoSmallImageTest(false, 1041 false, 1042 false, 1043 kBlockSize, 1044 kSignatureGenerator, 1045 false, 1046 kInPlaceMinorPayloadVersion); 1047 } 1048 1049 TEST(DeltaPerformerIntegrationTest, RunAsRootFullKernelSmallImageTest) { 1050 DoSmallImageTest(true, 1051 false, 1052 false, 1053 -1, 1054 kSignatureGenerator, 1055 false, 1056 kInPlaceMinorPayloadVersion); 1057 } 1058 1059 TEST(DeltaPerformerIntegrationTest, RunAsRootFullSmallImageTest) { 1060 DoSmallImageTest(true, 1061 true, 1062 false, 1063 -1, 1064 kSignatureGenerator, 1065 true, 1066 kFullPayloadMinorVersion); 1067 } 1068 1069 TEST(DeltaPerformerIntegrationTest, RunAsRootNoopSmallImageTest) { 1070 DoSmallImageTest(false, 1071 false, 1072 true, 1073 -1, 1074 kSignatureGenerator, 1075 false, 1076 kInPlaceMinorPayloadVersion); 1077 } 1078 1079 TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageSignNoneTest) { 1080 DoSmallImageTest(false, 1081 false, 1082 false, 1083 -1, 1084 kSignatureNone, 1085 false, 1086 kInPlaceMinorPayloadVersion); 1087 } 1088 1089 TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageSignGeneratedTest) { 1090 DoSmallImageTest(false, 1091 false, 1092 false, 1093 -1, 1094 kSignatureGenerated, 1095 true, 1096 kInPlaceMinorPayloadVersion); 1097 } 1098 1099 TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageSignGeneratedShellTest) { 1100 DoSmallImageTest(false, 1101 false, 1102 false, 1103 -1, 1104 kSignatureGeneratedShell, 1105 false, 1106 kInPlaceMinorPayloadVersion); 1107 } 1108 1109 TEST(DeltaPerformerIntegrationTest, 1110 RunAsRootSmallImageSignGeneratedShellECKeyTest) { 1111 DoSmallImageTest(false, 1112 false, 1113 false, 1114 -1, 1115 kSignatureGeneratedShellECKey, 1116 false, 1117 kInPlaceMinorPayloadVersion); 1118 } 1119 1120 TEST(DeltaPerformerIntegrationTest, 1121 RunAsRootSmallImageSignGeneratedShellBadKeyTest) { 1122 DoSmallImageTest(false, 1123 false, 1124 false, 1125 -1, 1126 kSignatureGeneratedShellBadKey, 1127 false, 1128 kInPlaceMinorPayloadVersion); 1129 } 1130 1131 TEST(DeltaPerformerIntegrationTest, 1132 RunAsRootSmallImageSignGeneratedShellRotateCl1Test) { 1133 DoSmallImageTest(false, 1134 false, 1135 false, 1136 -1, 1137 kSignatureGeneratedShellRotateCl1, 1138 false, 1139 kInPlaceMinorPayloadVersion); 1140 } 1141 1142 TEST(DeltaPerformerIntegrationTest, 1143 RunAsRootSmallImageSignGeneratedShellRotateCl2Test) { 1144 DoSmallImageTest(false, 1145 false, 1146 false, 1147 -1, 1148 kSignatureGeneratedShellRotateCl2, 1149 false, 1150 kInPlaceMinorPayloadVersion); 1151 } 1152 1153 TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageSourceOpsTest) { 1154 DoSmallImageTest(false, 1155 false, 1156 false, 1157 -1, 1158 kSignatureGenerator, 1159 false, 1160 kSourceMinorPayloadVersion); 1161 } 1162 1163 TEST(DeltaPerformerIntegrationTest, 1164 RunAsRootMandatoryOperationHashMismatchTest) { 1165 DoOperationHashMismatchTest(kInvalidOperationData, true); 1166 } 1167 1168 } // namespace chromeos_update_engine 1169