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