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