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