blob: 61b58ed33bbb6ef8ea271d8e5f316c6aafb5b491 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
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//
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/payload_consumer/delta_performer.h"
Alex Deymo8427b4a2014-11-05 14:00:32 -080018
Alex Deymo80f70ff2016-02-10 16:08:11 -080019#include <endian.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070020#include <inttypes.h>
Eric Caruso4495bfe2018-01-23 16:34:20 -080021#include <time.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070022
Sen Jiang77ab7bd2018-05-22 17:24:23 -070023#include <memory>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070024#include <string>
25#include <vector>
26
Allie Wood78750a42015-02-11 15:42:11 -080027#include <base/files/file_path.h>
Ben Chan06c76a42014-09-05 08:21:06 -070028#include <base/files/file_util.h>
Sen Jiang371615b2016-04-13 15:54:29 -070029#include <base/files/scoped_temp_dir.h>
Alex Deymocbf09892015-09-11 16:13:16 -070030#include <base/strings/string_number_conversions.h>
Alex Deymof1cbe172015-03-05 15:58:37 -080031#include <base/strings/string_util.h>
Alex Deymo2d621a32015-10-01 11:09:01 -070032#include <base/strings/stringprintf.h>
Alex Deymo542c19b2015-12-03 07:43:31 -030033#include <gmock/gmock.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070034#include <google/protobuf/repeated_field.h>
35#include <gtest/gtest.h>
36
Alex Deymo39910dc2015-11-09 17:04:30 -080037#include "update_engine/common/constants.h"
Alex Deymo542c19b2015-12-03 07:43:31 -030038#include "update_engine/common/fake_boot_control.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080039#include "update_engine/common/fake_hardware.h"
40#include "update_engine/common/fake_prefs.h"
41#include "update_engine/common/test_utils.h"
42#include "update_engine/common/utils.h"
Alex Deymo51c264e2016-11-04 15:49:53 -070043#include "update_engine/payload_consumer/fake_file_descriptor.h"
Alex Deymo542c19b2015-12-03 07:43:31 -030044#include "update_engine/payload_consumer/mock_download_action.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080045#include "update_engine/payload_consumer/payload_constants.h"
Alex Deymo0bc26112015-10-19 20:54:57 -070046#include "update_engine/payload_generator/bzip.h"
Sen Jiang2d528b42015-09-25 11:18:12 -070047#include "update_engine/payload_generator/extent_ranges.h"
Sen Jiangd78b3892015-09-25 15:19:31 -070048#include "update_engine/payload_generator/payload_file.h"
Alex Deymo923d8fa2014-07-15 17:58:51 -070049#include "update_engine/payload_generator/payload_signer.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070050#include "update_engine/update_metadata.pb.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070051
52namespace chromeos_update_engine {
53
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070054using std::string;
55using std::vector;
Sen Jiang260f03b2016-03-21 15:34:58 -070056using test_utils::GetBuildArtifactsPath;
Alex Deymo2d621a32015-10-01 11:09:01 -070057using test_utils::kRandomString;
Amin Hassani008c4582019-01-13 16:22:47 -080058using test_utils::System;
Alex Deymo542c19b2015-12-03 07:43:31 -030059using testing::_;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070060
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070061extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070062extern const char* kUnittestPublicKeyPath;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070063
Sen Jiange0d04282016-03-01 14:22:52 -080064namespace {
65
66const char kBogusMetadataSignature1[] =
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -070067 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
68 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
69 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
70 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
71 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
72 "pLRtClp97kN2+tXGNBQqkA==";
Jay Srinivasan738fdf32012-12-07 17:40:54 -080073
Jay Srinivasan738fdf32012-12-07 17:40:54 -080074// Different options that determine what we should fill into the
75// install_plan.metadata_signature to simulate the contents received in the
76// Omaha response.
77enum MetadataSignatureTest {
78 kEmptyMetadataSignature,
79 kInvalidMetadataSignature,
80 kValidMetadataSignature,
81};
82
Alex Deymo2d621a32015-10-01 11:09:01 -070083// Compressed data without checksum, generated with:
Sen Jiang5e1af982018-11-01 15:01:45 -070084// echo -n "a$(head -c 4095 /dev/zero)" | xz -9 --check=none |
85// hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
Alex Deymo2d621a32015-10-01 11:09:01 -070086const uint8_t kXzCompressedData[] = {
87 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x00, 0xff, 0x12, 0xd9, 0x41,
88 0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc,
Sen Jiang5e1af982018-11-01 15:01:45 -070089 0xe0, 0x0f, 0xff, 0x00, 0x1b, 0x5d, 0x00, 0x30, 0x80, 0x33, 0xff, 0xdf,
90 0xff, 0x51, 0xd6, 0xaf, 0x90, 0x1c, 0x1b, 0x4c, 0xaa, 0x3d, 0x7b, 0x28,
91 0xe4, 0x7a, 0x74, 0xbc, 0xe5, 0xa7, 0x33, 0x4e, 0xcf, 0x00, 0x00, 0x00,
92 0x00, 0x01, 0x2f, 0x80, 0x20, 0x00, 0x00, 0x00, 0x92, 0x7c, 0x7b, 0x24,
93 0xa8, 0x00, 0x0a, 0xfc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x5a,
Alex Deymo2d621a32015-10-01 11:09:01 -070094};
95
Amin Hassani008c4582019-01-13 16:22:47 -080096// clang-format off
Amin Hassani02855c22017-09-06 22:34:50 -070097const uint8_t src_deflates[] = {
98 /* raw 0 */ 0x11, 0x22,
99 /* deflate 2 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
100 /* raw 9 */ 0x33,
101 /* deflate 10 */ 0x03, 0x00,
102 /* raw 12 */
103 /* deflate 12 */ 0x63, 0x04, 0x00,
104 /* raw 15 */ 0x44, 0x55
105};
106
107const uint8_t dst_deflates[] = {
108 /* deflate 0 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
109 /* raw 7 */ 0x33, 0x66,
110 /* deflate 9 */ 0x01, 0x05, 0x00, 0xFA, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05,
111 /* deflate 19 */ 0x63, 0x04, 0x00
112};
Amin Hassani008c4582019-01-13 16:22:47 -0800113// clang-format on
Amin Hassani02855c22017-09-06 22:34:50 -0700114
115// To generate this patch either:
116// - Use puffin/src/patching_unittest.cc:TestPatching
117// Or
118// - Use the following approach:
119// * Make src_deflate a string of hex with only spaces. (e.g. "0XTE 0xST")
120// * echo "0XTE 0xST" | xxd -r -p > src.bin
121// * Find the location of deflates in src_deflates (in bytes) in the format of
122// "offset:length,...". (e.g. "2:7,10:2,12:3")
123// * Do previous three steps for dst_deflates.
124// * puffin --operation=puffdiff --src_file=src.bin --dst_file=dst.bin \
125// --src_deflates_byte="2:7,10:2,12:3" --dst_deflates_byte="0:7,9:10,19:3" \
126// --patch_file=patch.bin
127// * hexdump -ve '" " 12/1 "0x%02x, " "\n"' patch.bin
128const uint8_t puffdiff_patch[] = {
Amin Hassani008c4582019-01-13 16:22:47 -0800129 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x51, 0x08, 0x01, 0x12, 0x27,
130 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
131 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
132 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
133 0x38, 0x18, 0x1F, 0x1A, 0x24, 0x0A, 0x02, 0x10, 0x32, 0x0A, 0x04, 0x08,
134 0x48, 0x10, 0x50, 0x0A, 0x05, 0x08, 0x98, 0x01, 0x10, 0x12, 0x12, 0x02,
135 0x10, 0x58, 0x12, 0x04, 0x08, 0x70, 0x10, 0x58, 0x12, 0x05, 0x08, 0xC8,
136 0x01, 0x10, 0x38, 0x18, 0x21, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34,
137 0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x65,
140 0x29, 0x8C, 0x9B, 0x00, 0x00, 0x03, 0x60, 0x40, 0x7A, 0x0E, 0x08, 0x00,
141 0x40, 0x00, 0x20, 0x00, 0x21, 0x22, 0x9A, 0x3D, 0x4F, 0x50, 0x40, 0x0C,
142 0x3B, 0xC7, 0x9B, 0xB2, 0x21, 0x0E, 0xE9, 0x15, 0x98, 0x7A, 0x7C, 0x5D,
143 0xC9, 0x14, 0xE1, 0x42, 0x41, 0x94, 0xA6, 0x32, 0x6C, 0x42, 0x5A, 0x68,
144 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xF1, 0x20, 0x5F, 0x0D, 0x00,
145 0x00, 0x02, 0x41, 0x15, 0x42, 0x08, 0x20, 0x00, 0x40, 0x00, 0x00, 0x02,
146 0x40, 0x00, 0x20, 0x00, 0x22, 0x3D, 0x23, 0x10, 0x86, 0x03, 0x96, 0x54,
147 0x11, 0x16, 0x5F, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0xF1, 0x20, 0x5F,
148 0x0D, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x07,
149 0xD4, 0xCB, 0x6E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x00,
150 0x21, 0x18, 0x46, 0x82, 0xEE, 0x48, 0xA7, 0x0A, 0x12, 0x00, 0xFA, 0x99,
151 0x6D, 0xC0};
Amin Hassani02855c22017-09-06 22:34:50 -0700152
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700153} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800154
Allie Woodfdf00512015-03-02 13:34:55 -0800155class DeltaPerformerTest : public ::testing::Test {
Sen Jiang2d528b42015-09-25 11:18:12 -0700156 protected:
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700157 void SetUp() override {
158 install_plan_.source_slot = 0;
159 install_plan_.target_slot = 1;
Alex Deymo542c19b2015-12-03 07:43:31 -0300160 EXPECT_CALL(mock_delegate_, ShouldCancel(_))
161 .WillRepeatedly(testing::Return(false));
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700162 }
Allie Woodfdf00512015-03-02 13:34:55 -0800163
Sen Jiang2d528b42015-09-25 11:18:12 -0700164 // Test helper placed where it can easily be friended from DeltaPerformer.
165 void RunManifestValidation(const DeltaArchiveManifest& manifest,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800166 uint64_t major_version,
Alex Deymo64d98782016-02-05 18:03:48 -0800167 InstallPayloadType payload_type,
Sen Jiang2d528b42015-09-25 11:18:12 -0700168 ErrorCode expected) {
Sen Jiangcdd52062017-05-18 15:33:10 -0700169 payload_.type = payload_type;
Allie Woodfdf00512015-03-02 13:34:55 -0800170
171 // The Manifest we are validating.
Sen Jiang2d528b42015-09-25 11:18:12 -0700172 performer_.manifest_.CopyFrom(manifest);
Sen Jiang3e728fe2015-11-05 11:37:23 -0800173 performer_.major_payload_version_ = major_version;
Allie Woodfdf00512015-03-02 13:34:55 -0800174
Sen Jiang2d528b42015-09-25 11:18:12 -0700175 EXPECT_EQ(expected, performer_.ValidateManifest());
Allie Woodfdf00512015-03-02 13:34:55 -0800176 }
177
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700178 brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
179 const vector<AnnotatedOperation>& aops,
Sen Jiang889c65d2015-11-17 15:04:02 -0800180 bool sign_payload) {
Sen Jiangf1236632018-05-11 16:03:23 -0700181 return GeneratePayload(blob_data,
182 aops,
183 sign_payload,
184 kMaxSupportedMajorPayloadVersion,
185 kMaxSupportedMinorPayloadVersion);
Sen Jiang889c65d2015-11-17 15:04:02 -0800186 }
187
188 brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
189 const vector<AnnotatedOperation>& aops,
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700190 bool sign_payload,
Sen Jiang76bfa742015-10-12 17:13:26 -0700191 uint64_t major_version,
192 uint32_t minor_version) {
Sen Jiang0779a152018-07-02 17:34:56 -0700193 test_utils::ScopedTempFile blob_file("Blob-XXXXXX");
194 EXPECT_TRUE(test_utils::WriteFileVector(blob_file.path(), blob_data));
Sen Jiangd78b3892015-09-25 15:19:31 -0700195
196 PayloadGenerationConfig config;
Alex Deymoa4073ef2016-03-22 23:40:53 -0700197 config.version.major = major_version;
198 config.version.minor = minor_version;
Sen Jiangd78b3892015-09-25 15:19:31 -0700199
200 PayloadFile payload;
201 EXPECT_TRUE(payload.Init(config));
202
Tudor Brindusdda79e22018-06-28 18:03:21 -0700203 PartitionConfig old_part(kPartitionNameRoot);
Alex Deymo64d98782016-02-05 18:03:48 -0800204 if (minor_version != kFullPayloadMinorVersion) {
205 // When generating a delta payload we need to include the old partition
206 // information to mark it as a delta payload.
207 old_part.path = "/dev/null";
208 old_part.size = 0;
209 }
Tudor Brindusdda79e22018-06-28 18:03:21 -0700210 PartitionConfig new_part(kPartitionNameRoot);
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700211 new_part.path = "/dev/zero";
212 new_part.size = 1234;
Sen Jiang981eb112015-08-25 17:03:18 -0700213
214 payload.AddPartition(old_part, new_part, aops);
Sen Jiangd78b3892015-09-25 15:19:31 -0700215
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700216 // We include a kernel partition without operations.
Tudor Brindusdda79e22018-06-28 18:03:21 -0700217 old_part.name = kPartitionNameKernel;
218 new_part.name = kPartitionNameKernel;
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700219 new_part.size = 0;
220 payload.AddPartition(old_part, new_part, {});
221
Sen Jiang0779a152018-07-02 17:34:56 -0700222 test_utils::ScopedTempFile payload_file("Payload-XXXXXX");
Sen Jiang260f03b2016-03-21 15:34:58 -0700223 string private_key =
224 sign_payload ? GetBuildArtifactsPath(kUnittestPrivateKeyPath) : "";
Sen Jiang0779a152018-07-02 17:34:56 -0700225 EXPECT_TRUE(payload.WritePayload(payload_file.path(),
226 blob_file.path(),
227 private_key,
228 &payload_.metadata_size));
Sen Jiangd78b3892015-09-25 15:19:31 -0700229
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700230 brillo::Blob payload_data;
Sen Jiang0779a152018-07-02 17:34:56 -0700231 EXPECT_TRUE(utils::ReadFile(payload_file.path(), &payload_data));
Sen Jiangd78b3892015-09-25 15:19:31 -0700232 return payload_data;
233 }
Allie Woodfdf00512015-03-02 13:34:55 -0800234
Alex Deymo51c264e2016-11-04 15:49:53 -0700235 brillo::Blob GenerateSourceCopyPayload(const brillo::Blob& copied_data,
236 bool add_hash) {
237 PayloadGenerationConfig config;
238 const uint64_t kDefaultBlockSize = config.block_size;
239 EXPECT_EQ(0U, copied_data.size() % kDefaultBlockSize);
240 uint64_t num_blocks = copied_data.size() / kDefaultBlockSize;
241 AnnotatedOperation aop;
242 *(aop.op.add_src_extents()) = ExtentForRange(0, num_blocks);
243 *(aop.op.add_dst_extents()) = ExtentForRange(0, num_blocks);
244 aop.op.set_type(InstallOperation::SOURCE_COPY);
245 brillo::Blob src_hash;
246 EXPECT_TRUE(HashCalculator::RawHashOfData(copied_data, &src_hash));
247 if (add_hash)
248 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
249
250 return GeneratePayload(brillo::Blob(), {aop}, false);
251 }
252
Sen Jiang2d528b42015-09-25 11:18:12 -0700253 // Apply |payload_data| on partition specified in |source_path|.
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800254 // Expect result of performer_.Write() to be |expect_success|.
255 // Returns the result of the payload application.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700256 brillo::Blob ApplyPayload(const brillo::Blob& payload_data,
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800257 const string& source_path,
258 bool expect_success) {
Amin Hassani008c4582019-01-13 16:22:47 -0800259 return ApplyPayloadToData(
260 payload_data, source_path, brillo::Blob(), expect_success);
Alex Deymo79715ad2015-10-02 14:27:53 -0700261 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800262
Alex Deymo79715ad2015-10-02 14:27:53 -0700263 // Apply the payload provided in |payload_data| reading from the |source_path|
264 // file and writing the contents to a new partition. The existing data in the
265 // new target file are set to |target_data| before applying the payload.
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800266 // Expect result of performer_.Write() to be |expect_success|.
Alex Deymo79715ad2015-10-02 14:27:53 -0700267 // Returns the result of the payload application.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700268 brillo::Blob ApplyPayloadToData(const brillo::Blob& payload_data,
269 const string& source_path,
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800270 const brillo::Blob& target_data,
271 bool expect_success) {
Sen Jiang0779a152018-07-02 17:34:56 -0700272 test_utils::ScopedTempFile new_part("Partition-XXXXXX");
273 EXPECT_TRUE(test_utils::WriteFileVector(new_part.path(), target_data));
Alex Deymo79715ad2015-10-02 14:27:53 -0700274
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700275 // We installed the operations only in the rootfs partition, but the
276 // delta performer needs to access all the partitions.
Alex Deymo542c19b2015-12-03 07:43:31 -0300277 fake_boot_control_.SetPartitionDevice(
Sen Jiang456853f2018-08-13 15:41:43 -0700278 kPartitionNameRoot, install_plan_.target_slot, new_part.path());
Alex Deymo542c19b2015-12-03 07:43:31 -0300279 fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700280 kPartitionNameRoot, install_plan_.source_slot, source_path);
Alex Deymo542c19b2015-12-03 07:43:31 -0300281 fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700282 kPartitionNameKernel, install_plan_.target_slot, "/dev/null");
Alex Deymo542c19b2015-12-03 07:43:31 -0300283 fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700284 kPartitionNameKernel, install_plan_.source_slot, "/dev/null");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800285
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800286 EXPECT_EQ(expect_success,
287 performer_.Write(payload_data.data(), payload_data.size()));
Sen Jiang2d528b42015-09-25 11:18:12 -0700288 EXPECT_EQ(0, performer_.Close());
289
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700290 brillo::Blob partition_data;
Sen Jiang0779a152018-07-02 17:34:56 -0700291 EXPECT_TRUE(utils::ReadFile(new_part.path(), &partition_data));
Sen Jiang2d528b42015-09-25 11:18:12 -0700292 return partition_data;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800293 }
294
Sen Jiang2d528b42015-09-25 11:18:12 -0700295 // Calls delta performer's Write method by pretending to pass in bytes from a
296 // delta file whose metadata size is actual_metadata_size and tests if all
297 // checks are correctly performed if the install plan contains
298 // expected_metadata_size and that the result of the parsing are as per
299 // hash_checks_mandatory flag.
300 void DoMetadataSizeTest(uint64_t expected_metadata_size,
301 uint64_t actual_metadata_size,
302 bool hash_checks_mandatory) {
303 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800304
Sen Jiang2d528b42015-09-25 11:18:12 -0700305 // Set a valid magic string and version number 1.
306 EXPECT_TRUE(performer_.Write("CrAU", 4));
307 uint64_t version = htobe64(kChromeOSMajorPayloadVersion);
308 EXPECT_TRUE(performer_.Write(&version, 8));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800309
Sen Jiang0affc2c2017-02-10 15:55:05 -0800310 payload_.metadata_size = expected_metadata_size;
Sen Jiang2d528b42015-09-25 11:18:12 -0700311 ErrorCode error_code;
312 // When filling in size in manifest, exclude the size of the 20-byte header.
313 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
314 bool result = performer_.Write(&size_in_manifest, 8, &error_code);
315 if (expected_metadata_size == actual_metadata_size ||
316 !hash_checks_mandatory) {
317 EXPECT_TRUE(result);
318 } else {
319 EXPECT_FALSE(result);
320 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
321 }
Sen Jiangd78b3892015-09-25 15:19:31 -0700322
Sen Jiang2d528b42015-09-25 11:18:12 -0700323 EXPECT_LT(performer_.Close(), 0);
324 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800325
Sen Jiang2d528b42015-09-25 11:18:12 -0700326 // Generates a valid delta file but tests the delta performer by suppling
327 // different metadata signatures as per metadata_signature_test flag and
328 // sees if the result of the parsing are as per hash_checks_mandatory flag.
329 void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
330 bool sign_payload,
331 bool hash_checks_mandatory) {
Sen Jiang2d528b42015-09-25 11:18:12 -0700332 // Loads the payload and parses the manifest.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700333 brillo::Blob payload = GeneratePayload(brillo::Blob(),
Amin Hassani008c4582019-01-13 16:22:47 -0800334 vector<AnnotatedOperation>(),
335 sign_payload,
336 kChromeOSMajorPayloadVersion,
337 kFullPayloadMinorVersion);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800338
Sen Jiang2d528b42015-09-25 11:18:12 -0700339 LOG(INFO) << "Payload size: " << payload.size();
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800340
Sen Jiang2d528b42015-09-25 11:18:12 -0700341 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800342
Sen Jiang9c89e842018-02-02 13:51:21 -0800343 MetadataParseResult expected_result, actual_result;
Sen Jiang2d528b42015-09-25 11:18:12 -0700344 ErrorCode expected_error, actual_error;
345
346 // Fill up the metadata signature in install plan according to the test.
347 switch (metadata_signature_test) {
348 case kEmptyMetadataSignature:
Sen Jiang0affc2c2017-02-10 15:55:05 -0800349 payload_.metadata_signature.clear();
Sen Jiang9c89e842018-02-02 13:51:21 -0800350 expected_result = MetadataParseResult::kError;
Sen Jiang2d528b42015-09-25 11:18:12 -0700351 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
352 break;
353
354 case kInvalidMetadataSignature:
Sen Jiang0affc2c2017-02-10 15:55:05 -0800355 payload_.metadata_signature = kBogusMetadataSignature1;
Sen Jiang9c89e842018-02-02 13:51:21 -0800356 expected_result = MetadataParseResult::kError;
Sen Jiang2d528b42015-09-25 11:18:12 -0700357 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
358 break;
359
360 case kValidMetadataSignature:
361 default:
362 // Set the install plan's metadata size to be the same as the one
363 // in the manifest so that we pass the metadata size checks. Only
364 // then we can get to manifest signature checks.
365 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
366 payload.data(),
Sen Jiang0affc2c2017-02-10 15:55:05 -0800367 payload_.metadata_size,
Sen Jiang260f03b2016-03-21 15:34:58 -0700368 GetBuildArtifactsPath(kUnittestPrivateKeyPath),
Sen Jiang0affc2c2017-02-10 15:55:05 -0800369 &payload_.metadata_signature));
370 EXPECT_FALSE(payload_.metadata_signature.empty());
Sen Jiang9c89e842018-02-02 13:51:21 -0800371 expected_result = MetadataParseResult::kSuccess;
Sen Jiang2d528b42015-09-25 11:18:12 -0700372 expected_error = ErrorCode::kSuccess;
373 break;
374 }
375
376 // Ignore the expected result/error if hash checks are not mandatory.
377 if (!hash_checks_mandatory) {
Sen Jiang9c89e842018-02-02 13:51:21 -0800378 expected_result = MetadataParseResult::kSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700379 expected_error = ErrorCode::kSuccess;
Sen Jiang2d528b42015-09-25 11:18:12 -0700380 }
381
382 // Use the public key corresponding to the private key used above to
383 // sign the metadata.
Sen Jiang260f03b2016-03-21 15:34:58 -0700384 string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath);
385 EXPECT_TRUE(utils::FileExists(public_key_path.c_str()));
386 performer_.set_public_key_path(public_key_path);
Sen Jiang2d528b42015-09-25 11:18:12 -0700387
388 // Init actual_error with an invalid value so that we make sure
389 // ParsePayloadMetadata properly populates it in all cases.
390 actual_error = ErrorCode::kUmaReportedMax;
391 actual_result = performer_.ParsePayloadMetadata(payload, &actual_error);
392
393 EXPECT_EQ(expected_result, actual_result);
394 EXPECT_EQ(expected_error, actual_error);
395
396 // Check that the parsed metadata size is what's expected. This test
397 // implicitly confirms that the metadata signature is valid, if required.
Sen Jiang9c89e842018-02-02 13:51:21 -0800398 EXPECT_EQ(payload_.metadata_size, performer_.metadata_size_);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800399 }
400
Alex Deymo51c264e2016-11-04 15:49:53 -0700401 // Helper function to pretend that the ECC file descriptor was already opened.
402 // Returns a pointer to the created file descriptor.
403 FakeFileDescriptor* SetFakeECCFile(size_t size) {
404 EXPECT_FALSE(performer_.source_ecc_fd_) << "source_ecc_fd_ already open.";
405 FakeFileDescriptor* ret = new FakeFileDescriptor();
406 fake_ecc_fd_.reset(ret);
407 // Call open to simulate it was already opened.
408 ret->Open("", 0);
409 ret->SetFileSize(size);
410 performer_.source_ecc_fd_ = fake_ecc_fd_;
411 return ret;
412 }
413
414 uint64_t GetSourceEccRecoveredFailures() const {
415 return performer_.source_ecc_recovered_failures_;
416 }
417
Sen Jiang2d528b42015-09-25 11:18:12 -0700418 FakePrefs prefs_;
419 InstallPlan install_plan_;
Sen Jiang0affc2c2017-02-10 15:55:05 -0800420 InstallPlan::Payload payload_;
Alex Deymo542c19b2015-12-03 07:43:31 -0300421 FakeBootControl fake_boot_control_;
422 FakeHardware fake_hardware_;
423 MockDownloadActionDelegate mock_delegate_;
Alex Deymo51c264e2016-11-04 15:49:53 -0700424 FileDescriptorPtr fake_ecc_fd_;
Sen Jiang0affc2c2017-02-10 15:55:05 -0800425 DeltaPerformer performer_{&prefs_,
426 &fake_boot_control_,
427 &fake_hardware_,
428 &mock_delegate_,
429 &install_plan_,
Sen Jiang44906962018-01-08 17:39:04 -0800430 &payload_,
Amin Hassanied37d682018-04-06 13:22:00 -0700431 false /* interactive*/};
Sen Jiang2d528b42015-09-25 11:18:12 -0700432};
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800433
Sen Jiang2d528b42015-09-25 11:18:12 -0700434TEST_F(DeltaPerformerTest, FullPayloadWriteTest) {
Sen Jiangcdd52062017-05-18 15:33:10 -0700435 payload_.type = InstallPayloadType::kFull;
Amin Hassani008c4582019-01-13 16:22:47 -0800436 brillo::Blob expected_data =
437 brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
Sen Jiang2d528b42015-09-25 11:18:12 -0700438 expected_data.resize(4096); // block size
439 vector<AnnotatedOperation> aops;
440 AnnotatedOperation aop;
441 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
442 aop.op.set_data_offset(0);
443 aop.op.set_data_length(expected_data.size());
444 aop.op.set_type(InstallOperation::REPLACE);
445 aops.push_back(aop);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800446
Amin Hassani008c4582019-01-13 16:22:47 -0800447 brillo::Blob payload_data = GeneratePayload(expected_data,
448 aops,
449 false,
450 kChromeOSMajorPayloadVersion,
451 kFullPayloadMinorVersion);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800452
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800453 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800454}
455
Alex Deymo542c19b2015-12-03 07:43:31 -0300456TEST_F(DeltaPerformerTest, ShouldCancelTest) {
Sen Jiangcdd52062017-05-18 15:33:10 -0700457 payload_.type = InstallPayloadType::kFull;
Amin Hassani008c4582019-01-13 16:22:47 -0800458 brillo::Blob expected_data =
459 brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
Alex Deymo542c19b2015-12-03 07:43:31 -0300460 expected_data.resize(4096); // block size
461 vector<AnnotatedOperation> aops;
462 AnnotatedOperation aop;
463 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
464 aop.op.set_data_offset(0);
465 aop.op.set_data_length(expected_data.size());
466 aop.op.set_type(InstallOperation::REPLACE);
467 aops.push_back(aop);
468
Amin Hassani008c4582019-01-13 16:22:47 -0800469 brillo::Blob payload_data = GeneratePayload(expected_data,
470 aops,
471 false,
472 kChromeOSMajorPayloadVersion,
473 kFullPayloadMinorVersion);
Alex Deymo542c19b2015-12-03 07:43:31 -0300474
475 testing::Mock::VerifyAndClearExpectations(&mock_delegate_);
476 EXPECT_CALL(mock_delegate_, ShouldCancel(_))
Amin Hassani008c4582019-01-13 16:22:47 -0800477 .WillOnce(testing::DoAll(testing::SetArgPointee<0>(ErrorCode::kError),
478 testing::Return(true)));
Alex Deymo542c19b2015-12-03 07:43:31 -0300479
480 ApplyPayload(payload_data, "/dev/null", false);
481}
482
Sen Jiang2d528b42015-09-25 11:18:12 -0700483TEST_F(DeltaPerformerTest, ReplaceOperationTest) {
Amin Hassani008c4582019-01-13 16:22:47 -0800484 brillo::Blob expected_data =
485 brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
Sen Jiang2d528b42015-09-25 11:18:12 -0700486 expected_data.resize(4096); // block size
487 vector<AnnotatedOperation> aops;
488 AnnotatedOperation aop;
489 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
490 aop.op.set_data_offset(0);
491 aop.op.set_data_length(expected_data.size());
492 aop.op.set_type(InstallOperation::REPLACE);
493 aops.push_back(aop);
494
Sen Jiang889c65d2015-11-17 15:04:02 -0800495 brillo::Blob payload_data = GeneratePayload(expected_data, aops, false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700496
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800497 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
Sen Jiang2d528b42015-09-25 11:18:12 -0700498}
499
500TEST_F(DeltaPerformerTest, ReplaceBzOperationTest) {
Amin Hassani008c4582019-01-13 16:22:47 -0800501 brillo::Blob expected_data =
502 brillo::Blob(std::begin(kRandomString), std::end(kRandomString));
Sen Jiang2d528b42015-09-25 11:18:12 -0700503 expected_data.resize(4096); // block size
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700504 brillo::Blob bz_data;
Sen Jiang2d528b42015-09-25 11:18:12 -0700505 EXPECT_TRUE(BzipCompress(expected_data, &bz_data));
506
507 vector<AnnotatedOperation> aops;
508 AnnotatedOperation aop;
509 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
510 aop.op.set_data_offset(0);
511 aop.op.set_data_length(bz_data.size());
512 aop.op.set_type(InstallOperation::REPLACE_BZ);
513 aops.push_back(aop);
514
Sen Jiang889c65d2015-11-17 15:04:02 -0800515 brillo::Blob payload_data = GeneratePayload(bz_data, aops, false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700516
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800517 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
Sen Jiang2d528b42015-09-25 11:18:12 -0700518}
519
Alex Deymo2d621a32015-10-01 11:09:01 -0700520TEST_F(DeltaPerformerTest, ReplaceXzOperationTest) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700521 brillo::Blob xz_data(std::begin(kXzCompressedData),
Amin Hassani008c4582019-01-13 16:22:47 -0800522 std::end(kXzCompressedData));
Sen Jiang5e1af982018-11-01 15:01:45 -0700523 // The compressed xz data contains a single "a" and padded with zero for the
524 // rest of the block.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700525 brillo::Blob expected_data = brillo::Blob(4096, 0);
Alex Deymo2d621a32015-10-01 11:09:01 -0700526 expected_data[0] = 'a';
527
528 AnnotatedOperation aop;
529 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
530 aop.op.set_data_offset(0);
531 aop.op.set_data_length(xz_data.size());
532 aop.op.set_type(InstallOperation::REPLACE_XZ);
533 vector<AnnotatedOperation> aops = {aop};
534
Sen Jiang889c65d2015-11-17 15:04:02 -0800535 brillo::Blob payload_data = GeneratePayload(xz_data, aops, false);
Alex Deymo2d621a32015-10-01 11:09:01 -0700536
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800537 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
Alex Deymo2d621a32015-10-01 11:09:01 -0700538}
539
Alex Deymo79715ad2015-10-02 14:27:53 -0700540TEST_F(DeltaPerformerTest, ZeroOperationTest) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700541 brillo::Blob existing_data = brillo::Blob(4096 * 10, 'a');
542 brillo::Blob expected_data = existing_data;
Alex Deymo79715ad2015-10-02 14:27:53 -0700543 // Blocks 4, 5 and 7 should have zeros instead of 'a' after the operation is
544 // applied.
Amin Hassani008c4582019-01-13 16:22:47 -0800545 std::fill(
546 expected_data.data() + 4096 * 4, expected_data.data() + 4096 * 6, 0);
547 std::fill(
548 expected_data.data() + 4096 * 7, expected_data.data() + 4096 * 8, 0);
Alex Deymo79715ad2015-10-02 14:27:53 -0700549
550 AnnotatedOperation aop;
551 *(aop.op.add_dst_extents()) = ExtentForRange(4, 2);
552 *(aop.op.add_dst_extents()) = ExtentForRange(7, 1);
553 aop.op.set_type(InstallOperation::ZERO);
554 vector<AnnotatedOperation> aops = {aop};
555
Sen Jiang889c65d2015-11-17 15:04:02 -0800556 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), aops, false);
Alex Deymo79715ad2015-10-02 14:27:53 -0700557
558 EXPECT_EQ(expected_data,
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800559 ApplyPayloadToData(payload_data, "/dev/null", existing_data, true));
Alex Deymo79715ad2015-10-02 14:27:53 -0700560}
561
Sen Jiang2d528b42015-09-25 11:18:12 -0700562TEST_F(DeltaPerformerTest, SourceCopyOperationTest) {
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800563 brillo::Blob expected_data(std::begin(kRandomString),
564 std::end(kRandomString));
Sen Jiang2d528b42015-09-25 11:18:12 -0700565 expected_data.resize(4096); // block size
Sen Jiang2d528b42015-09-25 11:18:12 -0700566 AnnotatedOperation aop;
567 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
568 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
569 aop.op.set_type(InstallOperation::SOURCE_COPY);
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800570 brillo::Blob src_hash;
571 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
572 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
Sen Jiang2d528b42015-09-25 11:18:12 -0700573
Sen Jiang889c65d2015-11-17 15:04:02 -0800574 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
575
Sen Jiang0779a152018-07-02 17:34:56 -0700576 test_utils::ScopedTempFile source("Source-XXXXXX");
577 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
Sen Jiang2d528b42015-09-25 11:18:12 -0700578
Sen Jiang0779a152018-07-02 17:34:56 -0700579 EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800580}
581
Amin Hassani02855c22017-09-06 22:34:50 -0700582TEST_F(DeltaPerformerTest, PuffdiffOperationTest) {
583 AnnotatedOperation aop;
584 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
585 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
586 brillo::Blob puffdiff_payload(std::begin(puffdiff_patch),
587 std::end(puffdiff_patch));
588 aop.op.set_data_offset(0);
589 aop.op.set_data_length(puffdiff_payload.size());
590 aop.op.set_type(InstallOperation::PUFFDIFF);
591 brillo::Blob src(std::begin(src_deflates), std::end(src_deflates));
592 src.resize(4096); // block size
593 brillo::Blob src_hash;
594 EXPECT_TRUE(HashCalculator::RawHashOfData(src, &src_hash));
595 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
596
597 brillo::Blob payload_data = GeneratePayload(puffdiff_payload, {aop}, false);
598
Sen Jiang0779a152018-07-02 17:34:56 -0700599 test_utils::ScopedTempFile source("Source-XXXXXX");
600 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), src));
Amin Hassani02855c22017-09-06 22:34:50 -0700601
602 brillo::Blob dst(std::begin(dst_deflates), std::end(dst_deflates));
Sen Jiang0779a152018-07-02 17:34:56 -0700603 EXPECT_EQ(dst, ApplyPayload(payload_data, source.path(), true));
Amin Hassani02855c22017-09-06 22:34:50 -0700604}
605
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800606TEST_F(DeltaPerformerTest, SourceHashMismatchTest) {
607 brillo::Blob expected_data = {'f', 'o', 'o'};
608 brillo::Blob actual_data = {'b', 'a', 'r'};
609 expected_data.resize(4096); // block size
610 actual_data.resize(4096); // block size
611
612 AnnotatedOperation aop;
613 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
614 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
615 aop.op.set_type(InstallOperation::SOURCE_COPY);
616 brillo::Blob src_hash;
617 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
618 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
619
Sen Jiang889c65d2015-11-17 15:04:02 -0800620 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
621
Sen Jiang0779a152018-07-02 17:34:56 -0700622 test_utils::ScopedTempFile source("Source-XXXXXX");
623 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), actual_data));
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800624
Sen Jiang0779a152018-07-02 17:34:56 -0700625 EXPECT_EQ(actual_data, ApplyPayload(payload_data, source.path(), false));
Sen Jiang2d528b42015-09-25 11:18:12 -0700626}
627
Alex Deymo51c264e2016-11-04 15:49:53 -0700628// Test that the error-corrected file descriptor is used to read the partition
629// since the source partition doesn't match the operation hash.
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700630TEST_F(DeltaPerformerTest, ErrorCorrectionSourceCopyFallbackTest) {
Sen Jiang0779a152018-07-02 17:34:56 -0700631 constexpr size_t kCopyOperationSize = 4 * 4096;
632 test_utils::ScopedTempFile source("Source-XXXXXX");
Alex Deymo51c264e2016-11-04 15:49:53 -0700633 // Write invalid data to the source image, which doesn't match the expected
634 // hash.
635 brillo::Blob invalid_data(kCopyOperationSize, 0x55);
Sen Jiang0779a152018-07-02 17:34:56 -0700636 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), invalid_data));
Alex Deymo51c264e2016-11-04 15:49:53 -0700637
638 // Setup the fec file descriptor as the fake stream, which matches
639 // |expected_data|.
640 FakeFileDescriptor* fake_fec = SetFakeECCFile(kCopyOperationSize);
641 brillo::Blob expected_data = FakeFileDescriptorData(kCopyOperationSize);
642
643 brillo::Blob payload_data = GenerateSourceCopyPayload(expected_data, true);
Sen Jiang0779a152018-07-02 17:34:56 -0700644 EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
Alex Deymo51c264e2016-11-04 15:49:53 -0700645 // Verify that the fake_fec was actually used.
646 EXPECT_EQ(1U, fake_fec->GetReadOps().size());
647 EXPECT_EQ(1U, GetSourceEccRecoveredFailures());
648}
649
650// Test that the error-corrected file descriptor is used to read a partition
651// when no hash is available for SOURCE_COPY but it falls back to the normal
652// file descriptor when the size of the error corrected one is too small.
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700653TEST_F(DeltaPerformerTest, ErrorCorrectionSourceCopyWhenNoHashFallbackTest) {
Sen Jiang0779a152018-07-02 17:34:56 -0700654 constexpr size_t kCopyOperationSize = 4 * 4096;
655 test_utils::ScopedTempFile source("Source-XXXXXX");
Alex Deymo51c264e2016-11-04 15:49:53 -0700656 // Setup the source path with the right expected data.
657 brillo::Blob expected_data = FakeFileDescriptorData(kCopyOperationSize);
Sen Jiang0779a152018-07-02 17:34:56 -0700658 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
Alex Deymo51c264e2016-11-04 15:49:53 -0700659
660 // Setup the fec file descriptor as the fake stream, with smaller data than
661 // the expected.
662 FakeFileDescriptor* fake_fec = SetFakeECCFile(kCopyOperationSize / 2);
663
664 // The payload operation doesn't include an operation hash.
665 brillo::Blob payload_data = GenerateSourceCopyPayload(expected_data, false);
Sen Jiang0779a152018-07-02 17:34:56 -0700666 EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
Alex Deymo51c264e2016-11-04 15:49:53 -0700667 // Verify that the fake_fec was attempted to be used. Since the file
668 // descriptor is shorter it can actually do more than one read to realize it
669 // reached the EOF.
670 EXPECT_LE(1U, fake_fec->GetReadOps().size());
671 // This fallback doesn't count as an error-corrected operation since the
672 // operation hash was not available.
673 EXPECT_EQ(0U, GetSourceEccRecoveredFailures());
674}
675
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700676TEST_F(DeltaPerformerTest, ChooseSourceFDTest) {
Sen Jiang0779a152018-07-02 17:34:56 -0700677 constexpr size_t kSourceSize = 4 * 4096;
678 test_utils::ScopedTempFile source("Source-XXXXXX");
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700679 // Write invalid data to the source image, which doesn't match the expected
680 // hash.
681 brillo::Blob invalid_data(kSourceSize, 0x55);
Sen Jiang0779a152018-07-02 17:34:56 -0700682 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), invalid_data));
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700683
684 performer_.source_fd_ = std::make_shared<EintrSafeFileDescriptor>();
Sen Jiang0779a152018-07-02 17:34:56 -0700685 performer_.source_fd_->Open(source.path().c_str(), O_RDONLY);
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700686 performer_.block_size_ = 4096;
687
688 // Setup the fec file descriptor as the fake stream, which matches
689 // |expected_data|.
690 FakeFileDescriptor* fake_fec = SetFakeECCFile(kSourceSize);
691 brillo::Blob expected_data = FakeFileDescriptorData(kSourceSize);
692
693 InstallOperation op;
694 *(op.add_src_extents()) = ExtentForRange(0, kSourceSize / 4096);
695 brillo::Blob src_hash;
696 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
697 op.set_src_sha256_hash(src_hash.data(), src_hash.size());
698
699 ErrorCode error = ErrorCode::kSuccess;
700 EXPECT_EQ(performer_.source_ecc_fd_, performer_.ChooseSourceFD(op, &error));
701 EXPECT_EQ(ErrorCode::kSuccess, error);
702 // Verify that the fake_fec was actually used.
703 EXPECT_EQ(1U, fake_fec->GetReadOps().size());
704 EXPECT_EQ(1U, GetSourceEccRecoveredFailures());
705}
706
Sen Jiang2d528b42015-09-25 11:18:12 -0700707TEST_F(DeltaPerformerTest, ExtentsToByteStringTest) {
Allie Wood56873452015-03-27 17:48:40 -0700708 uint64_t test[] = {1, 1, 4, 2, 0, 1};
Alex Vakulenko0103c362016-01-20 07:56:15 -0800709 static_assert(arraysize(test) % 2 == 0, "Array size uneven");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800710 const uint64_t block_size = 4096;
Allie Wood56873452015-03-27 17:48:40 -0700711 const uint64_t file_length = 4 * block_size - 13;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800712
713 google::protobuf::RepeatedPtrField<Extent> extents;
714 for (size_t i = 0; i < arraysize(test); i += 2) {
Sen Jiang2d528b42015-09-25 11:18:12 -0700715 *(extents.Add()) = ExtentForRange(test[i], test[i + 1]);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800716 }
717
Allie Wood56873452015-03-27 17:48:40 -0700718 string expected_output = "4096:4096,16384:8192,0:4083";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800719 string actual_output;
Amin Hassani008c4582019-01-13 16:22:47 -0800720 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(
721 extents, block_size, file_length, &actual_output));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800722 EXPECT_EQ(expected_output, actual_output);
723}
Darin Petkov68c10d12010-10-14 09:24:37 -0700724
Sen Jiang2d528b42015-09-25 11:18:12 -0700725TEST_F(DeltaPerformerTest, ValidateManifestFullGoodTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800726 // The Manifest we are validating.
727 DeltaArchiveManifest manifest;
728 manifest.mutable_new_kernel_info();
729 manifest.mutable_new_rootfs_info();
Alex Deymocbf09892015-09-11 16:13:16 -0700730 manifest.set_minor_version(kFullPayloadMinorVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800731
Alex Deymo64d98782016-02-05 18:03:48 -0800732 RunManifestValidation(manifest,
733 kChromeOSMajorPayloadVersion,
734 InstallPayloadType::kFull,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800735 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800736}
737
Sen Jiang2d528b42015-09-25 11:18:12 -0700738TEST_F(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800739 // The Manifest we are validating.
740 DeltaArchiveManifest manifest;
741 manifest.mutable_old_kernel_info();
742 manifest.mutable_old_rootfs_info();
743 manifest.mutable_new_kernel_info();
744 manifest.mutable_new_rootfs_info();
Sen Jiangf1236632018-05-11 16:03:23 -0700745 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
746
747 RunManifestValidation(manifest,
748 kChromeOSMajorPayloadVersion,
749 InstallPayloadType::kDelta,
750 ErrorCode::kSuccess);
751}
752
753TEST_F(DeltaPerformerTest, ValidateManifestDeltaMinGoodTest) {
754 // The Manifest we are validating.
755 DeltaArchiveManifest manifest;
756 manifest.mutable_old_kernel_info();
757 manifest.mutable_old_rootfs_info();
758 manifest.mutable_new_kernel_info();
759 manifest.mutable_new_rootfs_info();
760 manifest.set_minor_version(kMinSupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800761
Alex Deymo64d98782016-02-05 18:03:48 -0800762 RunManifestValidation(manifest,
763 kChromeOSMajorPayloadVersion,
764 InstallPayloadType::kDelta,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800765 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800766}
767
Sen Jiang2d528b42015-09-25 11:18:12 -0700768TEST_F(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800769 // The Manifest we are validating.
770 DeltaArchiveManifest manifest;
771
Alex Deymo64d98782016-02-05 18:03:48 -0800772 RunManifestValidation(manifest,
Sen Jiangf1236632018-05-11 16:03:23 -0700773 kMaxSupportedMajorPayloadVersion,
Alex Deymo64d98782016-02-05 18:03:48 -0800774 InstallPayloadType::kFull,
775 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800776}
777
Sen Jiang2d528b42015-09-25 11:18:12 -0700778TEST_F(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800779 // The Manifest we are validating.
780 DeltaArchiveManifest manifest;
Alex Deymo64d98782016-02-05 18:03:48 -0800781 // Add an empty old_rootfs_info() to trick the DeltaPerformer into think that
782 // this is a delta payload manifest with a missing minor version.
783 manifest.mutable_old_rootfs_info();
Don Garrettb8dd1d92013-11-22 17:40:02 -0800784
Alex Deymo64d98782016-02-05 18:03:48 -0800785 RunManifestValidation(manifest,
Sen Jiangf1236632018-05-11 16:03:23 -0700786 kMaxSupportedMajorPayloadVersion,
Alex Deymo64d98782016-02-05 18:03:48 -0800787 InstallPayloadType::kDelta,
788 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800789}
790
Sen Jiang2d528b42015-09-25 11:18:12 -0700791TEST_F(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800792 // The Manifest we are validating.
793 DeltaArchiveManifest manifest;
794 manifest.mutable_old_kernel_info();
795 manifest.mutable_new_kernel_info();
796 manifest.mutable_new_rootfs_info();
Sen Jiangf1236632018-05-11 16:03:23 -0700797 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800798
Alex Deymo64d98782016-02-05 18:03:48 -0800799 RunManifestValidation(manifest,
800 kChromeOSMajorPayloadVersion,
801 InstallPayloadType::kFull,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800802 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800803}
804
Sen Jiang2d528b42015-09-25 11:18:12 -0700805TEST_F(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800806 // The Manifest we are validating.
807 DeltaArchiveManifest manifest;
808 manifest.mutable_old_rootfs_info();
809 manifest.mutable_new_kernel_info();
810 manifest.mutable_new_rootfs_info();
Sen Jiangf1236632018-05-11 16:03:23 -0700811 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800812
Alex Deymo64d98782016-02-05 18:03:48 -0800813 RunManifestValidation(manifest,
814 kChromeOSMajorPayloadVersion,
815 InstallPayloadType::kFull,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800816 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800817}
818
Sen Jiangc8f6b7a2015-10-21 11:09:59 -0700819TEST_F(DeltaPerformerTest, ValidateManifestFullPartitionUpdateTest) {
820 // The Manifest we are validating.
821 DeltaArchiveManifest manifest;
822 PartitionUpdate* partition = manifest.add_partitions();
823 partition->mutable_old_partition_info();
824 partition->mutable_new_partition_info();
Sen Jiangf1236632018-05-11 16:03:23 -0700825 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
Sen Jiangc8f6b7a2015-10-21 11:09:59 -0700826
Alex Deymo64d98782016-02-05 18:03:48 -0800827 RunManifestValidation(manifest,
828 kBrilloMajorPayloadVersion,
829 InstallPayloadType::kFull,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800830 ErrorCode::kPayloadMismatchedType);
Sen Jiangc8f6b7a2015-10-21 11:09:59 -0700831}
832
Sen Jiang2d528b42015-09-25 11:18:12 -0700833TEST_F(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800834 // The Manifest we are validating.
835 DeltaArchiveManifest manifest;
836
837 // Generate a bad version number.
Sen Jiangf1236632018-05-11 16:03:23 -0700838 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion + 10000);
Alex Deymo64d98782016-02-05 18:03:48 -0800839 // Mark the manifest as a delta payload by setting old_rootfs_info.
840 manifest.mutable_old_rootfs_info();
Don Garrettb8dd1d92013-11-22 17:40:02 -0800841
Alex Deymo64d98782016-02-05 18:03:48 -0800842 RunManifestValidation(manifest,
Sen Jiangf1236632018-05-11 16:03:23 -0700843 kMaxSupportedMajorPayloadVersion,
Alex Deymo64d98782016-02-05 18:03:48 -0800844 InstallPayloadType::kDelta,
845 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800846}
847
Sen Jiang5011df62017-06-28 17:13:19 -0700848TEST_F(DeltaPerformerTest, ValidateManifestDowngrade) {
849 // The Manifest we are validating.
850 DeltaArchiveManifest manifest;
851
852 manifest.set_minor_version(kFullPayloadMinorVersion);
853 manifest.set_max_timestamp(1);
854 fake_hardware_.SetBuildTimestamp(2);
855
856 RunManifestValidation(manifest,
Sen Jiangf1236632018-05-11 16:03:23 -0700857 kMaxSupportedMajorPayloadVersion,
Sen Jiang5011df62017-06-28 17:13:19 -0700858 InstallPayloadType::kFull,
859 ErrorCode::kPayloadTimestampError);
860}
861
Sen Jiangb8060e42015-09-24 17:30:50 -0700862TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeTest) {
Eric Caruso4495bfe2018-01-23 16:34:20 -0800863 unsigned int seed = time(nullptr);
Sen Jiangb8060e42015-09-24 17:30:50 -0700864 EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
865
866 uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
867 EXPECT_TRUE(performer_.Write(&major_version, 8));
868
Eric Caruso4495bfe2018-01-23 16:34:20 -0800869 uint64_t manifest_size = rand_r(&seed) % 256;
Sen Jiangb8060e42015-09-24 17:30:50 -0700870 uint64_t manifest_size_be = htobe64(manifest_size);
871 EXPECT_TRUE(performer_.Write(&manifest_size_be, 8));
872
Eric Caruso4495bfe2018-01-23 16:34:20 -0800873 uint32_t metadata_signature_size = rand_r(&seed) % 256;
Sen Jiangb8060e42015-09-24 17:30:50 -0700874 uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
875 EXPECT_TRUE(performer_.Write(&metadata_signature_size_be, 4));
876
877 EXPECT_LT(performer_.Close(), 0);
878
879 EXPECT_TRUE(performer_.IsHeaderParsed());
Sen Jiang9c89e842018-02-02 13:51:21 -0800880 EXPECT_EQ(kBrilloMajorPayloadVersion, performer_.major_payload_version_);
881 EXPECT_EQ(24 + manifest_size, performer_.metadata_size_); // 4 + 8 + 8 + 4
Sen Jiang76bfa742015-10-12 17:13:26 -0700882 EXPECT_EQ(metadata_signature_size, performer_.metadata_signature_size_);
883}
884
Sen Jiang9c89e842018-02-02 13:51:21 -0800885TEST_F(DeltaPerformerTest, BrilloParsePayloadMetadataTest) {
Amin Hassani008c4582019-01-13 16:22:47 -0800886 brillo::Blob payload_data = GeneratePayload(
887 {}, {}, true, kBrilloMajorPayloadVersion, kSourceMinorPayloadVersion);
Sen Jiang76bfa742015-10-12 17:13:26 -0700888 install_plan_.hash_checks_mandatory = true;
Sen Jiang260f03b2016-03-21 15:34:58 -0700889 performer_.set_public_key_path(GetBuildArtifactsPath(kUnittestPublicKeyPath));
Sen Jiang9c89e842018-02-02 13:51:21 -0800890 ErrorCode error;
891 EXPECT_EQ(MetadataParseResult::kSuccess,
892 performer_.ParsePayloadMetadata(payload_data, &error));
893 EXPECT_EQ(ErrorCode::kSuccess, error);
Sen Jiangb8060e42015-09-24 17:30:50 -0700894}
895
Sen Jiang2d528b42015-09-25 11:18:12 -0700896TEST_F(DeltaPerformerTest, BadDeltaMagicTest) {
Sen Jiang2d528b42015-09-25 11:18:12 -0700897 EXPECT_TRUE(performer_.Write("junk", 4));
Sen Jiang2d528b42015-09-25 11:18:12 -0700898 EXPECT_FALSE(performer_.Write("morejunk", 8));
899 EXPECT_LT(performer_.Close(), 0);
Darin Petkov934bb412010-11-18 11:21:35 -0800900}
901
Sen Jiang2d528b42015-09-25 11:18:12 -0700902TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800903 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700904}
905
Sen Jiang2d528b42015-09-25 11:18:12 -0700906TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800907 DoMetadataSizeTest(0, 123456, false);
908}
909
Sen Jiang2d528b42015-09-25 11:18:12 -0700910TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800911 DoMetadataSizeTest(13000, 140000, true);
912}
913
Sen Jiang2d528b42015-09-25 11:18:12 -0700914TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800915 DoMetadataSizeTest(40000, 50000, false);
916}
917
Sen Jiang2d528b42015-09-25 11:18:12 -0700918TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800919 DoMetadataSizeTest(85376, 85376, true);
920}
921
Sen Jiang2d528b42015-09-25 11:18:12 -0700922TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700923 DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800924}
925
Sen Jiang2d528b42015-09-25 11:18:12 -0700926TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700927 DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800928}
929
Sen Jiang2d528b42015-09-25 11:18:12 -0700930TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700931 DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800932}
933
Sen Jiang2d528b42015-09-25 11:18:12 -0700934TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700935 DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800936}
937
Sen Jiang2d528b42015-09-25 11:18:12 -0700938TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700939 DoMetadataSignatureTest(kValidMetadataSignature, false, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800940}
941
Sen Jiang2d528b42015-09-25 11:18:12 -0700942TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700943 DoMetadataSignatureTest(kValidMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800944}
945
Sen Jiang2d528b42015-09-25 11:18:12 -0700946TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700947 DoMetadataSignatureTest(kValidMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800948}
949
Sen Jiang2d528b42015-09-25 11:18:12 -0700950TEST_F(DeltaPerformerTest, UsePublicKeyFromResponse) {
David Zeuthene7f89172013-10-31 10:21:04 -0700951 // The result of the GetPublicKeyResponse() method is based on three things
952 //
953 // 1. Whether it's an official build; and
954 // 2. Whether the Public RSA key to be used is in the root filesystem; and
Alex Vakulenko072359c2014-07-18 11:41:07 -0700955 // 3. Whether the response has a public key
David Zeuthene7f89172013-10-31 10:21:04 -0700956 //
957 // We test all eight combinations to ensure that we only use the
958 // public key in the response if
959 //
960 // a. it's not an official build; and
961 // b. there is no key in the root filesystem.
962
Sen Jiang371615b2016-04-13 15:54:29 -0700963 base::ScopedTempDir temp_dir;
964 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Jay Civellia78ddf82017-03-30 11:02:03 -0700965 string non_existing_file = temp_dir.GetPath().Append("non-existing").value();
966 string existing_file = temp_dir.GetPath().Append("existing").value();
Sen Jiang08c6da12019-01-07 18:28:56 -0800967 constexpr char kExistingKey[] = "Existing";
968 ASSERT_TRUE(test_utils::WriteFileString(existing_file, kExistingKey));
David Zeuthene7f89172013-10-31 10:21:04 -0700969
Sen Jiang08c6da12019-01-07 18:28:56 -0800970 // Non-official build, non-existing public-key, key in response ->
971 // kResponseKey
Alex Deymo542c19b2015-12-03 07:43:31 -0300972 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700973 performer_.public_key_path_ = non_existing_file;
Sen Jiang08c6da12019-01-07 18:28:56 -0800974 // This is the result of 'echo -n "Response" | base64' and is not meant to be
975 // a valid public key, but it is valid base-64.
976 constexpr char kResponseKey[] = "Response";
977 constexpr char kBase64ResponseKey[] = "UmVzcG9uc2U=";
978 install_plan_.public_key_rsa = kBase64ResponseKey;
979 string public_key;
980 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
981 EXPECT_EQ(public_key, kResponseKey);
982 // Same with official build -> no key
Alex Deymo542c19b2015-12-03 07:43:31 -0300983 fake_hardware_.SetIsOfficialBuild(true);
Sen Jiang08c6da12019-01-07 18:28:56 -0800984 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
985 EXPECT_TRUE(public_key.empty());
David Zeuthene7f89172013-10-31 10:21:04 -0700986
Sen Jiang08c6da12019-01-07 18:28:56 -0800987 // Non-official build, existing public-key, key in response -> kExistingKey
Alex Deymo542c19b2015-12-03 07:43:31 -0300988 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700989 performer_.public_key_path_ = existing_file;
Sen Jiang08c6da12019-01-07 18:28:56 -0800990 install_plan_.public_key_rsa = kBase64ResponseKey;
991 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
992 EXPECT_EQ(public_key, kExistingKey);
993 // Same with official build -> kExistingKey
Alex Deymo542c19b2015-12-03 07:43:31 -0300994 fake_hardware_.SetIsOfficialBuild(true);
Sen Jiang08c6da12019-01-07 18:28:56 -0800995 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
996 EXPECT_EQ(public_key, kExistingKey);
David Zeuthene7f89172013-10-31 10:21:04 -0700997
Sen Jiang08c6da12019-01-07 18:28:56 -0800998 // Non-official build, non-existing public-key, no key in response -> no key
Alex Deymo542c19b2015-12-03 07:43:31 -0300999 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -07001000 performer_.public_key_path_ = non_existing_file;
1001 install_plan_.public_key_rsa = "";
Sen Jiang08c6da12019-01-07 18:28:56 -08001002 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1003 EXPECT_TRUE(public_key.empty());
1004 // Same with official build -> no key
Alex Deymo542c19b2015-12-03 07:43:31 -03001005 fake_hardware_.SetIsOfficialBuild(true);
Sen Jiang08c6da12019-01-07 18:28:56 -08001006 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1007 EXPECT_TRUE(public_key.empty());
David Zeuthene7f89172013-10-31 10:21:04 -07001008
Sen Jiang08c6da12019-01-07 18:28:56 -08001009 // Non-official build, existing public-key, no key in response -> kExistingKey
Alex Deymo542c19b2015-12-03 07:43:31 -03001010 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -07001011 performer_.public_key_path_ = existing_file;
1012 install_plan_.public_key_rsa = "";
Sen Jiang08c6da12019-01-07 18:28:56 -08001013 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1014 EXPECT_EQ(public_key, kExistingKey);
1015 // Same with official build -> kExistingKey
Alex Deymo542c19b2015-12-03 07:43:31 -03001016 fake_hardware_.SetIsOfficialBuild(true);
Sen Jiang08c6da12019-01-07 18:28:56 -08001017 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1018 EXPECT_EQ(public_key, kExistingKey);
David Zeuthene7f89172013-10-31 10:21:04 -07001019
1020 // Non-official build, non-existing public-key, key in response
1021 // but invalid base64 -> false
Alex Deymo542c19b2015-12-03 07:43:31 -03001022 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -07001023 performer_.public_key_path_ = non_existing_file;
1024 install_plan_.public_key_rsa = "not-valid-base64";
Sen Jiang08c6da12019-01-07 18:28:56 -08001025 EXPECT_FALSE(performer_.GetPublicKey(&public_key));
David Zeuthene7f89172013-10-31 10:21:04 -07001026}
1027
Alex Deymocbf09892015-09-11 16:13:16 -07001028TEST_F(DeltaPerformerTest, ConfVersionsMatch) {
1029 // Test that the versions in update_engine.conf that is installed to the
Sen Jiangf1236632018-05-11 16:03:23 -07001030 // image match the maximum supported delta versions in the update engine.
Allie Wood78750a42015-02-11 15:42:11 -08001031 uint32_t minor_version;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -07001032 brillo::KeyValueStore store;
Sen Jiangee63c6e2016-03-30 14:01:02 -07001033 EXPECT_TRUE(store.Load(GetBuildArtifactsPath().Append("update_engine.conf")));
Alex Deymob42b98d2015-07-06 17:42:38 -07001034 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
Sen Jiangf1236632018-05-11 16:03:23 -07001035 EXPECT_EQ(kMaxSupportedMinorPayloadVersion, minor_version);
Alex Deymocbf09892015-09-11 16:13:16 -07001036
1037 string major_version_str;
1038 uint64_t major_version;
1039 EXPECT_TRUE(store.GetString("PAYLOAD_MAJOR_VERSION", &major_version_str));
1040 EXPECT_TRUE(base::StringToUint64(major_version_str, &major_version));
Sen Jiangf1236632018-05-11 16:03:23 -07001041 EXPECT_EQ(kMaxSupportedMajorPayloadVersion, major_version);
Allie Wood78750a42015-02-11 15:42:11 -08001042}
1043
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001044} // namespace chromeos_update_engine