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