blob: 4cf975698390cc64dd2ea32a71871adb1be0619d [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 Deymo10875d92014-11-10 21:52:57 -080057using test_utils::System;
Alex Deymo2d621a32015-10-01 11:09:01 -070058using test_utils::kRandomString;
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 Hassani02855c22017-09-06 22:34:50 -070096const uint8_t src_deflates[] = {
97 /* raw 0 */ 0x11, 0x22,
98 /* deflate 2 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
99 /* raw 9 */ 0x33,
100 /* deflate 10 */ 0x03, 0x00,
101 /* raw 12 */
102 /* deflate 12 */ 0x63, 0x04, 0x00,
103 /* raw 15 */ 0x44, 0x55
104};
105
106const uint8_t dst_deflates[] = {
107 /* deflate 0 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00,
108 /* raw 7 */ 0x33, 0x66,
109 /* deflate 9 */ 0x01, 0x05, 0x00, 0xFA, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05,
110 /* deflate 19 */ 0x63, 0x04, 0x00
111};
112
113// To generate this patch either:
114// - Use puffin/src/patching_unittest.cc:TestPatching
115// Or
116// - Use the following approach:
117// * Make src_deflate a string of hex with only spaces. (e.g. "0XTE 0xST")
118// * echo "0XTE 0xST" | xxd -r -p > src.bin
119// * Find the location of deflates in src_deflates (in bytes) in the format of
120// "offset:length,...". (e.g. "2:7,10:2,12:3")
121// * Do previous three steps for dst_deflates.
122// * puffin --operation=puffdiff --src_file=src.bin --dst_file=dst.bin \
123// --src_deflates_byte="2:7,10:2,12:3" --dst_deflates_byte="0:7,9:10,19:3" \
124// --patch_file=patch.bin
125// * hexdump -ve '" " 12/1 "0x%02x, " "\n"' patch.bin
126const uint8_t puffdiff_patch[] = {
127 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x51, 0x08, 0x01, 0x12, 0x27,
128 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A,
129 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58,
130 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10,
131 0x38, 0x18, 0x1F, 0x1A, 0x24, 0x0A, 0x02, 0x10, 0x32, 0x0A, 0x04, 0x08,
132 0x48, 0x10, 0x50, 0x0A, 0x05, 0x08, 0x98, 0x01, 0x10, 0x12, 0x12, 0x02,
133 0x10, 0x58, 0x12, 0x04, 0x08, 0x70, 0x10, 0x58, 0x12, 0x05, 0x08, 0xC8,
134 0x01, 0x10, 0x38, 0x18, 0x21, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34,
135 0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x65,
138 0x29, 0x8C, 0x9B, 0x00, 0x00, 0x03, 0x60, 0x40, 0x7A, 0x0E, 0x08, 0x00,
139 0x40, 0x00, 0x20, 0x00, 0x21, 0x22, 0x9A, 0x3D, 0x4F, 0x50, 0x40, 0x0C,
140 0x3B, 0xC7, 0x9B, 0xB2, 0x21, 0x0E, 0xE9, 0x15, 0x98, 0x7A, 0x7C, 0x5D,
141 0xC9, 0x14, 0xE1, 0x42, 0x41, 0x94, 0xA6, 0x32, 0x6C, 0x42, 0x5A, 0x68,
142 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xF1, 0x20, 0x5F, 0x0D, 0x00,
143 0x00, 0x02, 0x41, 0x15, 0x42, 0x08, 0x20, 0x00, 0x40, 0x00, 0x00, 0x02,
144 0x40, 0x00, 0x20, 0x00, 0x22, 0x3D, 0x23, 0x10, 0x86, 0x03, 0x96, 0x54,
145 0x11, 0x16, 0x5F, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0xF1, 0x20, 0x5F,
146 0x0D, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x07,
147 0xD4, 0xCB, 0x6E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x00,
148 0x21, 0x18, 0x46, 0x82, 0xEE, 0x48, 0xA7, 0x0A, 0x12, 0x00, 0xFA, 0x99,
149 0x6D, 0xC0};
150
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700151} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800152
Allie Woodfdf00512015-03-02 13:34:55 -0800153class DeltaPerformerTest : public ::testing::Test {
Sen Jiang2d528b42015-09-25 11:18:12 -0700154 protected:
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700155 void SetUp() override {
156 install_plan_.source_slot = 0;
157 install_plan_.target_slot = 1;
Alex Deymo542c19b2015-12-03 07:43:31 -0300158 EXPECT_CALL(mock_delegate_, ShouldCancel(_))
159 .WillRepeatedly(testing::Return(false));
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700160 }
Allie Woodfdf00512015-03-02 13:34:55 -0800161
Sen Jiang2d528b42015-09-25 11:18:12 -0700162 // Test helper placed where it can easily be friended from DeltaPerformer.
163 void RunManifestValidation(const DeltaArchiveManifest& manifest,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800164 uint64_t major_version,
Alex Deymo64d98782016-02-05 18:03:48 -0800165 InstallPayloadType payload_type,
Sen Jiang2d528b42015-09-25 11:18:12 -0700166 ErrorCode expected) {
Sen Jiangcdd52062017-05-18 15:33:10 -0700167 payload_.type = payload_type;
Allie Woodfdf00512015-03-02 13:34:55 -0800168
169 // The Manifest we are validating.
Sen Jiang2d528b42015-09-25 11:18:12 -0700170 performer_.manifest_.CopyFrom(manifest);
Sen Jiang3e728fe2015-11-05 11:37:23 -0800171 performer_.major_payload_version_ = major_version;
Allie Woodfdf00512015-03-02 13:34:55 -0800172
Sen Jiang2d528b42015-09-25 11:18:12 -0700173 EXPECT_EQ(expected, performer_.ValidateManifest());
Allie Woodfdf00512015-03-02 13:34:55 -0800174 }
175
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700176 brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
177 const vector<AnnotatedOperation>& aops,
Sen Jiang889c65d2015-11-17 15:04:02 -0800178 bool sign_payload) {
Sen Jiangf1236632018-05-11 16:03:23 -0700179 return GeneratePayload(blob_data,
180 aops,
181 sign_payload,
182 kMaxSupportedMajorPayloadVersion,
183 kMaxSupportedMinorPayloadVersion);
Sen Jiang889c65d2015-11-17 15:04:02 -0800184 }
185
186 brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
187 const vector<AnnotatedOperation>& aops,
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700188 bool sign_payload,
Sen Jiang76bfa742015-10-12 17:13:26 -0700189 uint64_t major_version,
190 uint32_t minor_version) {
Sen Jiang0779a152018-07-02 17:34:56 -0700191 test_utils::ScopedTempFile blob_file("Blob-XXXXXX");
192 EXPECT_TRUE(test_utils::WriteFileVector(blob_file.path(), blob_data));
Sen Jiangd78b3892015-09-25 15:19:31 -0700193
194 PayloadGenerationConfig config;
Alex Deymoa4073ef2016-03-22 23:40:53 -0700195 config.version.major = major_version;
196 config.version.minor = minor_version;
Sen Jiangd78b3892015-09-25 15:19:31 -0700197
198 PayloadFile payload;
199 EXPECT_TRUE(payload.Init(config));
200
Tudor Brindusdda79e22018-06-28 18:03:21 -0700201 PartitionConfig old_part(kPartitionNameRoot);
Alex Deymo64d98782016-02-05 18:03:48 -0800202 if (minor_version != kFullPayloadMinorVersion) {
203 // When generating a delta payload we need to include the old partition
204 // information to mark it as a delta payload.
205 old_part.path = "/dev/null";
206 old_part.size = 0;
207 }
Tudor Brindusdda79e22018-06-28 18:03:21 -0700208 PartitionConfig new_part(kPartitionNameRoot);
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700209 new_part.path = "/dev/zero";
210 new_part.size = 1234;
Sen Jiang981eb112015-08-25 17:03:18 -0700211
212 payload.AddPartition(old_part, new_part, aops);
Sen Jiangd78b3892015-09-25 15:19:31 -0700213
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700214 // We include a kernel partition without operations.
Tudor Brindusdda79e22018-06-28 18:03:21 -0700215 old_part.name = kPartitionNameKernel;
216 new_part.name = kPartitionNameKernel;
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700217 new_part.size = 0;
218 payload.AddPartition(old_part, new_part, {});
219
Sen Jiang0779a152018-07-02 17:34:56 -0700220 test_utils::ScopedTempFile payload_file("Payload-XXXXXX");
Sen Jiang260f03b2016-03-21 15:34:58 -0700221 string private_key =
222 sign_payload ? GetBuildArtifactsPath(kUnittestPrivateKeyPath) : "";
Sen Jiang0779a152018-07-02 17:34:56 -0700223 EXPECT_TRUE(payload.WritePayload(payload_file.path(),
224 blob_file.path(),
225 private_key,
226 &payload_.metadata_size));
Sen Jiangd78b3892015-09-25 15:19:31 -0700227
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700228 brillo::Blob payload_data;
Sen Jiang0779a152018-07-02 17:34:56 -0700229 EXPECT_TRUE(utils::ReadFile(payload_file.path(), &payload_data));
Sen Jiangd78b3892015-09-25 15:19:31 -0700230 return payload_data;
231 }
Allie Woodfdf00512015-03-02 13:34:55 -0800232
Alex Deymo51c264e2016-11-04 15:49:53 -0700233 brillo::Blob GenerateSourceCopyPayload(const brillo::Blob& copied_data,
234 bool add_hash) {
235 PayloadGenerationConfig config;
236 const uint64_t kDefaultBlockSize = config.block_size;
237 EXPECT_EQ(0U, copied_data.size() % kDefaultBlockSize);
238 uint64_t num_blocks = copied_data.size() / kDefaultBlockSize;
239 AnnotatedOperation aop;
240 *(aop.op.add_src_extents()) = ExtentForRange(0, num_blocks);
241 *(aop.op.add_dst_extents()) = ExtentForRange(0, num_blocks);
242 aop.op.set_type(InstallOperation::SOURCE_COPY);
243 brillo::Blob src_hash;
244 EXPECT_TRUE(HashCalculator::RawHashOfData(copied_data, &src_hash));
245 if (add_hash)
246 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
247
248 return GeneratePayload(brillo::Blob(), {aop}, false);
249 }
250
Sen Jiang2d528b42015-09-25 11:18:12 -0700251 // Apply |payload_data| on partition specified in |source_path|.
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800252 // Expect result of performer_.Write() to be |expect_success|.
253 // Returns the result of the payload application.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700254 brillo::Blob ApplyPayload(const brillo::Blob& payload_data,
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800255 const string& source_path,
256 bool expect_success) {
257 return ApplyPayloadToData(payload_data, source_path, brillo::Blob(),
258 expect_success);
Alex Deymo79715ad2015-10-02 14:27:53 -0700259 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800260
Alex Deymo79715ad2015-10-02 14:27:53 -0700261 // Apply the payload provided in |payload_data| reading from the |source_path|
262 // file and writing the contents to a new partition. The existing data in the
263 // new target file are set to |target_data| before applying the payload.
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800264 // Expect result of performer_.Write() to be |expect_success|.
Alex Deymo79715ad2015-10-02 14:27:53 -0700265 // Returns the result of the payload application.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700266 brillo::Blob ApplyPayloadToData(const brillo::Blob& payload_data,
267 const string& source_path,
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800268 const brillo::Blob& target_data,
269 bool expect_success) {
Sen Jiang0779a152018-07-02 17:34:56 -0700270 test_utils::ScopedTempFile new_part("Partition-XXXXXX");
271 EXPECT_TRUE(test_utils::WriteFileVector(new_part.path(), target_data));
Alex Deymo79715ad2015-10-02 14:27:53 -0700272
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700273 // We installed the operations only in the rootfs partition, but the
274 // delta performer needs to access all the partitions.
Alex Deymo542c19b2015-12-03 07:43:31 -0300275 fake_boot_control_.SetPartitionDevice(
Sen Jiang456853f2018-08-13 15:41:43 -0700276 kPartitionNameRoot, install_plan_.target_slot, new_part.path());
Alex Deymo542c19b2015-12-03 07:43:31 -0300277 fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700278 kPartitionNameRoot, install_plan_.source_slot, source_path);
Alex Deymo542c19b2015-12-03 07:43:31 -0300279 fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700280 kPartitionNameKernel, install_plan_.target_slot, "/dev/null");
Alex Deymo542c19b2015-12-03 07:43:31 -0300281 fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700282 kPartitionNameKernel, install_plan_.source_slot, "/dev/null");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800283
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800284 EXPECT_EQ(expect_success,
285 performer_.Write(payload_data.data(), payload_data.size()));
Sen Jiang2d528b42015-09-25 11:18:12 -0700286 EXPECT_EQ(0, performer_.Close());
287
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700288 brillo::Blob partition_data;
Sen Jiang0779a152018-07-02 17:34:56 -0700289 EXPECT_TRUE(utils::ReadFile(new_part.path(), &partition_data));
Sen Jiang2d528b42015-09-25 11:18:12 -0700290 return partition_data;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800291 }
292
Sen Jiang2d528b42015-09-25 11:18:12 -0700293 // Calls delta performer's Write method by pretending to pass in bytes from a
294 // delta file whose metadata size is actual_metadata_size and tests if all
295 // checks are correctly performed if the install plan contains
296 // expected_metadata_size and that the result of the parsing are as per
297 // hash_checks_mandatory flag.
298 void DoMetadataSizeTest(uint64_t expected_metadata_size,
299 uint64_t actual_metadata_size,
300 bool hash_checks_mandatory) {
301 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800302
Sen Jiang2d528b42015-09-25 11:18:12 -0700303 // Set a valid magic string and version number 1.
304 EXPECT_TRUE(performer_.Write("CrAU", 4));
305 uint64_t version = htobe64(kChromeOSMajorPayloadVersion);
306 EXPECT_TRUE(performer_.Write(&version, 8));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800307
Sen Jiang0affc2c2017-02-10 15:55:05 -0800308 payload_.metadata_size = expected_metadata_size;
Sen Jiang2d528b42015-09-25 11:18:12 -0700309 ErrorCode error_code;
310 // When filling in size in manifest, exclude the size of the 20-byte header.
311 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
312 bool result = performer_.Write(&size_in_manifest, 8, &error_code);
313 if (expected_metadata_size == actual_metadata_size ||
314 !hash_checks_mandatory) {
315 EXPECT_TRUE(result);
316 } else {
317 EXPECT_FALSE(result);
318 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
319 }
Sen Jiangd78b3892015-09-25 15:19:31 -0700320
Sen Jiang2d528b42015-09-25 11:18:12 -0700321 EXPECT_LT(performer_.Close(), 0);
322 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800323
Sen Jiang2d528b42015-09-25 11:18:12 -0700324 // Generates a valid delta file but tests the delta performer by suppling
325 // different metadata signatures as per metadata_signature_test flag and
326 // sees if the result of the parsing are as per hash_checks_mandatory flag.
327 void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
328 bool sign_payload,
329 bool hash_checks_mandatory) {
Sen Jiang2d528b42015-09-25 11:18:12 -0700330 // Loads the payload and parses the manifest.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700331 brillo::Blob payload = GeneratePayload(brillo::Blob(),
Sen Jiang2d528b42015-09-25 11:18:12 -0700332 vector<AnnotatedOperation>(), sign_payload,
Sen Jiang76bfa742015-10-12 17:13:26 -0700333 kChromeOSMajorPayloadVersion, kFullPayloadMinorVersion);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800334
Sen Jiang2d528b42015-09-25 11:18:12 -0700335 LOG(INFO) << "Payload size: " << payload.size();
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800336
Sen Jiang2d528b42015-09-25 11:18:12 -0700337 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800338
Sen Jiang9c89e842018-02-02 13:51:21 -0800339 MetadataParseResult expected_result, actual_result;
Sen Jiang2d528b42015-09-25 11:18:12 -0700340 ErrorCode expected_error, actual_error;
341
342 // Fill up the metadata signature in install plan according to the test.
343 switch (metadata_signature_test) {
344 case kEmptyMetadataSignature:
Sen Jiang0affc2c2017-02-10 15:55:05 -0800345 payload_.metadata_signature.clear();
Sen Jiang9c89e842018-02-02 13:51:21 -0800346 expected_result = MetadataParseResult::kError;
Sen Jiang2d528b42015-09-25 11:18:12 -0700347 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
348 break;
349
350 case kInvalidMetadataSignature:
Sen Jiang0affc2c2017-02-10 15:55:05 -0800351 payload_.metadata_signature = kBogusMetadataSignature1;
Sen Jiang9c89e842018-02-02 13:51:21 -0800352 expected_result = MetadataParseResult::kError;
Sen Jiang2d528b42015-09-25 11:18:12 -0700353 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
354 break;
355
356 case kValidMetadataSignature:
357 default:
358 // Set the install plan's metadata size to be the same as the one
359 // in the manifest so that we pass the metadata size checks. Only
360 // then we can get to manifest signature checks.
361 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
362 payload.data(),
Sen Jiang0affc2c2017-02-10 15:55:05 -0800363 payload_.metadata_size,
Sen Jiang260f03b2016-03-21 15:34:58 -0700364 GetBuildArtifactsPath(kUnittestPrivateKeyPath),
Sen Jiang0affc2c2017-02-10 15:55:05 -0800365 &payload_.metadata_signature));
366 EXPECT_FALSE(payload_.metadata_signature.empty());
Sen Jiang9c89e842018-02-02 13:51:21 -0800367 expected_result = MetadataParseResult::kSuccess;
Sen Jiang2d528b42015-09-25 11:18:12 -0700368 expected_error = ErrorCode::kSuccess;
369 break;
370 }
371
372 // Ignore the expected result/error if hash checks are not mandatory.
373 if (!hash_checks_mandatory) {
Sen Jiang9c89e842018-02-02 13:51:21 -0800374 expected_result = MetadataParseResult::kSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700375 expected_error = ErrorCode::kSuccess;
Sen Jiang2d528b42015-09-25 11:18:12 -0700376 }
377
378 // Use the public key corresponding to the private key used above to
379 // sign the metadata.
Sen Jiang260f03b2016-03-21 15:34:58 -0700380 string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath);
381 EXPECT_TRUE(utils::FileExists(public_key_path.c_str()));
382 performer_.set_public_key_path(public_key_path);
Sen Jiang2d528b42015-09-25 11:18:12 -0700383
384 // Init actual_error with an invalid value so that we make sure
385 // ParsePayloadMetadata properly populates it in all cases.
386 actual_error = ErrorCode::kUmaReportedMax;
387 actual_result = performer_.ParsePayloadMetadata(payload, &actual_error);
388
389 EXPECT_EQ(expected_result, actual_result);
390 EXPECT_EQ(expected_error, actual_error);
391
392 // Check that the parsed metadata size is what's expected. This test
393 // implicitly confirms that the metadata signature is valid, if required.
Sen Jiang9c89e842018-02-02 13:51:21 -0800394 EXPECT_EQ(payload_.metadata_size, performer_.metadata_size_);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800395 }
396
Alex Deymo51c264e2016-11-04 15:49:53 -0700397 // Helper function to pretend that the ECC file descriptor was already opened.
398 // Returns a pointer to the created file descriptor.
399 FakeFileDescriptor* SetFakeECCFile(size_t size) {
400 EXPECT_FALSE(performer_.source_ecc_fd_) << "source_ecc_fd_ already open.";
401 FakeFileDescriptor* ret = new FakeFileDescriptor();
402 fake_ecc_fd_.reset(ret);
403 // Call open to simulate it was already opened.
404 ret->Open("", 0);
405 ret->SetFileSize(size);
406 performer_.source_ecc_fd_ = fake_ecc_fd_;
407 return ret;
408 }
409
410 uint64_t GetSourceEccRecoveredFailures() const {
411 return performer_.source_ecc_recovered_failures_;
412 }
413
Sen Jiang2d528b42015-09-25 11:18:12 -0700414 FakePrefs prefs_;
415 InstallPlan install_plan_;
Sen Jiang0affc2c2017-02-10 15:55:05 -0800416 InstallPlan::Payload payload_;
Alex Deymo542c19b2015-12-03 07:43:31 -0300417 FakeBootControl fake_boot_control_;
418 FakeHardware fake_hardware_;
419 MockDownloadActionDelegate mock_delegate_;
Alex Deymo51c264e2016-11-04 15:49:53 -0700420 FileDescriptorPtr fake_ecc_fd_;
Sen Jiang0affc2c2017-02-10 15:55:05 -0800421 DeltaPerformer performer_{&prefs_,
422 &fake_boot_control_,
423 &fake_hardware_,
424 &mock_delegate_,
425 &install_plan_,
Sen Jiang44906962018-01-08 17:39:04 -0800426 &payload_,
Amin Hassanied37d682018-04-06 13:22:00 -0700427 false /* interactive*/};
Sen Jiang2d528b42015-09-25 11:18:12 -0700428};
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800429
Sen Jiang2d528b42015-09-25 11:18:12 -0700430TEST_F(DeltaPerformerTest, FullPayloadWriteTest) {
Sen Jiangcdd52062017-05-18 15:33:10 -0700431 payload_.type = InstallPayloadType::kFull;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700432 brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
433 std::end(kRandomString));
Sen Jiang2d528b42015-09-25 11:18:12 -0700434 expected_data.resize(4096); // block size
435 vector<AnnotatedOperation> aops;
436 AnnotatedOperation aop;
437 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
438 aop.op.set_data_offset(0);
439 aop.op.set_data_length(expected_data.size());
440 aop.op.set_type(InstallOperation::REPLACE);
441 aops.push_back(aop);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800442
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700443 brillo::Blob payload_data = GeneratePayload(expected_data, aops, false,
Sen Jiang76bfa742015-10-12 17:13:26 -0700444 kChromeOSMajorPayloadVersion, kFullPayloadMinorVersion);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800445
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800446 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800447}
448
Alex Deymo542c19b2015-12-03 07:43:31 -0300449TEST_F(DeltaPerformerTest, ShouldCancelTest) {
Sen Jiangcdd52062017-05-18 15:33:10 -0700450 payload_.type = InstallPayloadType::kFull;
Alex Deymo542c19b2015-12-03 07:43:31 -0300451 brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
452 std::end(kRandomString));
453 expected_data.resize(4096); // block size
454 vector<AnnotatedOperation> aops;
455 AnnotatedOperation aop;
456 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
457 aop.op.set_data_offset(0);
458 aop.op.set_data_length(expected_data.size());
459 aop.op.set_type(InstallOperation::REPLACE);
460 aops.push_back(aop);
461
462 brillo::Blob payload_data = GeneratePayload(expected_data, aops, false,
463 kChromeOSMajorPayloadVersion, kFullPayloadMinorVersion);
464
465 testing::Mock::VerifyAndClearExpectations(&mock_delegate_);
466 EXPECT_CALL(mock_delegate_, ShouldCancel(_))
467 .WillOnce(
Ben Chan672c1f52017-10-23 15:41:39 -0700468 testing::DoAll(testing::SetArgPointee<0>(ErrorCode::kError),
Alex Deymo542c19b2015-12-03 07:43:31 -0300469 testing::Return(true)));
470
471 ApplyPayload(payload_data, "/dev/null", false);
472}
473
Sen Jiang2d528b42015-09-25 11:18:12 -0700474TEST_F(DeltaPerformerTest, ReplaceOperationTest) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700475 brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
476 std::end(kRandomString));
Sen Jiang2d528b42015-09-25 11:18:12 -0700477 expected_data.resize(4096); // block size
478 vector<AnnotatedOperation> aops;
479 AnnotatedOperation aop;
480 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
481 aop.op.set_data_offset(0);
482 aop.op.set_data_length(expected_data.size());
483 aop.op.set_type(InstallOperation::REPLACE);
484 aops.push_back(aop);
485
Sen Jiang889c65d2015-11-17 15:04:02 -0800486 brillo::Blob payload_data = GeneratePayload(expected_data, aops, false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700487
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800488 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
Sen Jiang2d528b42015-09-25 11:18:12 -0700489}
490
491TEST_F(DeltaPerformerTest, ReplaceBzOperationTest) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700492 brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
493 std::end(kRandomString));
Sen Jiang2d528b42015-09-25 11:18:12 -0700494 expected_data.resize(4096); // block size
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700495 brillo::Blob bz_data;
Sen Jiang2d528b42015-09-25 11:18:12 -0700496 EXPECT_TRUE(BzipCompress(expected_data, &bz_data));
497
498 vector<AnnotatedOperation> aops;
499 AnnotatedOperation aop;
500 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
501 aop.op.set_data_offset(0);
502 aop.op.set_data_length(bz_data.size());
503 aop.op.set_type(InstallOperation::REPLACE_BZ);
504 aops.push_back(aop);
505
Sen Jiang889c65d2015-11-17 15:04:02 -0800506 brillo::Blob payload_data = GeneratePayload(bz_data, aops, false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700507
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800508 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
Sen Jiang2d528b42015-09-25 11:18:12 -0700509}
510
Alex Deymo2d621a32015-10-01 11:09:01 -0700511TEST_F(DeltaPerformerTest, ReplaceXzOperationTest) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700512 brillo::Blob xz_data(std::begin(kXzCompressedData),
Alex Deymo2d621a32015-10-01 11:09:01 -0700513 std::end(kXzCompressedData));
Sen Jiang5e1af982018-11-01 15:01:45 -0700514 // The compressed xz data contains a single "a" and padded with zero for the
515 // rest of the block.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700516 brillo::Blob expected_data = brillo::Blob(4096, 0);
Alex Deymo2d621a32015-10-01 11:09:01 -0700517 expected_data[0] = 'a';
518
519 AnnotatedOperation aop;
520 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
521 aop.op.set_data_offset(0);
522 aop.op.set_data_length(xz_data.size());
523 aop.op.set_type(InstallOperation::REPLACE_XZ);
524 vector<AnnotatedOperation> aops = {aop};
525
Sen Jiang889c65d2015-11-17 15:04:02 -0800526 brillo::Blob payload_data = GeneratePayload(xz_data, aops, false);
Alex Deymo2d621a32015-10-01 11:09:01 -0700527
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800528 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
Alex Deymo2d621a32015-10-01 11:09:01 -0700529}
530
Alex Deymo79715ad2015-10-02 14:27:53 -0700531TEST_F(DeltaPerformerTest, ZeroOperationTest) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700532 brillo::Blob existing_data = brillo::Blob(4096 * 10, 'a');
533 brillo::Blob expected_data = existing_data;
Alex Deymo79715ad2015-10-02 14:27:53 -0700534 // Blocks 4, 5 and 7 should have zeros instead of 'a' after the operation is
535 // applied.
536 std::fill(expected_data.data() + 4096 * 4, expected_data.data() + 4096 * 6,
537 0);
538 std::fill(expected_data.data() + 4096 * 7, expected_data.data() + 4096 * 8,
539 0);
540
541 AnnotatedOperation aop;
542 *(aop.op.add_dst_extents()) = ExtentForRange(4, 2);
543 *(aop.op.add_dst_extents()) = ExtentForRange(7, 1);
544 aop.op.set_type(InstallOperation::ZERO);
545 vector<AnnotatedOperation> aops = {aop};
546
Sen Jiang889c65d2015-11-17 15:04:02 -0800547 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), aops, false);
Alex Deymo79715ad2015-10-02 14:27:53 -0700548
549 EXPECT_EQ(expected_data,
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800550 ApplyPayloadToData(payload_data, "/dev/null", existing_data, true));
Alex Deymo79715ad2015-10-02 14:27:53 -0700551}
552
Sen Jiang2d528b42015-09-25 11:18:12 -0700553TEST_F(DeltaPerformerTest, SourceCopyOperationTest) {
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800554 brillo::Blob expected_data(std::begin(kRandomString),
555 std::end(kRandomString));
Sen Jiang2d528b42015-09-25 11:18:12 -0700556 expected_data.resize(4096); // block size
Sen Jiang2d528b42015-09-25 11:18:12 -0700557 AnnotatedOperation aop;
558 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
559 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
560 aop.op.set_type(InstallOperation::SOURCE_COPY);
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800561 brillo::Blob src_hash;
562 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
563 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
Sen Jiang2d528b42015-09-25 11:18:12 -0700564
Sen Jiang889c65d2015-11-17 15:04:02 -0800565 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
566
Sen Jiang0779a152018-07-02 17:34:56 -0700567 test_utils::ScopedTempFile source("Source-XXXXXX");
568 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
Sen Jiang2d528b42015-09-25 11:18:12 -0700569
Sen Jiang0779a152018-07-02 17:34:56 -0700570 EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800571}
572
Amin Hassani02855c22017-09-06 22:34:50 -0700573TEST_F(DeltaPerformerTest, PuffdiffOperationTest) {
574 AnnotatedOperation aop;
575 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
576 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
577 brillo::Blob puffdiff_payload(std::begin(puffdiff_patch),
578 std::end(puffdiff_patch));
579 aop.op.set_data_offset(0);
580 aop.op.set_data_length(puffdiff_payload.size());
581 aop.op.set_type(InstallOperation::PUFFDIFF);
582 brillo::Blob src(std::begin(src_deflates), std::end(src_deflates));
583 src.resize(4096); // block size
584 brillo::Blob src_hash;
585 EXPECT_TRUE(HashCalculator::RawHashOfData(src, &src_hash));
586 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
587
588 brillo::Blob payload_data = GeneratePayload(puffdiff_payload, {aop}, false);
589
Sen Jiang0779a152018-07-02 17:34:56 -0700590 test_utils::ScopedTempFile source("Source-XXXXXX");
591 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), src));
Amin Hassani02855c22017-09-06 22:34:50 -0700592
593 brillo::Blob dst(std::begin(dst_deflates), std::end(dst_deflates));
Sen Jiang0779a152018-07-02 17:34:56 -0700594 EXPECT_EQ(dst, ApplyPayload(payload_data, source.path(), true));
Amin Hassani02855c22017-09-06 22:34:50 -0700595}
596
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800597TEST_F(DeltaPerformerTest, SourceHashMismatchTest) {
598 brillo::Blob expected_data = {'f', 'o', 'o'};
599 brillo::Blob actual_data = {'b', 'a', 'r'};
600 expected_data.resize(4096); // block size
601 actual_data.resize(4096); // block size
602
603 AnnotatedOperation aop;
604 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
605 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
606 aop.op.set_type(InstallOperation::SOURCE_COPY);
607 brillo::Blob src_hash;
608 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
609 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
610
Sen Jiang889c65d2015-11-17 15:04:02 -0800611 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
612
Sen Jiang0779a152018-07-02 17:34:56 -0700613 test_utils::ScopedTempFile source("Source-XXXXXX");
614 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), actual_data));
Sen Jiang2ec4aab2015-11-13 15:04:03 -0800615
Sen Jiang0779a152018-07-02 17:34:56 -0700616 EXPECT_EQ(actual_data, ApplyPayload(payload_data, source.path(), false));
Sen Jiang2d528b42015-09-25 11:18:12 -0700617}
618
Alex Deymo51c264e2016-11-04 15:49:53 -0700619// Test that the error-corrected file descriptor is used to read the partition
620// since the source partition doesn't match the operation hash.
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700621TEST_F(DeltaPerformerTest, ErrorCorrectionSourceCopyFallbackTest) {
Sen Jiang0779a152018-07-02 17:34:56 -0700622 constexpr size_t kCopyOperationSize = 4 * 4096;
623 test_utils::ScopedTempFile source("Source-XXXXXX");
Alex Deymo51c264e2016-11-04 15:49:53 -0700624 // Write invalid data to the source image, which doesn't match the expected
625 // hash.
626 brillo::Blob invalid_data(kCopyOperationSize, 0x55);
Sen Jiang0779a152018-07-02 17:34:56 -0700627 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), invalid_data));
Alex Deymo51c264e2016-11-04 15:49:53 -0700628
629 // Setup the fec file descriptor as the fake stream, which matches
630 // |expected_data|.
631 FakeFileDescriptor* fake_fec = SetFakeECCFile(kCopyOperationSize);
632 brillo::Blob expected_data = FakeFileDescriptorData(kCopyOperationSize);
633
634 brillo::Blob payload_data = GenerateSourceCopyPayload(expected_data, true);
Sen Jiang0779a152018-07-02 17:34:56 -0700635 EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
Alex Deymo51c264e2016-11-04 15:49:53 -0700636 // Verify that the fake_fec was actually used.
637 EXPECT_EQ(1U, fake_fec->GetReadOps().size());
638 EXPECT_EQ(1U, GetSourceEccRecoveredFailures());
639}
640
641// Test that the error-corrected file descriptor is used to read a partition
642// when no hash is available for SOURCE_COPY but it falls back to the normal
643// file descriptor when the size of the error corrected one is too small.
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700644TEST_F(DeltaPerformerTest, ErrorCorrectionSourceCopyWhenNoHashFallbackTest) {
Sen Jiang0779a152018-07-02 17:34:56 -0700645 constexpr size_t kCopyOperationSize = 4 * 4096;
646 test_utils::ScopedTempFile source("Source-XXXXXX");
Alex Deymo51c264e2016-11-04 15:49:53 -0700647 // Setup the source path with the right expected data.
648 brillo::Blob expected_data = FakeFileDescriptorData(kCopyOperationSize);
Sen Jiang0779a152018-07-02 17:34:56 -0700649 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
Alex Deymo51c264e2016-11-04 15:49:53 -0700650
651 // Setup the fec file descriptor as the fake stream, with smaller data than
652 // the expected.
653 FakeFileDescriptor* fake_fec = SetFakeECCFile(kCopyOperationSize / 2);
654
655 // The payload operation doesn't include an operation hash.
656 brillo::Blob payload_data = GenerateSourceCopyPayload(expected_data, false);
Sen Jiang0779a152018-07-02 17:34:56 -0700657 EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
Alex Deymo51c264e2016-11-04 15:49:53 -0700658 // Verify that the fake_fec was attempted to be used. Since the file
659 // descriptor is shorter it can actually do more than one read to realize it
660 // reached the EOF.
661 EXPECT_LE(1U, fake_fec->GetReadOps().size());
662 // This fallback doesn't count as an error-corrected operation since the
663 // operation hash was not available.
664 EXPECT_EQ(0U, GetSourceEccRecoveredFailures());
665}
666
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700667TEST_F(DeltaPerformerTest, ChooseSourceFDTest) {
Sen Jiang0779a152018-07-02 17:34:56 -0700668 constexpr size_t kSourceSize = 4 * 4096;
669 test_utils::ScopedTempFile source("Source-XXXXXX");
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700670 // Write invalid data to the source image, which doesn't match the expected
671 // hash.
672 brillo::Blob invalid_data(kSourceSize, 0x55);
Sen Jiang0779a152018-07-02 17:34:56 -0700673 EXPECT_TRUE(test_utils::WriteFileVector(source.path(), invalid_data));
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700674
675 performer_.source_fd_ = std::make_shared<EintrSafeFileDescriptor>();
Sen Jiang0779a152018-07-02 17:34:56 -0700676 performer_.source_fd_->Open(source.path().c_str(), O_RDONLY);
Sen Jiang77ab7bd2018-05-22 17:24:23 -0700677 performer_.block_size_ = 4096;
678
679 // Setup the fec file descriptor as the fake stream, which matches
680 // |expected_data|.
681 FakeFileDescriptor* fake_fec = SetFakeECCFile(kSourceSize);
682 brillo::Blob expected_data = FakeFileDescriptorData(kSourceSize);
683
684 InstallOperation op;
685 *(op.add_src_extents()) = ExtentForRange(0, kSourceSize / 4096);
686 brillo::Blob src_hash;
687 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
688 op.set_src_sha256_hash(src_hash.data(), src_hash.size());
689
690 ErrorCode error = ErrorCode::kSuccess;
691 EXPECT_EQ(performer_.source_ecc_fd_, performer_.ChooseSourceFD(op, &error));
692 EXPECT_EQ(ErrorCode::kSuccess, error);
693 // Verify that the fake_fec was actually used.
694 EXPECT_EQ(1U, fake_fec->GetReadOps().size());
695 EXPECT_EQ(1U, GetSourceEccRecoveredFailures());
696}
697
Sen Jiang2d528b42015-09-25 11:18:12 -0700698TEST_F(DeltaPerformerTest, ExtentsToByteStringTest) {
Allie Wood56873452015-03-27 17:48:40 -0700699 uint64_t test[] = {1, 1, 4, 2, 0, 1};
Alex Vakulenko0103c362016-01-20 07:56:15 -0800700 static_assert(arraysize(test) % 2 == 0, "Array size uneven");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800701 const uint64_t block_size = 4096;
Allie Wood56873452015-03-27 17:48:40 -0700702 const uint64_t file_length = 4 * block_size - 13;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800703
704 google::protobuf::RepeatedPtrField<Extent> extents;
705 for (size_t i = 0; i < arraysize(test); i += 2) {
Sen Jiang2d528b42015-09-25 11:18:12 -0700706 *(extents.Add()) = ExtentForRange(test[i], test[i + 1]);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800707 }
708
Allie Wood56873452015-03-27 17:48:40 -0700709 string expected_output = "4096:4096,16384:8192,0:4083";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800710 string actual_output;
711 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
712 block_size,
713 file_length,
714 &actual_output));
715 EXPECT_EQ(expected_output, actual_output);
716}
Darin Petkov68c10d12010-10-14 09:24:37 -0700717
Sen Jiang2d528b42015-09-25 11:18:12 -0700718TEST_F(DeltaPerformerTest, ValidateManifestFullGoodTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800719 // The Manifest we are validating.
720 DeltaArchiveManifest manifest;
721 manifest.mutable_new_kernel_info();
722 manifest.mutable_new_rootfs_info();
Alex Deymocbf09892015-09-11 16:13:16 -0700723 manifest.set_minor_version(kFullPayloadMinorVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800724
Alex Deymo64d98782016-02-05 18:03:48 -0800725 RunManifestValidation(manifest,
726 kChromeOSMajorPayloadVersion,
727 InstallPayloadType::kFull,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800728 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800729}
730
Sen Jiang2d528b42015-09-25 11:18:12 -0700731TEST_F(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800732 // The Manifest we are validating.
733 DeltaArchiveManifest manifest;
734 manifest.mutable_old_kernel_info();
735 manifest.mutable_old_rootfs_info();
736 manifest.mutable_new_kernel_info();
737 manifest.mutable_new_rootfs_info();
Sen Jiangf1236632018-05-11 16:03:23 -0700738 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
739
740 RunManifestValidation(manifest,
741 kChromeOSMajorPayloadVersion,
742 InstallPayloadType::kDelta,
743 ErrorCode::kSuccess);
744}
745
746TEST_F(DeltaPerformerTest, ValidateManifestDeltaMinGoodTest) {
747 // The Manifest we are validating.
748 DeltaArchiveManifest manifest;
749 manifest.mutable_old_kernel_info();
750 manifest.mutable_old_rootfs_info();
751 manifest.mutable_new_kernel_info();
752 manifest.mutable_new_rootfs_info();
753 manifest.set_minor_version(kMinSupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800754
Alex Deymo64d98782016-02-05 18:03:48 -0800755 RunManifestValidation(manifest,
756 kChromeOSMajorPayloadVersion,
757 InstallPayloadType::kDelta,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800758 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800759}
760
Sen Jiang2d528b42015-09-25 11:18:12 -0700761TEST_F(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800762 // The Manifest we are validating.
763 DeltaArchiveManifest manifest;
764
Alex Deymo64d98782016-02-05 18:03:48 -0800765 RunManifestValidation(manifest,
Sen Jiangf1236632018-05-11 16:03:23 -0700766 kMaxSupportedMajorPayloadVersion,
Alex Deymo64d98782016-02-05 18:03:48 -0800767 InstallPayloadType::kFull,
768 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800769}
770
Sen Jiang2d528b42015-09-25 11:18:12 -0700771TEST_F(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800772 // The Manifest we are validating.
773 DeltaArchiveManifest manifest;
Alex Deymo64d98782016-02-05 18:03:48 -0800774 // Add an empty old_rootfs_info() to trick the DeltaPerformer into think that
775 // this is a delta payload manifest with a missing minor version.
776 manifest.mutable_old_rootfs_info();
Don Garrettb8dd1d92013-11-22 17:40:02 -0800777
Alex Deymo64d98782016-02-05 18:03:48 -0800778 RunManifestValidation(manifest,
Sen Jiangf1236632018-05-11 16:03:23 -0700779 kMaxSupportedMajorPayloadVersion,
Alex Deymo64d98782016-02-05 18:03:48 -0800780 InstallPayloadType::kDelta,
781 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800782}
783
Sen Jiang2d528b42015-09-25 11:18:12 -0700784TEST_F(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800785 // The Manifest we are validating.
786 DeltaArchiveManifest manifest;
787 manifest.mutable_old_kernel_info();
788 manifest.mutable_new_kernel_info();
789 manifest.mutable_new_rootfs_info();
Sen Jiangf1236632018-05-11 16:03:23 -0700790 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800791
Alex Deymo64d98782016-02-05 18:03:48 -0800792 RunManifestValidation(manifest,
793 kChromeOSMajorPayloadVersion,
794 InstallPayloadType::kFull,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800795 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800796}
797
Sen Jiang2d528b42015-09-25 11:18:12 -0700798TEST_F(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800799 // The Manifest we are validating.
800 DeltaArchiveManifest manifest;
801 manifest.mutable_old_rootfs_info();
802 manifest.mutable_new_kernel_info();
803 manifest.mutable_new_rootfs_info();
Sen Jiangf1236632018-05-11 16:03:23 -0700804 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800805
Alex Deymo64d98782016-02-05 18:03:48 -0800806 RunManifestValidation(manifest,
807 kChromeOSMajorPayloadVersion,
808 InstallPayloadType::kFull,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800809 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800810}
811
Sen Jiangc8f6b7a2015-10-21 11:09:59 -0700812TEST_F(DeltaPerformerTest, ValidateManifestFullPartitionUpdateTest) {
813 // The Manifest we are validating.
814 DeltaArchiveManifest manifest;
815 PartitionUpdate* partition = manifest.add_partitions();
816 partition->mutable_old_partition_info();
817 partition->mutable_new_partition_info();
Sen Jiangf1236632018-05-11 16:03:23 -0700818 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion);
Sen Jiangc8f6b7a2015-10-21 11:09:59 -0700819
Alex Deymo64d98782016-02-05 18:03:48 -0800820 RunManifestValidation(manifest,
821 kBrilloMajorPayloadVersion,
822 InstallPayloadType::kFull,
Sen Jiang3e728fe2015-11-05 11:37:23 -0800823 ErrorCode::kPayloadMismatchedType);
Sen Jiangc8f6b7a2015-10-21 11:09:59 -0700824}
825
Sen Jiang2d528b42015-09-25 11:18:12 -0700826TEST_F(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800827 // The Manifest we are validating.
828 DeltaArchiveManifest manifest;
829
830 // Generate a bad version number.
Sen Jiangf1236632018-05-11 16:03:23 -0700831 manifest.set_minor_version(kMaxSupportedMinorPayloadVersion + 10000);
Alex Deymo64d98782016-02-05 18:03:48 -0800832 // Mark the manifest as a delta payload by setting old_rootfs_info.
833 manifest.mutable_old_rootfs_info();
Don Garrettb8dd1d92013-11-22 17:40:02 -0800834
Alex Deymo64d98782016-02-05 18:03:48 -0800835 RunManifestValidation(manifest,
Sen Jiangf1236632018-05-11 16:03:23 -0700836 kMaxSupportedMajorPayloadVersion,
Alex Deymo64d98782016-02-05 18:03:48 -0800837 InstallPayloadType::kDelta,
838 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800839}
840
Sen Jiang5011df62017-06-28 17:13:19 -0700841TEST_F(DeltaPerformerTest, ValidateManifestDowngrade) {
842 // The Manifest we are validating.
843 DeltaArchiveManifest manifest;
844
845 manifest.set_minor_version(kFullPayloadMinorVersion);
846 manifest.set_max_timestamp(1);
847 fake_hardware_.SetBuildTimestamp(2);
848
849 RunManifestValidation(manifest,
Sen Jiangf1236632018-05-11 16:03:23 -0700850 kMaxSupportedMajorPayloadVersion,
Sen Jiang5011df62017-06-28 17:13:19 -0700851 InstallPayloadType::kFull,
852 ErrorCode::kPayloadTimestampError);
853}
854
Sen Jiangb8060e42015-09-24 17:30:50 -0700855TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeTest) {
Eric Caruso4495bfe2018-01-23 16:34:20 -0800856 unsigned int seed = time(nullptr);
Sen Jiangb8060e42015-09-24 17:30:50 -0700857 EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
858
859 uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
860 EXPECT_TRUE(performer_.Write(&major_version, 8));
861
Eric Caruso4495bfe2018-01-23 16:34:20 -0800862 uint64_t manifest_size = rand_r(&seed) % 256;
Sen Jiangb8060e42015-09-24 17:30:50 -0700863 uint64_t manifest_size_be = htobe64(manifest_size);
864 EXPECT_TRUE(performer_.Write(&manifest_size_be, 8));
865
Eric Caruso4495bfe2018-01-23 16:34:20 -0800866 uint32_t metadata_signature_size = rand_r(&seed) % 256;
Sen Jiangb8060e42015-09-24 17:30:50 -0700867 uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
868 EXPECT_TRUE(performer_.Write(&metadata_signature_size_be, 4));
869
870 EXPECT_LT(performer_.Close(), 0);
871
872 EXPECT_TRUE(performer_.IsHeaderParsed());
Sen Jiang9c89e842018-02-02 13:51:21 -0800873 EXPECT_EQ(kBrilloMajorPayloadVersion, performer_.major_payload_version_);
874 EXPECT_EQ(24 + manifest_size, performer_.metadata_size_); // 4 + 8 + 8 + 4
Sen Jiang76bfa742015-10-12 17:13:26 -0700875 EXPECT_EQ(metadata_signature_size, performer_.metadata_signature_size_);
876}
877
Sen Jiang9c89e842018-02-02 13:51:21 -0800878TEST_F(DeltaPerformerTest, BrilloParsePayloadMetadataTest) {
Sen Jiang76bfa742015-10-12 17:13:26 -0700879 brillo::Blob payload_data = GeneratePayload({}, {}, true,
880 kBrilloMajorPayloadVersion,
881 kSourceMinorPayloadVersion);
882 install_plan_.hash_checks_mandatory = true;
Sen Jiang260f03b2016-03-21 15:34:58 -0700883 performer_.set_public_key_path(GetBuildArtifactsPath(kUnittestPublicKeyPath));
Sen Jiang9c89e842018-02-02 13:51:21 -0800884 ErrorCode error;
885 EXPECT_EQ(MetadataParseResult::kSuccess,
886 performer_.ParsePayloadMetadata(payload_data, &error));
887 EXPECT_EQ(ErrorCode::kSuccess, error);
Sen Jiangb8060e42015-09-24 17:30:50 -0700888}
889
Sen Jiang2d528b42015-09-25 11:18:12 -0700890TEST_F(DeltaPerformerTest, BadDeltaMagicTest) {
Sen Jiang2d528b42015-09-25 11:18:12 -0700891 EXPECT_TRUE(performer_.Write("junk", 4));
Sen Jiang2d528b42015-09-25 11:18:12 -0700892 EXPECT_FALSE(performer_.Write("morejunk", 8));
893 EXPECT_LT(performer_.Close(), 0);
Darin Petkov934bb412010-11-18 11:21:35 -0800894}
895
Sen Jiang2d528b42015-09-25 11:18:12 -0700896TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800897 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700898}
899
Sen Jiang2d528b42015-09-25 11:18:12 -0700900TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800901 DoMetadataSizeTest(0, 123456, false);
902}
903
Sen Jiang2d528b42015-09-25 11:18:12 -0700904TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800905 DoMetadataSizeTest(13000, 140000, true);
906}
907
Sen Jiang2d528b42015-09-25 11:18:12 -0700908TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800909 DoMetadataSizeTest(40000, 50000, false);
910}
911
Sen Jiang2d528b42015-09-25 11:18:12 -0700912TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800913 DoMetadataSizeTest(85376, 85376, true);
914}
915
Sen Jiang2d528b42015-09-25 11:18:12 -0700916TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700917 DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800918}
919
Sen Jiang2d528b42015-09-25 11:18:12 -0700920TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700921 DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800922}
923
Sen Jiang2d528b42015-09-25 11:18:12 -0700924TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700925 DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800926}
927
Sen Jiang2d528b42015-09-25 11:18:12 -0700928TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700929 DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800930}
931
Sen Jiang2d528b42015-09-25 11:18:12 -0700932TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700933 DoMetadataSignatureTest(kValidMetadataSignature, false, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800934}
935
Sen Jiang2d528b42015-09-25 11:18:12 -0700936TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700937 DoMetadataSignatureTest(kValidMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800938}
939
Sen Jiang2d528b42015-09-25 11:18:12 -0700940TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700941 DoMetadataSignatureTest(kValidMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800942}
943
Sen Jiang2d528b42015-09-25 11:18:12 -0700944TEST_F(DeltaPerformerTest, UsePublicKeyFromResponse) {
David Zeuthene7f89172013-10-31 10:21:04 -0700945 // The result of the GetPublicKeyResponse() method is based on three things
946 //
947 // 1. Whether it's an official build; and
948 // 2. Whether the Public RSA key to be used is in the root filesystem; and
Alex Vakulenko072359c2014-07-18 11:41:07 -0700949 // 3. Whether the response has a public key
David Zeuthene7f89172013-10-31 10:21:04 -0700950 //
951 // We test all eight combinations to ensure that we only use the
952 // public key in the response if
953 //
954 // a. it's not an official build; and
955 // b. there is no key in the root filesystem.
956
Sen Jiang371615b2016-04-13 15:54:29 -0700957 base::ScopedTempDir temp_dir;
958 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Jay Civellia78ddf82017-03-30 11:02:03 -0700959 string non_existing_file = temp_dir.GetPath().Append("non-existing").value();
960 string existing_file = temp_dir.GetPath().Append("existing").value();
Sen Jiang08c6da12019-01-07 18:28:56 -0800961 constexpr char kExistingKey[] = "Existing";
962 ASSERT_TRUE(test_utils::WriteFileString(existing_file, kExistingKey));
David Zeuthene7f89172013-10-31 10:21:04 -0700963
Sen Jiang08c6da12019-01-07 18:28:56 -0800964 // Non-official build, non-existing public-key, key in response ->
965 // kResponseKey
Alex Deymo542c19b2015-12-03 07:43:31 -0300966 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700967 performer_.public_key_path_ = non_existing_file;
Sen Jiang08c6da12019-01-07 18:28:56 -0800968 // This is the result of 'echo -n "Response" | base64' and is not meant to be
969 // a valid public key, but it is valid base-64.
970 constexpr char kResponseKey[] = "Response";
971 constexpr char kBase64ResponseKey[] = "UmVzcG9uc2U=";
972 install_plan_.public_key_rsa = kBase64ResponseKey;
973 string public_key;
974 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
975 EXPECT_EQ(public_key, kResponseKey);
976 // Same with official build -> no key
Alex Deymo542c19b2015-12-03 07:43:31 -0300977 fake_hardware_.SetIsOfficialBuild(true);
Sen Jiang08c6da12019-01-07 18:28:56 -0800978 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
979 EXPECT_TRUE(public_key.empty());
David Zeuthene7f89172013-10-31 10:21:04 -0700980
Sen Jiang08c6da12019-01-07 18:28:56 -0800981 // Non-official build, existing public-key, key in response -> kExistingKey
Alex Deymo542c19b2015-12-03 07:43:31 -0300982 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700983 performer_.public_key_path_ = existing_file;
Sen Jiang08c6da12019-01-07 18:28:56 -0800984 install_plan_.public_key_rsa = kBase64ResponseKey;
985 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
986 EXPECT_EQ(public_key, kExistingKey);
987 // Same with official build -> kExistingKey
Alex Deymo542c19b2015-12-03 07:43:31 -0300988 fake_hardware_.SetIsOfficialBuild(true);
Sen Jiang08c6da12019-01-07 18:28:56 -0800989 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
990 EXPECT_EQ(public_key, kExistingKey);
David Zeuthene7f89172013-10-31 10:21:04 -0700991
Sen Jiang08c6da12019-01-07 18:28:56 -0800992 // Non-official build, non-existing public-key, no key in response -> no key
Alex Deymo542c19b2015-12-03 07:43:31 -0300993 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700994 performer_.public_key_path_ = non_existing_file;
995 install_plan_.public_key_rsa = "";
Sen Jiang08c6da12019-01-07 18:28:56 -0800996 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
997 EXPECT_TRUE(public_key.empty());
998 // Same with official build -> no key
Alex Deymo542c19b2015-12-03 07:43:31 -0300999 fake_hardware_.SetIsOfficialBuild(true);
Sen Jiang08c6da12019-01-07 18:28:56 -08001000 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1001 EXPECT_TRUE(public_key.empty());
David Zeuthene7f89172013-10-31 10:21:04 -07001002
Sen Jiang08c6da12019-01-07 18:28:56 -08001003 // Non-official build, existing public-key, no key in response -> kExistingKey
Alex Deymo542c19b2015-12-03 07:43:31 -03001004 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -07001005 performer_.public_key_path_ = existing_file;
1006 install_plan_.public_key_rsa = "";
Sen Jiang08c6da12019-01-07 18:28:56 -08001007 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1008 EXPECT_EQ(public_key, kExistingKey);
1009 // Same with official build -> kExistingKey
Alex Deymo542c19b2015-12-03 07:43:31 -03001010 fake_hardware_.SetIsOfficialBuild(true);
Sen Jiang08c6da12019-01-07 18:28:56 -08001011 EXPECT_TRUE(performer_.GetPublicKey(&public_key));
1012 EXPECT_EQ(public_key, kExistingKey);
David Zeuthene7f89172013-10-31 10:21:04 -07001013
1014 // Non-official build, non-existing public-key, key in response
1015 // but invalid base64 -> false
Alex Deymo542c19b2015-12-03 07:43:31 -03001016 fake_hardware_.SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -07001017 performer_.public_key_path_ = non_existing_file;
1018 install_plan_.public_key_rsa = "not-valid-base64";
Sen Jiang08c6da12019-01-07 18:28:56 -08001019 EXPECT_FALSE(performer_.GetPublicKey(&public_key));
David Zeuthene7f89172013-10-31 10:21:04 -07001020}
1021
Alex Deymocbf09892015-09-11 16:13:16 -07001022TEST_F(DeltaPerformerTest, ConfVersionsMatch) {
1023 // Test that the versions in update_engine.conf that is installed to the
Sen Jiangf1236632018-05-11 16:03:23 -07001024 // image match the maximum supported delta versions in the update engine.
Allie Wood78750a42015-02-11 15:42:11 -08001025 uint32_t minor_version;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -07001026 brillo::KeyValueStore store;
Sen Jiangee63c6e2016-03-30 14:01:02 -07001027 EXPECT_TRUE(store.Load(GetBuildArtifactsPath().Append("update_engine.conf")));
Alex Deymob42b98d2015-07-06 17:42:38 -07001028 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
Sen Jiangf1236632018-05-11 16:03:23 -07001029 EXPECT_EQ(kMaxSupportedMinorPayloadVersion, minor_version);
Alex Deymocbf09892015-09-11 16:13:16 -07001030
1031 string major_version_str;
1032 uint64_t major_version;
1033 EXPECT_TRUE(store.GetString("PAYLOAD_MAJOR_VERSION", &major_version_str));
1034 EXPECT_TRUE(base::StringToUint64(major_version_str, &major_version));
Sen Jiangf1236632018-05-11 16:03:23 -07001035 EXPECT_EQ(kMaxSupportedMajorPayloadVersion, major_version);
Allie Wood78750a42015-02-11 15:42:11 -08001036}
1037
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001038} // namespace chromeos_update_engine