1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "update_engine/payload_consumer/delta_performer.h"
18
19 #include <endian.h>
20 #include <time.h>
21
22 #include <algorithm>
23 #include <map>
24 #include <memory>
25 #include <string>
26 #include <vector>
27
28 #include <base/files/file_path.h>
29 #include <base/files/file_util.h>
30 #include <base/files/scoped_temp_dir.h>
31 #include <base/stl_util.h>
32 #include <base/strings/string_number_conversions.h>
33 #include <base/strings/string_util.h>
34 #include <base/strings/stringprintf.h>
35 #include <brillo/secure_blob.h>
36 #include <gmock/gmock.h>
37 #include <google/protobuf/repeated_field.h>
38 #include <gtest/gtest.h>
39
40 #include "update_engine/common/constants.h"
41 #include "update_engine/common/error_code.h"
42 #include "update_engine/common/fake_boot_control.h"
43 #include "update_engine/common/fake_hardware.h"
44 #include "update_engine/common/fake_prefs.h"
45 #include "update_engine/common/hash_calculator.h"
46 #include "update_engine/common/mock_download_action.h"
47 #include "update_engine/common/test_utils.h"
48 #include "update_engine/common/testing_constants.h"
49 #include "update_engine/common/utils.h"
50 #include "update_engine/payload_consumer/mock_partition_writer.h"
51 #include "update_engine/payload_consumer/payload_constants.h"
52 #include "update_engine/payload_consumer/payload_metadata.h"
53 #include "update_engine/payload_generator/bzip.h"
54 #include "update_engine/payload_generator/extent_ranges.h"
55 #include "update_engine/payload_generator/payload_file.h"
56 #include "update_engine/payload_generator/payload_signer.h"
57 #include "update_engine/update_metadata.pb.h"
58
59 namespace chromeos_update_engine {
60
61 using std::string;
62 using std::vector;
63 using test_utils::GetBuildArtifactsPath;
64 using test_utils::kRandomString;
65 using testing::_;
66 using testing::Return;
67 using ::testing::Sequence;
68
69 namespace {
70
71 const char kBogusMetadataSignature1[] =
72 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
73 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
74 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
75 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
76 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
77 "pLRtClp97kN2+tXGNBQqkA==";
78
79 // Different options that determine what we should fill into the
80 // install_plan.metadata_signature to simulate the contents received in the
81 // Omaha response.
82 enum MetadataSignatureTest {
83 kEmptyMetadataSignature,
84 kInvalidMetadataSignature,
85 kValidMetadataSignature,
86 };
87
88 // Compressed data without checksum, generated with:
89 // echo -n "a$(head -c 4095 /dev/zero)" | xz -9 --check=none |
90 // hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
91 const uint8_t kXzCompressedData[] = {
92 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x00, 0xff, 0x12, 0xd9, 0x41,
93 0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc,
94 0xe0, 0x0f, 0xff, 0x00, 0x1b, 0x5d, 0x00, 0x30, 0x80, 0x33, 0xff, 0xdf,
95 0xff, 0x51, 0xd6, 0xaf, 0x90, 0x1c, 0x1b, 0x4c, 0xaa, 0x3d, 0x7b, 0x28,
96 0xe4, 0x7a, 0x74, 0xbc, 0xe5, 0xa7, 0x33, 0x4e, 0xcf, 0x00, 0x00, 0x00,
97 0x00, 0x01, 0x2f, 0x80, 0x20, 0x00, 0x00, 0x00, 0x92, 0x7c, 0x7b, 0x24,
98 0xa8, 0x00, 0x0a, 0xfc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x5a,
99 };
100
101 // clang-format off
102 const uint8_t src_deflates[] = {
103 /* raw 0 */ 0x11, 0x22,
104 /* deflate 2 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
105 /* raw 9 */ 0x33,
106 /* deflate 10 */ 0x03, 0x00,
107 /* raw 12 */
108 /* deflate 12 */ 0x63, 0x04, 0x00,
109 /* raw 15 */ 0x44, 0x55
110 };
111
112 const uint8_t dst_deflates[] = {
113 /* deflate 0 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
114 /* raw 7 */ 0x33, 0x66,
115 /* deflate 9 */ 0x01, 0x05, 0x00, 0xFA, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05,
116 /* deflate 19 */ 0x63, 0x04, 0x00
117 };
118 // clang-format on
119
120 // To generate this patch either:
121 // - Use puffin/src/patching_unittest.cc:TestPatching
122 // Or
123 // - Use the following approach:
124 // * Make src_deflate a string of hex with only spaces. (e.g. "0XTE 0xST")
125 // * echo "0XTE 0xST" | xxd -r -p > src.bin
126 // * Find the location of deflates in src_deflates (in bytes) in the format of
127 // "offset:length,...". (e.g. "2:7,10:2,12:3")
128 // * Do previous three steps for dst_deflates.
129 // * puffin --operation=puffdiff --src_file=src.bin --dst_file=dst.bin \
130 // --src_deflates_byte="2:7,10:2,12:3" --dst_deflates_byte="0:7,9:10,19:3" \
131 // --patch_file=patch.bin
132 // * hexdump -ve '" " 12/1 "0x%02x, " "\n"' patch.bin
133 const uint8_t puffdiff_patch[] = {
134 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x51, 0x08, 0x01, 0x12, 0x27,
135 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
136 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
137 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
138 0x38, 0x18, 0x1F, 0x1A, 0x24, 0x0A, 0x02, 0x10, 0x32, 0x0A, 0x04, 0x08,
139 0x48, 0x10, 0x50, 0x0A, 0x05, 0x08, 0x98, 0x01, 0x10, 0x12, 0x12, 0x02,
140 0x10, 0x58, 0x12, 0x04, 0x08, 0x70, 0x10, 0x58, 0x12, 0x05, 0x08, 0xC8,
141 0x01, 0x10, 0x38, 0x18, 0x21, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34,
142 0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x65,
145 0x29, 0x8C, 0x9B, 0x00, 0x00, 0x03, 0x60, 0x40, 0x7A, 0x0E, 0x08, 0x00,
146 0x40, 0x00, 0x20, 0x00, 0x21, 0x22, 0x9A, 0x3D, 0x4F, 0x50, 0x40, 0x0C,
147 0x3B, 0xC7, 0x9B, 0xB2, 0x21, 0x0E, 0xE9, 0x15, 0x98, 0x7A, 0x7C, 0x5D,
148 0xC9, 0x14, 0xE1, 0x42, 0x41, 0x94, 0xA6, 0x32, 0x6C, 0x42, 0x5A, 0x68,
149 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xF1, 0x20, 0x5F, 0x0D, 0x00,
150 0x00, 0x02, 0x41, 0x15, 0x42, 0x08, 0x20, 0x00, 0x40, 0x00, 0x00, 0x02,
151 0x40, 0x00, 0x20, 0x00, 0x22, 0x3D, 0x23, 0x10, 0x86, 0x03, 0x96, 0x54,
152 0x11, 0x16, 0x5F, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0xF1, 0x20, 0x5F,
153 0x0D, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x07,
154 0xD4, 0xCB, 0x6E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x00,
155 0x21, 0x18, 0x46, 0x82, 0xEE, 0x48, 0xA7, 0x0A, 0x12, 0x00, 0xFA, 0x99,
156 0x6D, 0xC0};
157
158 } // namespace
159
160 class DeltaPerformerTest : public ::testing::Test {
161 protected:
SetUp()162 void SetUp() override {
163 install_plan_.source_slot = 0;
164 install_plan_.target_slot = 1;
165 EXPECT_CALL(mock_delegate_, ShouldCancel(_))
166 .WillRepeatedly(testing::Return(false));
167 // Set the public key corresponding to the unittest private key.
168 string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath);
169 EXPECT_TRUE(utils::FileExists(public_key_path.c_str()));
170 performer_.set_public_key_path(public_key_path);
171 }
172
173 // Test helper placed where it can easily be friended from DeltaPerformer.
RunManifestValidation(const DeltaArchiveManifest & manifest,uint64_t major_version,InstallPayloadType payload_type,ErrorCode expected)174 void RunManifestValidation(const DeltaArchiveManifest& manifest,
175 uint64_t major_version,
176 InstallPayloadType payload_type,
177 ErrorCode expected) {
178 payload_.type = payload_type;
179
180 // The Manifest we are validating.
181 performer_.manifest_.CopyFrom(manifest);
182 performer_.major_payload_version_ = major_version;
183
184 EXPECT_EQ(expected, performer_.ValidateManifest());
185 }
186
GeneratePayload(const brillo::Blob & blob_data,const vector<AnnotatedOperation> & aops,bool sign_payload,PartitionConfig * old_part=nullptr)187 brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
188 const vector<AnnotatedOperation>& aops,
189 bool sign_payload,
190 PartitionConfig* old_part = nullptr) {
191 return GeneratePayload(blob_data,
192 aops,
193 sign_payload,
194 kMaxSupportedMajorPayloadVersion,
195 kMaxSupportedMinorPayloadVersion,
196 old_part);
197 }
198
GeneratePayload(const brillo::Blob & blob_data,const vector<AnnotatedOperation> & aops,bool sign_payload,uint64_t major_version,uint32_t minor_version,PartitionConfig * old_part=nullptr)199 brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
200 const vector<AnnotatedOperation>& aops,
201 bool sign_payload,
202 uint64_t major_version,
203 uint32_t minor_version,
204 PartitionConfig* old_part = nullptr) {
205 ScopedTempFile blob_file("Blob-XXXXXX");
206 EXPECT_TRUE(test_utils::WriteFileVector(blob_file.path(), blob_data));
207
208 PayloadGenerationConfig config;
209 config.version.major = major_version;
210 config.version.minor = minor_version;
211
212 PayloadFile payload;
213 EXPECT_TRUE(payload.Init(config));
214
215 std::unique_ptr<PartitionConfig> old_part_uptr;
216 if (!old_part) {
217 old_part_uptr = std::make_unique<PartitionConfig>(kPartitionNameRoot);
218 old_part = old_part_uptr.get();
219 }
220 if (minor_version != kFullPayloadMinorVersion) {
221 // When generating a delta payload we need to include the old partition
222 // information to mark it as a delta payload.
223 if (old_part->path.empty()) {
224 old_part->path = "/dev/null";
225 }
226 }
227 PartitionConfig new_part(kPartitionNameRoot);
228 new_part.path = "/dev/zero";
229 new_part.size = 1234;
230
231 payload.AddPartition(*old_part, new_part, aops, {}, {});
232
233 // We include a kernel partition without operations.
234 old_part->name = kPartitionNameKernel;
235 new_part.name = kPartitionNameKernel;
236 new_part.size = 0;
237
238 payload.AddPartition(*old_part, new_part, {}, {}, {});
239
240 ScopedTempFile payload_file("Payload-XXXXXX");
241 string private_key =
242 sign_payload ? GetBuildArtifactsPath(kUnittestPrivateKeyPath) : "";
243 EXPECT_TRUE(payload.WritePayload(payload_file.path(),
244 blob_file.path(),
245 private_key,
246 &payload_.metadata_size));
247
248 brillo::Blob payload_data;
249 EXPECT_TRUE(utils::ReadFile(payload_file.path(), &payload_data));
250 return payload_data;
251 }
252
GenerateSourceCopyPayload(const brillo::Blob & copied_data,bool add_hash,PartitionConfig * old_part=nullptr)253 brillo::Blob GenerateSourceCopyPayload(const brillo::Blob& copied_data,
254 bool add_hash,
255 PartitionConfig* old_part = nullptr) {
256 PayloadGenerationConfig config;
257 const uint64_t kDefaultBlockSize = config.block_size;
258 EXPECT_EQ(0U, copied_data.size() % kDefaultBlockSize);
259 uint64_t num_blocks = copied_data.size() / kDefaultBlockSize;
260 AnnotatedOperation aop;
261 *(aop.op.add_src_extents()) = ExtentForRange(0, num_blocks);
262 *(aop.op.add_dst_extents()) = ExtentForRange(0, num_blocks);
263 aop.op.set_type(InstallOperation::SOURCE_COPY);
264 brillo::Blob src_hash;
265 EXPECT_TRUE(HashCalculator::RawHashOfData(copied_data, &src_hash));
266 if (add_hash)
267 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
268
269 return GeneratePayload(brillo::Blob(), {aop}, false, old_part);
270 }
271
272 // Apply |payload_data| on partition specified in |source_path|.
273 // Expect result of performer_.Write() to be |expect_success|.
274 // Returns the result of the payload application.
ApplyPayload(const brillo::Blob & payload_data,const string & source_path,bool expect_success)275 brillo::Blob ApplyPayload(const brillo::Blob& payload_data,
276 const string& source_path,
277 bool expect_success) {
278 return ApplyPayloadToData(
279 &performer_, payload_data, source_path, brillo::Blob(), expect_success);
280 }
ApplyPayloadToData(const brillo::Blob & payload_data,const string & source_path,const brillo::Blob & target_data,bool expect_success)281 brillo::Blob ApplyPayloadToData(const brillo::Blob& payload_data,
282 const string& source_path,
283 const brillo::Blob& target_data,
284 bool expect_success) {
285 return ApplyPayloadToData(
286 &performer_, payload_data, source_path, target_data, expect_success);
287 }
288
289 // Apply the payload provided in |payload_data| reading from the |source_path|
290 // file and writing the contents to a new partition. The existing data in the
291 // new target file are set to |target_data| before applying the payload.
292 // Expect result of performer_.Write() to be |expect_success|.
293 // Returns the result of the payload application.
ApplyPayloadToData(DeltaPerformer * delta_performer,const brillo::Blob & payload_data,const string & source_path,const brillo::Blob & target_data,bool expect_success)294 brillo::Blob ApplyPayloadToData(DeltaPerformer* delta_performer,
295 const brillo::Blob& payload_data,
296 const string& source_path,
297 const brillo::Blob& target_data,
298 bool expect_success) {
299 ScopedTempFile new_part("Partition-XXXXXX");
300 EXPECT_TRUE(test_utils::WriteFileVector(new_part.path(), target_data));
301
302 payload_.size = payload_data.size();
303 // We installed the operations only in the rootfs partition, but the
304 // delta performer needs to access all the partitions.
305 fake_boot_control_.SetPartitionDevice(
306 kPartitionNameRoot, install_plan_.target_slot, new_part.path());
307 fake_boot_control_.SetPartitionDevice(
308 kPartitionNameRoot, install_plan_.source_slot, source_path);
309 fake_boot_control_.SetPartitionDevice(
310 kPartitionNameKernel, install_plan_.target_slot, "/dev/null");
311 fake_boot_control_.SetPartitionDevice(
312 kPartitionNameKernel, install_plan_.source_slot, "/dev/null");
313
314 EXPECT_EQ(expect_success,
315 delta_performer->Write(payload_data.data(), payload_data.size()));
316 EXPECT_EQ(0, performer_.Close());
317
318 brillo::Blob partition_data;
319 EXPECT_TRUE(utils::ReadFile(new_part.path(), &partition_data));
320 return partition_data;
321 }
322
323 // Calls delta performer's Write method by pretending to pass in bytes from a
324 // delta file whose metadata size is actual_metadata_size and tests if all
325 // checks are correctly performed if the install plan contains
326 // expected_metadata_size and that the result of the parsing are as per
327 // hash_checks_mandatory flag.
DoMetadataSizeTest(uint64_t expected_metadata_size,uint64_t actual_metadata_size,bool hash_checks_mandatory)328 void DoMetadataSizeTest(uint64_t expected_metadata_size,
329 uint64_t actual_metadata_size,
330 bool hash_checks_mandatory) {
331 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
332
333 // Set a valid magic string and version number 1.
334 EXPECT_TRUE(performer_.Write("CrAU", 4));
335 uint64_t version = htobe64(kBrilloMajorPayloadVersion);
336 EXPECT_TRUE(performer_.Write(&version, 8));
337
338 payload_.metadata_size = expected_metadata_size;
339 payload_.size = actual_metadata_size + 1;
340 ErrorCode error_code{};
341 // When filling in size in manifest, exclude the size of the 24-byte header.
342 uint64_t size_in_manifest = htobe64(actual_metadata_size - 24);
343 performer_.Write(&size_in_manifest, 8, &error_code);
344 auto signature_size = htobe64(10);
345 bool result = performer_.Write(&signature_size, 4, &error_code);
346 if (expected_metadata_size == actual_metadata_size ||
347 !hash_checks_mandatory) {
348 EXPECT_TRUE(result);
349 } else {
350 EXPECT_FALSE(result);
351 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
352 }
353
354 EXPECT_LT(performer_.Close(), 0);
355 }
356
357 // Generates a valid delta file but tests the delta performer by supplying
358 // different metadata signatures as per metadata_signature_test flag and
359 // sees if the result of the parsing are as per hash_checks_mandatory flag.
DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,bool sign_payload,bool hash_checks_mandatory)360 void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
361 bool sign_payload,
362 bool hash_checks_mandatory) {
363 // Loads the payload and parses the manifest.
364 brillo::Blob payload = GeneratePayload(brillo::Blob(),
365 vector<AnnotatedOperation>(),
366 sign_payload,
367 kBrilloMajorPayloadVersion,
368 kFullPayloadMinorVersion);
369
370 payload_.size = payload.size();
371 LOG(INFO) << "Payload size: " << payload.size();
372
373 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
374
375 MetadataParseResult expected_result{}, actual_result{};
376 ErrorCode expected_error{}, actual_error{};
377
378 // Fill up the metadata signature in install plan according to the test.
379 switch (metadata_signature_test) {
380 case kEmptyMetadataSignature:
381 payload_.metadata_signature.clear();
382 // We need to set the signature size in a signed payload to zero.
383 std::fill(
384 std::next(payload.begin(), 20), std::next(payload.begin(), 24), 0);
385 expected_result = MetadataParseResult::kError;
386 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
387 break;
388
389 case kInvalidMetadataSignature:
390 payload_.metadata_signature = kBogusMetadataSignature1;
391 expected_result = MetadataParseResult::kError;
392 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
393 break;
394
395 case kValidMetadataSignature:
396 default:
397 // Set the install plan's metadata size to be the same as the one
398 // in the manifest so that we pass the metadata size checks. Only
399 // then we can get to manifest signature checks.
400 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
401 payload.data(),
402 payload_.metadata_size,
403 GetBuildArtifactsPath(kUnittestPrivateKeyPath),
404 &payload_.metadata_signature));
405 EXPECT_FALSE(payload_.metadata_signature.empty());
406 expected_result = MetadataParseResult::kSuccess;
407 expected_error = ErrorCode::kSuccess;
408 break;
409 }
410
411 // Ignore the expected result/error if hash checks are not mandatory.
412 if (!hash_checks_mandatory) {
413 expected_result = MetadataParseResult::kSuccess;
414 expected_error = ErrorCode::kSuccess;
415 }
416
417 // Init actual_error with an invalid value so that we make sure
418 // ParsePayloadMetadata properly populates it in all cases.
419 actual_error = ErrorCode::kUmaReportedMax;
420 actual_result = performer_.ParsePayloadMetadata(payload, &actual_error);
421
422 EXPECT_EQ(expected_result, actual_result);
423 EXPECT_EQ(expected_error, actual_error);
424
425 // Check that the parsed metadata size is what's expected. This test
426 // implicitly confirms that the metadata signature is valid, if required.
427 EXPECT_EQ(payload_.metadata_size, performer_.metadata_size_);
428 }
429
430 FakePrefs prefs_;
431 InstallPlan install_plan_;
432 InstallPlan::Payload payload_;
433 FakeBootControl fake_boot_control_;
434 FakeHardware fake_hardware_;
435 MockDownloadActionDelegate mock_delegate_;
436 FileDescriptorPtr fake_ecc_fd_;
437 DeltaPerformer performer_{&prefs_,
438 &fake_boot_control_,
439 &fake_hardware_,
440 &mock_delegate_,
441 &install_plan_,
442 &payload_,
443 false /* interactive */,
444 "" /* Update certs path */};
445 };
446
TEST_F(DeltaPerformerTest,FullPayloadWriteTest)447 TEST_F(DeltaPerformerTest, FullPayloadWriteTest) {
448 payload_.type = InstallPayloadType::kFull;
449 brillo::Blob expected_data =
450 brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
451 expected_data.resize(4096); // block size
452 vector<AnnotatedOperation> aops;
453 AnnotatedOperation aop;
454 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
455 aop.op.set_data_offset(0);
456 aop.op.set_data_length(expected_data.size());
457 aop.op.set_type(InstallOperation::REPLACE);
458 aops.push_back(aop);
459
460 brillo::Blob payload_data = GeneratePayload(expected_data,
461 aops,
462 false,
463 kBrilloMajorPayloadVersion,
464 kFullPayloadMinorVersion);
465
466 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
467 }
468
TEST_F(DeltaPerformerTest,ShouldCancelTest)469 TEST_F(DeltaPerformerTest, ShouldCancelTest) {
470 payload_.type = InstallPayloadType::kFull;
471 brillo::Blob expected_data =
472 brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
473 expected_data.resize(4096); // block size
474 vector<AnnotatedOperation> aops;
475 AnnotatedOperation aop;
476 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
477 aop.op.set_data_offset(0);
478 aop.op.set_data_length(expected_data.size());
479 aop.op.set_type(InstallOperation::REPLACE);
480 aops.push_back(aop);
481
482 brillo::Blob payload_data = GeneratePayload(expected_data,
483 aops,
484 false,
485 kBrilloMajorPayloadVersion,
486 kFullPayloadMinorVersion);
487
488 testing::Mock::VerifyAndClearExpectations(&mock_delegate_);
489 EXPECT_CALL(mock_delegate_, ShouldCancel(_))
490 .WillOnce(testing::DoAll(testing::SetArgPointee<0>(ErrorCode::kError),
491 testing::Return(true)));
492
493 ApplyPayload(payload_data, "/dev/null", false);
494 }
495
TEST_F(DeltaPerformerTest,ReplaceOperationTest)496 TEST_F(DeltaPerformerTest, ReplaceOperationTest) {
497 brillo::Blob expected_data =
498 brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
499 expected_data.resize(4096); // block size
500 vector<AnnotatedOperation> aops;
501 AnnotatedOperation aop;
502 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
503 aop.op.set_data_offset(0);
504 aop.op.set_data_length(expected_data.size());
505 aop.op.set_type(InstallOperation::REPLACE);
506 aops.push_back(aop);
507
508 brillo::Blob payload_data = GeneratePayload(expected_data, aops, false);
509
510 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
511 }
512
TEST_F(DeltaPerformerTest,ReplaceBzOperationTest)513 TEST_F(DeltaPerformerTest, ReplaceBzOperationTest) {
514 brillo::Blob expected_data =
515 brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
516 expected_data.resize(4096); // block size
517 brillo::Blob bz_data;
518 EXPECT_TRUE(BzipCompress(expected_data, &bz_data));
519
520 vector<AnnotatedOperation> aops;
521 AnnotatedOperation aop;
522 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
523 aop.op.set_data_offset(0);
524 aop.op.set_data_length(bz_data.size());
525 aop.op.set_type(InstallOperation::REPLACE_BZ);
526 aops.push_back(aop);
527
528 brillo::Blob payload_data = GeneratePayload(bz_data, aops, false);
529
530 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
531 }
532
TEST_F(DeltaPerformerTest,ReplaceXzOperationTest)533 TEST_F(DeltaPerformerTest, ReplaceXzOperationTest) {
534 brillo::Blob xz_data(std::begin(kXzCompressedData),
535 std::end(kXzCompressedData));
536 // The compressed xz data contains a single "a" and padded with zero for the
537 // rest of the block.
538 brillo::Blob expected_data = brillo::Blob(4096, 0);
539 expected_data[0] = 'a';
540
541 AnnotatedOperation aop;
542 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
543 aop.op.set_data_offset(0);
544 aop.op.set_data_length(xz_data.size());
545 aop.op.set_type(InstallOperation::REPLACE_XZ);
546 vector<AnnotatedOperation> aops = {aop};
547
548 brillo::Blob payload_data = GeneratePayload(xz_data, aops, false);
549
550 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
551 }
552
TEST_F(DeltaPerformerTest,ZeroOperationTest)553 TEST_F(DeltaPerformerTest, ZeroOperationTest) {
554 brillo::Blob existing_data = brillo::Blob(4096 * 10, 'a');
555 brillo::Blob expected_data = existing_data;
556 // Blocks 4, 5 and 7 should have zeros instead of 'a' after the operation is
557 // applied.
558 std::fill(
559 expected_data.data() + 4096 * 4, expected_data.data() + 4096 * 6, 0);
560 std::fill(
561 expected_data.data() + 4096 * 7, expected_data.data() + 4096 * 8, 0);
562
563 AnnotatedOperation aop;
564 *(aop.op.add_dst_extents()) = ExtentForRange(4, 2);
565 *(aop.op.add_dst_extents()) = ExtentForRange(7, 1);
566 aop.op.set_type(InstallOperation::ZERO);
567 vector<AnnotatedOperation> aops = {aop};
568
569 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), aops, false);
570
571 EXPECT_EQ(expected_data,
572 ApplyPayloadToData(payload_data, "/dev/null", existing_data, true));
573 }
574
TEST_F(DeltaPerformerTest,SourceCopyOperationTest)575 TEST_F(DeltaPerformerTest, SourceCopyOperationTest) {
576 brillo::Blob expected_data(std::begin(kRandomString),
577 std::end(kRandomString));
578 expected_data.resize(4096); // block size
579 AnnotatedOperation aop;
580 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
581 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
582 aop.op.set_type(InstallOperation::SOURCE_COPY);
583 brillo::Blob src_hash;
584 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
585 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
586
587 ScopedTempFile source("Source-XXXXXX");
588 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
589
590 PartitionConfig old_part(kPartitionNameRoot);
591 old_part.path = source.path();
592 old_part.size = expected_data.size();
593
594 brillo::Blob payload_data =
595 GeneratePayload(brillo::Blob(), {aop}, false, &old_part);
596
597 EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
598 }
599
TEST_F(DeltaPerformerTest,PuffdiffOperationTest)600 TEST_F(DeltaPerformerTest, PuffdiffOperationTest) {
601 AnnotatedOperation aop;
602 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
603 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
604 brillo::Blob puffdiff_payload(std::begin(puffdiff_patch),
605 std::end(puffdiff_patch));
606 aop.op.set_data_offset(0);
607 aop.op.set_data_length(puffdiff_payload.size());
608 aop.op.set_type(InstallOperation::PUFFDIFF);
609 brillo::Blob src(std::begin(src_deflates), std::end(src_deflates));
610 src.resize(4096); // block size
611 brillo::Blob src_hash;
612 EXPECT_TRUE(HashCalculator::RawHashOfData(src, &src_hash));
613 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
614
615 ScopedTempFile source("Source-XXXXXX");
616 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), src));
617
618 PartitionConfig old_part(kPartitionNameRoot);
619 old_part.path = source.path();
620 old_part.size = src.size();
621
622 brillo::Blob payload_data =
623 GeneratePayload(puffdiff_payload, {aop}, false, &old_part);
624
625 brillo::Blob dst(std::begin(dst_deflates), std::end(dst_deflates));
626 EXPECT_EQ(dst, ApplyPayload(payload_data, source.path(), true));
627 }
628
TEST_F(DeltaPerformerTest,SourceHashMismatchTest)629 TEST_F(DeltaPerformerTest, SourceHashMismatchTest) {
630 brillo::Blob expected_data = {'f', 'o', 'o'};
631 brillo::Blob actual_data = {'b', 'a', 'r'};
632 expected_data.resize(4096); // block size
633 actual_data.resize(4096); // block size
634
635 AnnotatedOperation aop;
636 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
637 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
638 aop.op.set_type(InstallOperation::SOURCE_COPY);
639 brillo::Blob src_hash;
640 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
641 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
642
643 ScopedTempFile source("Source-XXXXXX");
644 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), actual_data));
645
646 PartitionConfig old_part(kPartitionNameRoot);
647 old_part.path = source.path();
648 old_part.size = actual_data.size();
649
650 brillo::Blob payload_data =
651 GeneratePayload(brillo::Blob(), {aop}, false, &old_part);
652
653 // When source hash mismatches, PartitionWriter will refuse to write anything.
654 // Therefore we should expect an empty blob.
655 EXPECT_EQ(brillo::Blob{}, ApplyPayload(payload_data, source.path(), false));
656 }
657
TEST_F(DeltaPerformerTest,ExtentsToByteStringTest)658 TEST_F(DeltaPerformerTest, ExtentsToByteStringTest) {
659 uint64_t test[] = {1, 1, 4, 2, 0, 1};
660 static_assert(base::size(test) % 2 == 0, "Array size uneven");
661 const uint64_t block_size = 4096;
662 const uint64_t file_length = 4 * block_size - 13;
663
664 google::protobuf::RepeatedPtrField<Extent> extents;
665 for (size_t i = 0; i < base::size(test); i += 2) {
666 *(extents.Add()) = ExtentForRange(test[i], test[i + 1]);
667 }
668
669 string expected_output = "4096:4096,16384:8192,0:4083";
670 string actual_output;
671 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(
672 extents, block_size, file_length, &actual_output));
673 EXPECT_EQ(expected_output, actual_output);
674 }
675
TEST_F(DeltaPerformerTest,ValidateManifestFullGoodTest)676 TEST_F(DeltaPerformerTest, ValidateManifestFullGoodTest) {
677 // The Manifest we are validating.
678 DeltaArchiveManifest manifest;
679 for (const auto& part_name : {"kernel", "rootfs"}) {
680 auto part = manifest.add_partitions();
681 part->set_partition_name(part_name);
682 part->mutable_new_partition_info();
683 }
684 manifest.set_minor_version(kFullPayloadMinorVersion);
685
686 RunManifestValidation(manifest,
687 kBrilloMajorPayloadVersion,
688 InstallPayloadType::kFull,
689 ErrorCode::kSuccess);
690 }
691
TEST_F(DeltaPerformerTest,ValidateManifestDeltaMaxGoodTest)692 TEST_F(DeltaPerformerTest, ValidateManifestDeltaMaxGoodTest) {
693 // The Manifest we are validating.
694 DeltaArchiveManifest manifest;
695 for (const auto& part_name : {"kernel", "rootfs"}) {
696 auto part = manifest.add_partitions();
697 part->set_partition_name(part_name);
698 part->mutable_old_partition_info();
699 part->mutable_new_partition_info();
700 }
701 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
702
703 RunManifestValidation(manifest,
704 kBrilloMajorPayloadVersion,
705 InstallPayloadType::kDelta,
706 ErrorCode::kSuccess);
707 }
708
TEST_F(DeltaPerformerTest,ValidateManifestDeltaMinGoodTest)709 TEST_F(DeltaPerformerTest, ValidateManifestDeltaMinGoodTest) {
710 // The Manifest we are validating.
711 DeltaArchiveManifest manifest;
712 for (const auto& part_name : {"kernel", "rootfs"}) {
713 auto part = manifest.add_partitions();
714 part->set_partition_name(part_name);
715 part->mutable_old_partition_info();
716 part->mutable_new_partition_info();
717 }
718 manifest.set_minor_version(kMinSupportedMinorPayloadVersion);
719
720 RunManifestValidation(manifest,
721 kBrilloMajorPayloadVersion,
722 InstallPayloadType::kDelta,
723 ErrorCode::kSuccess);
724 }
725
TEST_F(DeltaPerformerTest,ValidateManifestFullUnsetMinorVersion)726 TEST_F(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
727 // The Manifest we are validating.
728 DeltaArchiveManifest manifest;
729
730 RunManifestValidation(manifest,
731 kMaxSupportedMajorPayloadVersion,
732 InstallPayloadType::kFull,
733 ErrorCode::kSuccess);
734 }
735
TEST_F(DeltaPerformerTest,ValidateManifestDeltaUnsetMinorVersion)736 TEST_F(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
737 // The Manifest we are validating.
738 DeltaArchiveManifest manifest;
739 // Add an empty rootfs partition info to trick the DeltaPerformer into think
740 // that this is a delta payload manifest with a missing minor version.
741 auto rootfs = manifest.add_partitions();
742 rootfs->set_partition_name("rootfs");
743 rootfs->mutable_old_partition_info();
744
745 RunManifestValidation(manifest,
746 kMaxSupportedMajorPayloadVersion,
747 InstallPayloadType::kDelta,
748 ErrorCode::kUnsupportedMinorPayloadVersion);
749 }
750
TEST_F(DeltaPerformerTest,ValidateManifestFullOldKernelTest)751 TEST_F(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
752 // The Manifest we are validating.
753 DeltaArchiveManifest manifest;
754 for (const auto& part_name : {"kernel", "rootfs"}) {
755 auto part = manifest.add_partitions();
756 part->set_partition_name(part_name);
757 part->mutable_old_partition_info();
758 part->mutable_new_partition_info();
759 }
760 manifest.mutable_partitions(0)->clear_old_partition_info();
761 RunManifestValidation(manifest,
762 kBrilloMajorPayloadVersion,
763 InstallPayloadType::kFull,
764 ErrorCode::kPayloadMismatchedType);
765 }
766
TEST_F(DeltaPerformerTest,ValidateManifestFullPartitionUpdateTest)767 TEST_F(DeltaPerformerTest, ValidateManifestFullPartitionUpdateTest) {
768 // The Manifest we are validating.
769 DeltaArchiveManifest manifest;
770 PartitionUpdate* partition = manifest.add_partitions();
771 partition->mutable_old_partition_info();
772 partition->mutable_new_partition_info();
773 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
774
775 RunManifestValidation(manifest,
776 kBrilloMajorPayloadVersion,
777 InstallPayloadType::kFull,
778 ErrorCode::kPayloadMismatchedType);
779 }
780
TEST_F(DeltaPerformerTest,ValidateManifestBadMinorVersion)781 TEST_F(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
782 // The Manifest we are validating.
783 DeltaArchiveManifest manifest;
784
785 // Generate a bad version number.
786 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion + 10000);
787 // Mark the manifest as a delta payload by setting |old_partition_info|.
788 manifest.add_partitions()->mutable_old_partition_info();
789
790 RunManifestValidation(manifest,
791 kMaxSupportedMajorPayloadVersion,
792 InstallPayloadType::kDelta,
793 ErrorCode::kUnsupportedMinorPayloadVersion);
794 }
795
TEST_F(DeltaPerformerTest,ValidateManifestDowngrade)796 TEST_F(DeltaPerformerTest, ValidateManifestDowngrade) {
797 // The Manifest we are validating.
798 DeltaArchiveManifest manifest;
799
800 manifest.set_minor_version(kFullPayloadMinorVersion);
801 manifest.set_max_timestamp(1);
802 fake_hardware_.SetBuildTimestamp(2);
803
804 RunManifestValidation(manifest,
805 kMaxSupportedMajorPayloadVersion,
806 InstallPayloadType::kFull,
807 ErrorCode::kPayloadTimestampError);
808 }
809
TEST_F(DeltaPerformerTest,ValidatePerPartitionTimestampSuccess)810 TEST_F(DeltaPerformerTest, ValidatePerPartitionTimestampSuccess) {
811 // The Manifest we are validating.
812 DeltaArchiveManifest manifest;
813
814 manifest.set_minor_version(kFullPayloadMinorVersion);
815 manifest.set_max_timestamp(2);
816 fake_hardware_.SetBuildTimestamp(1);
817 auto& partition = *manifest.add_partitions();
818 partition.set_version("10");
819 partition.set_partition_name("system");
820 fake_hardware_.SetVersion("system", "5");
821
822 RunManifestValidation(manifest,
823 kMaxSupportedMajorPayloadVersion,
824 InstallPayloadType::kFull,
825 ErrorCode::kSuccess);
826 }
827
TEST_F(DeltaPerformerTest,BrilloMetadataSignatureSizeTest)828 TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeTest) {
829 unsigned int seed = time(nullptr);
830 EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
831
832 uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
833 EXPECT_TRUE(
834 performer_.Write(&major_version, PayloadMetadata::kDeltaVersionSize));
835
836 uint64_t manifest_size = rand_r(&seed) % 256;
837 uint32_t metadata_signature_size = rand_r(&seed) % 256;
838
839 // The payload size has to be bigger than the |metadata_size| and
840 // |metadata_signature_size|
841 payload_.size = PayloadMetadata::kDeltaManifestSizeOffset +
842 PayloadMetadata::kDeltaManifestSizeSize +
843 PayloadMetadata::kDeltaMetadataSignatureSizeSize +
844 manifest_size + metadata_signature_size + 1;
845
846 uint64_t manifest_size_be = htobe64(manifest_size);
847 EXPECT_TRUE(performer_.Write(&manifest_size_be,
848 PayloadMetadata::kDeltaManifestSizeSize));
849
850 uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
851 EXPECT_TRUE(
852 performer_.Write(&metadata_signature_size_be,
853 PayloadMetadata::kDeltaMetadataSignatureSizeSize));
854
855 EXPECT_LT(performer_.Close(), 0);
856
857 EXPECT_TRUE(performer_.IsHeaderParsed());
858 EXPECT_EQ(kBrilloMajorPayloadVersion, performer_.major_payload_version_);
859 EXPECT_EQ(24 + manifest_size, performer_.metadata_size_); // 4 + 8 + 8 + 4
860 EXPECT_EQ(metadata_signature_size, performer_.metadata_signature_size_);
861 }
862
TEST_F(DeltaPerformerTest,BrilloMetadataSizeNOKTest)863 TEST_F(DeltaPerformerTest, BrilloMetadataSizeNOKTest) {
864 unsigned int seed = time(nullptr);
865 EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
866
867 uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
868 EXPECT_TRUE(
869 performer_.Write(&major_version, PayloadMetadata::kDeltaVersionSize));
870
871 uint64_t manifest_size = UINT64_MAX - 600; // Subtract to avoid wrap around.
872 uint64_t manifest_offset = PayloadMetadata::kDeltaManifestSizeOffset +
873 PayloadMetadata::kDeltaManifestSizeSize +
874 PayloadMetadata::kDeltaMetadataSignatureSizeSize;
875 payload_.metadata_size = manifest_offset + manifest_size;
876 uint32_t metadata_signature_size = rand_r(&seed) % 256;
877
878 // The payload size is greater than the payload header but smaller than
879 // |metadata_signature_size| + |metadata_size|
880 payload_.size = manifest_offset + metadata_signature_size + 1;
881
882 uint64_t manifest_size_be = htobe64(manifest_size);
883 EXPECT_TRUE(performer_.Write(&manifest_size_be,
884 PayloadMetadata::kDeltaManifestSizeSize));
885 uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
886
887 ErrorCode error{};
888 EXPECT_FALSE(
889 performer_.Write(&metadata_signature_size_be,
890 PayloadMetadata::kDeltaMetadataSignatureSizeSize + 1,
891 &error));
892
893 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error);
894 }
895
TEST_F(DeltaPerformerTest,BrilloMetadataSignatureSizeNOKTest)896 TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeNOKTest) {
897 unsigned int seed = time(nullptr);
898 EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
899
900 uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
901 EXPECT_TRUE(
902 performer_.Write(&major_version, PayloadMetadata::kDeltaVersionSize));
903
904 uint64_t manifest_size = rand_r(&seed) % 256;
905 // Subtract from UINT32_MAX to avoid wrap around.
906 uint32_t metadata_signature_size = UINT32_MAX - 600;
907
908 // The payload size is greater than |manifest_size| but smaller than
909 // |metadata_signature_size|
910 payload_.size = manifest_size + 1;
911
912 uint64_t manifest_size_be = htobe64(manifest_size);
913 EXPECT_TRUE(performer_.Write(&manifest_size_be,
914 PayloadMetadata::kDeltaManifestSizeSize));
915
916 uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
917 ErrorCode error{};
918 EXPECT_FALSE(
919 performer_.Write(&metadata_signature_size_be,
920 PayloadMetadata::kDeltaMetadataSignatureSizeSize + 1,
921 &error));
922
923 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error);
924 }
925
TEST_F(DeltaPerformerTest,BrilloParsePayloadMetadataTest)926 TEST_F(DeltaPerformerTest, BrilloParsePayloadMetadataTest) {
927 brillo::Blob payload_data = GeneratePayload(
928 {}, {}, true, kBrilloMajorPayloadVersion, kSourceMinorPayloadVersion);
929 install_plan_.hash_checks_mandatory = true;
930 payload_.size = payload_data.size();
931 ErrorCode error{};
932 EXPECT_EQ(MetadataParseResult::kSuccess,
933 performer_.ParsePayloadMetadata(payload_data, &error));
934 EXPECT_EQ(ErrorCode::kSuccess, error);
935 }
936
TEST_F(DeltaPerformerTest,BadDeltaMagicTest)937 TEST_F(DeltaPerformerTest, BadDeltaMagicTest) {
938 EXPECT_TRUE(performer_.Write("junk", 4));
939 EXPECT_FALSE(performer_.Write("morejunk", 8));
940 EXPECT_LT(performer_.Close(), 0);
941 }
942
TEST_F(DeltaPerformerTest,MissingMandatoryMetadataSizeTest)943 TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
944 DoMetadataSizeTest(0, 75456, true);
945 }
946
TEST_F(DeltaPerformerTest,MissingNonMandatoryMetadataSizeTest)947 TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
948 DoMetadataSizeTest(0, 123456, false);
949 }
950
TEST_F(DeltaPerformerTest,InvalidMandatoryMetadataSizeTest)951 TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
952 DoMetadataSizeTest(13000, 140000, true);
953 }
954
TEST_F(DeltaPerformerTest,InvalidNonMandatoryMetadataSizeTest)955 TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
956 DoMetadataSizeTest(40000, 50000, false);
957 }
958
TEST_F(DeltaPerformerTest,ValidMandatoryMetadataSizeTest)959 TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
960 DoMetadataSizeTest(85376, 85376, true);
961 }
962
TEST_F(DeltaPerformerTest,MandatoryEmptyMetadataSignatureTest)963 TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) {
964 DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
965 }
966
TEST_F(DeltaPerformerTest,NonMandatoryEmptyMetadataSignatureTest)967 TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) {
968 DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
969 }
970
TEST_F(DeltaPerformerTest,MandatoryInvalidMetadataSignatureTest)971 TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) {
972 DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
973 }
974
TEST_F(DeltaPerformerTest,NonMandatoryInvalidMetadataSignatureTest)975 TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) {
976 DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
977 }
978
TEST_F(DeltaPerformerTest,MandatoryValidMetadataSignature1Test)979 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) {
980 DoMetadataSignatureTest(kValidMetadataSignature, false, true);
981 }
982
TEST_F(DeltaPerformerTest,MandatoryValidMetadataSignature2Test)983 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) {
984 DoMetadataSignatureTest(kValidMetadataSignature, true, true);
985 }
986
TEST_F(DeltaPerformerTest,NonMandatoryValidMetadataSignatureTest)987 TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) {
988 DoMetadataSignatureTest(kValidMetadataSignature, true, false);
989 }
990
TEST_F(DeltaPerformerTest,UsePublicKeyFromResponse)991 TEST_F(DeltaPerformerTest, UsePublicKeyFromResponse) {
992 // The result of the GetPublicKeyResponse() method is based on three things
993 //
994 // 1. Whether it's an official build; and
995 // 2. Whether the Public RSA key to be used is in the root filesystem; and
996 // 3. Whether the response has a public key
997 //
998 // We test all eight combinations to ensure that we only use the
999 // public key in the response if
1000 //
1001 // a. it's not an official build; and
1002 // b. there is no key in the root filesystem.
1003
1004 base::ScopedTempDir temp_dir;
1005 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1006 string non_existing_file = temp_dir.GetPath().Append("non-existing").value();
1007 string existing_file = temp_dir.GetPath().Append("existing").value();
1008 constexpr char kExistingKey[] = "Existing";
1009 ASSERT_TRUE(test_utils::WriteFileString(existing_file, kExistingKey));
1010
1011 // Non-official build, non-existing public-key, key in response ->
1012 // kResponseKey
1013 fake_hardware_.SetIsOfficialBuild(false);
1014 performer_.public_key_path_ = non_existing_file;
1015 // This is the result of 'echo -n "Response" | base64' and is not meant to be
1016 // a valid public key, but it is valid base-64.
1017 constexpr char kResponseKey[] = "Response";
1018 constexpr char kBase64ResponseKey[] = "UmVzcG9uc2U=";
1019 install_plan_.public_key_rsa = kBase64ResponseKey;
1020 string public_key;
1021 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1022 EXPECT_EQ(public_key, kResponseKey);
1023 // Same with official build -> no key
1024 fake_hardware_.SetIsOfficialBuild(true);
1025 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1026 EXPECT_TRUE(public_key.empty());
1027
1028 // Non-official build, existing public-key, key in response -> kExistingKey
1029 fake_hardware_.SetIsOfficialBuild(false);
1030 performer_.public_key_path_ = existing_file;
1031 install_plan_.public_key_rsa = kBase64ResponseKey;
1032 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1033 EXPECT_EQ(public_key, kExistingKey);
1034 // Same with official build -> kExistingKey
1035 fake_hardware_.SetIsOfficialBuild(true);
1036 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1037 EXPECT_EQ(public_key, kExistingKey);
1038
1039 // Non-official build, non-existing public-key, no key in response -> no key
1040 fake_hardware_.SetIsOfficialBuild(false);
1041 performer_.public_key_path_ = non_existing_file;
1042 install_plan_.public_key_rsa = "";
1043 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1044 EXPECT_TRUE(public_key.empty());
1045 // Same with official build -> no key
1046 fake_hardware_.SetIsOfficialBuild(true);
1047 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1048 EXPECT_TRUE(public_key.empty());
1049
1050 // Non-official build, existing public-key, no key in response -> kExistingKey
1051 fake_hardware_.SetIsOfficialBuild(false);
1052 performer_.public_key_path_ = existing_file;
1053 install_plan_.public_key_rsa = "";
1054 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1055 EXPECT_EQ(public_key, kExistingKey);
1056 // Same with official build -> kExistingKey
1057 fake_hardware_.SetIsOfficialBuild(true);
1058 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1059 EXPECT_EQ(public_key, kExistingKey);
1060
1061 // Non-official build, non-existing public-key, key in response
1062 // but invalid base64 -> false
1063 fake_hardware_.SetIsOfficialBuild(false);
1064 performer_.public_key_path_ = non_existing_file;
1065 install_plan_.public_key_rsa = "not-valid-base64";
1066 EXPECT_FALSE(performer_.GetPublicKey(&public_key));
1067 }
1068
1069 // TODO(197361113) re-enable the test after we bump the version in config.
TEST(DISABLED_ConfVersionTest,ConfVersionsMatch)1070 TEST(DISABLED_ConfVersionTest, ConfVersionsMatch) {
1071 // Test that the versions in update_engine.conf that is installed to the
1072 // image match the maximum supported delta versions in the update engine.
1073 uint32_t minor_version{};
1074 brillo::KeyValueStore store;
1075 EXPECT_TRUE(store.Load(GetBuildArtifactsPath().Append("update_engine.conf")));
1076 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
1077 EXPECT_EQ(kMaxSupportedMinorPayloadVersion, minor_version);
1078
1079 string major_version_str;
1080 uint64_t major_version{};
1081 EXPECT_TRUE(store.GetString("PAYLOAD_MAJOR_VERSION", &major_version_str));
1082 EXPECT_TRUE(base::StringToUint64(major_version_str, &major_version));
1083 EXPECT_EQ(kMaxSupportedMajorPayloadVersion, major_version);
1084 }
1085
TEST_F(DeltaPerformerTest,FullPayloadCanResumeTest)1086 TEST_F(DeltaPerformerTest, FullPayloadCanResumeTest) {
1087 payload_.type = InstallPayloadType::kFull;
1088 brillo::Blob expected_data =
1089 brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
1090 expected_data.resize(4096); // block size
1091 vector<AnnotatedOperation> aops;
1092 AnnotatedOperation aop;
1093 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
1094 aop.op.set_data_offset(0);
1095 aop.op.set_data_length(expected_data.size());
1096 aop.op.set_type(InstallOperation::REPLACE);
1097 aops.push_back(aop);
1098
1099 brillo::Blob payload_data = GeneratePayload(expected_data,
1100 aops,
1101 false,
1102 kBrilloMajorPayloadVersion,
1103 kFullPayloadMinorVersion);
1104
1105 ASSERT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
1106 performer_.CheckpointUpdateProgress(true);
1107 const std::string payload_id = "12345";
1108 prefs_.SetString(kPrefsUpdateCheckResponseHash, payload_id);
1109 ASSERT_TRUE(DeltaPerformer::CanResumeUpdate(&prefs_, payload_id));
1110 }
1111
1112 class TestDeltaPerformer : public DeltaPerformer {
1113 public:
1114 using DeltaPerformer::DeltaPerformer;
1115
CreatePartitionWriter(const PartitionUpdate & partition_update,const InstallPlan::Partition & install_part,DynamicPartitionControlInterface * dynamic_control,size_t block_size,bool is_interactive,bool is_dynamic_partition)1116 std::unique_ptr<PartitionWriterInterface> CreatePartitionWriter(
1117 const PartitionUpdate& partition_update,
1118 const InstallPlan::Partition& install_part,
1119 DynamicPartitionControlInterface* dynamic_control,
1120 size_t block_size,
1121 bool is_interactive,
1122 bool is_dynamic_partition) {
1123 LOG(INFO) << __FUNCTION__ << ": " << install_part.name;
1124 auto node = partition_writers_.extract(install_part.name);
1125 return std::move(node.mapped());
1126 }
1127
ShouldCheckpoint()1128 bool ShouldCheckpoint() override { return true; }
1129
1130 std::map<std::string, std::unique_ptr<MockPartitionWriter>>
1131 partition_writers_;
1132 };
1133
1134 namespace {
GetSourceCopyOp(uint32_t src_block,uint32_t dst_block,const void * data,size_t length)1135 AnnotatedOperation GetSourceCopyOp(uint32_t src_block,
1136 uint32_t dst_block,
1137 const void* data,
1138 size_t length) {
1139 AnnotatedOperation aop;
1140 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
1141 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
1142 aop.op.set_type(InstallOperation::SOURCE_COPY);
1143 brillo::Blob src_hash;
1144 HashCalculator::RawHashOfBytes(data, length, &src_hash);
1145 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
1146 return aop;
1147 }
1148 } // namespace
1149
TEST_F(DeltaPerformerTest,SetNextOpIndex)1150 TEST_F(DeltaPerformerTest, SetNextOpIndex) {
1151 TestDeltaPerformer delta_performer{&prefs_,
1152 &fake_boot_control_,
1153 &fake_hardware_,
1154 &mock_delegate_,
1155 &install_plan_,
1156 &payload_,
1157 false};
1158 brillo::Blob expected_data(std::begin(kRandomString),
1159 std::end(kRandomString));
1160 expected_data.resize(4096 * 2); // block size
1161 AnnotatedOperation aop;
1162
1163 ScopedTempFile source("Source-XXXXXX");
1164 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
1165
1166 PartitionConfig old_part(kPartitionNameRoot);
1167 old_part.path = source.path();
1168 old_part.size = expected_data.size();
1169
1170 delta_performer.partition_writers_[kPartitionNameRoot] =
1171 std::make_unique<MockPartitionWriter>();
1172 auto& writer1 = *delta_performer.partition_writers_[kPartitionNameRoot];
1173
1174 Sequence seq;
1175 std::vector<size_t> indices;
1176 EXPECT_CALL(writer1, CheckpointUpdateProgress(_))
1177 .WillRepeatedly(
1178 [&indices](size_t index) mutable { indices.emplace_back(index); });
1179 EXPECT_CALL(writer1, Init(_, true, _)).Times(1).WillOnce(Return(true));
1180 EXPECT_CALL(writer1, PerformSourceCopyOperation(_, _))
1181 .Times(2)
1182 .WillRepeatedly(Return(true));
1183
1184 brillo::Blob payload_data = GeneratePayload(
1185 brillo::Blob(),
1186 {GetSourceCopyOp(0, 0, expected_data.data(), 4096),
1187 GetSourceCopyOp(1, 1, expected_data.data() + 4096, 4096)},
1188 false,
1189 &old_part);
1190
1191 ApplyPayloadToData(&delta_performer, payload_data, source.path(), {}, true);
1192 ASSERT_TRUE(std::is_sorted(indices.begin(), indices.end()));
1193 ASSERT_GT(indices.size(), 0UL);
1194
1195 // Should be equal to number of operations
1196 ASSERT_EQ(indices[indices.size() - 1], 2UL);
1197 }
1198
1199 } // namespace chromeos_update_engine
1200