• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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