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