blob: 87ed369bd7b98c091111a6b31621cc120248e90a [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 Deymo8427b4a2014-11-05 14:00:32 -080017#include "update_engine/delta_performer.h"
18
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070019#include <inttypes.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070020#include <sys/mount.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070021
22#include <algorithm>
23#include <string>
24#include <vector>
25
Allie Wood78750a42015-02-11 15:42:11 -080026#include <base/files/file_path.h>
Ben Chan06c76a42014-09-05 08:21:06 -070027#include <base/files/file_util.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070028#include <base/strings/stringprintf.h>
Alex Deymof1cbe172015-03-05 15:58:37 -080029#include <base/strings/string_util.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070030#include <google/protobuf/repeated_field.h>
31#include <gtest/gtest.h>
32
Jay Srinivasand29695d2013-04-08 15:08:05 -070033#include "update_engine/constants.h"
David Zeuthene7f89172013-10-31 10:21:04 -070034#include "update_engine/fake_hardware.h"
Gilad Arnold5bb4c902014-04-10 12:32:13 -070035#include "update_engine/fake_system_state.h"
Alex Deymo8427b4a2014-11-05 14:00:32 -080036#include "update_engine/mock_prefs.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070037#include "update_engine/payload_constants.h"
38#include "update_engine/payload_generator/delta_diff_generator.h"
Sen Jiangd78b3892015-09-25 15:19:31 -070039#include "update_engine/payload_generator/payload_file.h"
Alex Deymo923d8fa2014-07-15 17:58:51 -070040#include "update_engine/payload_generator/payload_signer.h"
41#include "update_engine/payload_verifier.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070042#include "update_engine/test_utils.h"
43#include "update_engine/update_metadata.pb.h"
44#include "update_engine/utils.h"
45
46namespace chromeos_update_engine {
47
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070048using std::string;
49using std::vector;
Darin Petkov73058b42010-10-06 16:32:19 -070050using testing::Return;
Alex Deymo161c4a12014-05-16 15:56:21 -070051using testing::_;
Alex Deymo10875d92014-11-10 21:52:57 -080052using test_utils::kRandomString;
53using test_utils::ScopedLoopMounter;
54using test_utils::System;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070055
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070056extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070057extern const char* kUnittestPublicKeyPath;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070058extern const char* kUnittestPrivateKey2Path;
59extern const char* kUnittestPublicKey2Path;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070060
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -070061static const char* kBogusMetadataSignature1 =
62 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
63 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
64 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
65 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
66 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
67 "pLRtClp97kN2+tXGNBQqkA==";
Jay Srinivasan738fdf32012-12-07 17:40:54 -080068
Alex Vakulenkod2779df2014-06-16 13:19:00 -070069static const int kDefaultKernelSize = 4096; // Something small for a test
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080070static const uint8_t kNewData[] = {'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
71 'n', 'e', 'w', ' ', 'd', 'a', 't', 'a', '.'};
Jay Srinivasan738fdf32012-12-07 17:40:54 -080072
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070073namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080074struct DeltaState {
75 string a_img;
76 string b_img;
Allie Wood9f6f0a52015-03-30 11:25:47 -070077 string result_img;
Alex Deymoda73df52015-07-22 13:53:29 -070078 size_t image_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070079
Jay Srinivasan738fdf32012-12-07 17:40:54 -080080 string delta_path;
81 uint64_t metadata_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070082
Jay Srinivasan738fdf32012-12-07 17:40:54 -080083 string old_kernel;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080084 chromeos::Blob old_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070085
Jay Srinivasan738fdf32012-12-07 17:40:54 -080086 string new_kernel;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080087 chromeos::Blob new_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070088
Allie Wood9f6f0a52015-03-30 11:25:47 -070089 string result_kernel;
90 chromeos::Blob result_kernel_data;
Alex Deymoda73df52015-07-22 13:53:29 -070091 size_t kernel_size;
Allie Wood9f6f0a52015-03-30 11:25:47 -070092
Jay Srinivasan738fdf32012-12-07 17:40:54 -080093 // The in-memory copy of delta file.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080094 chromeos::Blob delta;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080095
96 // The mock system state object with which we initialize the
97 // delta performer.
Gilad Arnold5bb4c902014-04-10 12:32:13 -070098 FakeSystemState fake_system_state;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080099};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700100
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800101enum SignatureTest {
102 kSignatureNone, // No payload signing.
103 kSignatureGenerator, // Sign the payload at generation time.
104 kSignatureGenerated, // Sign the payload after it's generated.
Don Garrett2ae37872013-10-25 13:33:20 -0700105 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700106 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800107 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
108 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
109 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
110 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
111};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700112
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800113// Different options that determine what we should fill into the
114// install_plan.metadata_signature to simulate the contents received in the
115// Omaha response.
116enum MetadataSignatureTest {
117 kEmptyMetadataSignature,
118 kInvalidMetadataSignature,
119 kValidMetadataSignature,
120};
121
122enum OperationHashTest {
123 kInvalidOperationData,
124 kValidOperationData,
125};
126
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700127} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800128
Allie Woodfdf00512015-03-02 13:34:55 -0800129class DeltaPerformerTest : public ::testing::Test {
130 public:
131 // Test helper placed where it can easily be friended from DeltaPerformer.
132 static void RunManifestValidation(const DeltaArchiveManifest& manifest,
133 bool full_payload,
134 ErrorCode expected) {
135 MockPrefs prefs;
136 InstallPlan install_plan;
137 FakeSystemState fake_system_state;
138 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
139
140 // The install plan is for Full or Delta.
141 install_plan.is_full_update = full_payload;
142
143 // The Manifest we are validating.
144 performer.manifest_.CopyFrom(manifest);
145
146 EXPECT_EQ(expected, performer.ValidateManifest());
147 }
148
149 static void SetSupportedVersion(DeltaPerformer* performer,
150 uint64_t minor_version) {
151 performer->supported_minor_version_ = minor_version;
152 }
Sen Jiangd78b3892015-09-25 15:19:31 -0700153
154 static chromeos::Blob GeneratePayload(const chromeos::Blob& blob_data,
155 const vector<AnnotatedOperation>& aops,
156 bool sign_payload,
157 int32_t minor_version,
158 uint64_t* out_metadata_size) {
159 string blob_path;
160 EXPECT_TRUE(utils::MakeTempFile("Blob-XXXXXX", &blob_path, nullptr));
161 ScopedPathUnlinker blob_unlinker(blob_path);
162 EXPECT_TRUE(utils::WriteFile(blob_path.c_str(),
163 blob_data.data(),
164 blob_data.size()));
165
166 PayloadGenerationConfig config;
167 config.major_version = kChromeOSMajorPayloadVersion;
168 config.minor_version = minor_version;
169 config.target.rootfs.path = blob_path;
170 config.target.rootfs.size = blob_data.size();
171 config.target.kernel.path = blob_path;
172 config.target.kernel.size = blob_data.size();
173
174 PayloadFile payload;
175 EXPECT_TRUE(payload.Init(config));
176
177 payload.AddPartition(config.source.rootfs, config.target.rootfs, aops);
178
179 string payload_path;
180 EXPECT_TRUE(utils::MakeTempFile("Payload-XXXXXX", &payload_path, nullptr));
181 ScopedPathUnlinker payload_unlinker(payload_path);
182 EXPECT_TRUE(payload.WritePayload(payload_path, blob_path,
183 sign_payload ? kUnittestPrivateKeyPath : "",
184 out_metadata_size));
185
186 chromeos::Blob payload_data;
187 EXPECT_TRUE(utils::ReadFile(payload_path, &payload_data));
188 return payload_data;
189 }
Allie Woodfdf00512015-03-02 13:34:55 -0800190};
191
Alex Deymoda73df52015-07-22 13:53:29 -0700192static void CompareFilesByBlock(const string& a_file, const string& b_file,
193 size_t image_size) {
194 EXPECT_EQ(0, image_size % kBlockSize);
195
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800196 chromeos::Blob a_data, b_data;
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700197 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
198 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700199
Alex Deymoda73df52015-07-22 13:53:29 -0700200 EXPECT_GE(a_data.size(), image_size);
201 EXPECT_GE(b_data.size(), image_size);
202 for (size_t i = 0; i < image_size; i += kBlockSize) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700203 EXPECT_EQ(0, i % kBlockSize);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800204 chromeos::Blob a_sub(&a_data[i], &a_data[i + kBlockSize]);
205 chromeos::Blob b_sub(&b_data[i], &b_data[i + kBlockSize]);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700206 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
207 }
Alex Deymoda73df52015-07-22 13:53:29 -0700208 if (::testing::Test::HasNonfatalFailure()) {
209 LOG(INFO) << "Compared filesystems with size " << image_size
210 << ", partition A " << a_file << " size: " << a_data.size()
211 << ", partition B " << b_file << " size: " << b_data.size();
212 }
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700213}
214
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800215static bool WriteSparseFile(const string& path, off_t size) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700216 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
217 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
218 ScopedFdCloser fd_closer(&fd);
219 off_t rc = lseek(fd, size + 1, SEEK_SET);
220 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
221 int return_code = ftruncate(fd, size);
222 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
223 return true;
224}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700225
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800226static size_t GetSignatureSize(const string& private_key_path) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800227 const chromeos::Blob data(1, 'x');
228 chromeos::Blob hash;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800229 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(data, &hash));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800230 chromeos::Blob signature;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800231 EXPECT_TRUE(PayloadSigner::SignHash(hash,
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800232 private_key_path,
Darin Petkovcbfb0172011-01-14 15:24:45 -0800233 &signature));
234 return signature.size();
235}
236
Don Garrett2ae37872013-10-25 13:33:20 -0700237static bool InsertSignaturePlaceholder(int signature_size,
238 const string& payload_path,
239 uint64_t* out_metadata_size) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800240 vector<chromeos::Blob> signatures;
241 signatures.push_back(chromeos::Blob(signature_size, 0));
Don Garrett2ae37872013-10-25 13:33:20 -0700242
243 return PayloadSigner::AddSignatureToPayload(
244 payload_path,
245 signatures,
246 payload_path,
247 out_metadata_size);
248}
249
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800250static void SignGeneratedPayload(const string& payload_path,
251 uint64_t* out_metadata_size) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800252 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800253 chromeos::Blob hash;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700254 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
255 payload_path,
256 vector<int>(1, signature_size),
257 &hash));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800258 chromeos::Blob signature;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800259 ASSERT_TRUE(PayloadSigner::SignHash(hash,
260 kUnittestPrivateKeyPath,
261 &signature));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700262 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
263 payload_path,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800264 vector<chromeos::Blob>(1, signature),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800265 payload_path,
266 out_metadata_size));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700267 EXPECT_TRUE(PayloadVerifier::VerifySignedPayload(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700268 payload_path,
269 kUnittestPublicKeyPath,
270 kSignatureMessageOriginalVersion));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800271}
272
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800273static void SignGeneratedShellPayload(SignatureTest signature_test,
274 const string& payload_path) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800275 string private_key_path = kUnittestPrivateKeyPath;
276 if (signature_test == kSignatureGeneratedShellBadKey) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800277 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800278 &private_key_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700279 nullptr));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800280 } else {
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700281 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
282 signature_test == kSignatureGeneratedShellRotateCl1 ||
283 signature_test == kSignatureGeneratedShellRotateCl2);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800284 }
285 ScopedPathUnlinker key_unlinker(private_key_path);
286 key_unlinker.set_should_remove(signature_test ==
287 kSignatureGeneratedShellBadKey);
288 // Generates a new private key that will not match the public key.
289 if (signature_test == kSignatureGeneratedShellBadKey) {
290 LOG(INFO) << "Generating a mismatched private key.";
Alex Deymo719bfff2014-07-11 12:12:32 -0700291 ASSERT_EQ(0, System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400292 "openssl genrsa -out %s 2048", private_key_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800293 }
294 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800295 string hash_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700296 ASSERT_TRUE(utils::MakeTempFile("hash.XXXXXX", &hash_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800297 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700298 string signature_size_string;
299 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
300 signature_test == kSignatureGeneratedShellRotateCl2)
Alex Vakulenko75039d72014-03-25 12:36:28 -0700301 signature_size_string = base::StringPrintf("%d:%d",
302 signature_size, signature_size);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700303 else
Alex Vakulenko75039d72014-03-25 12:36:28 -0700304 signature_size_string = base::StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800305 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700306 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700307 "./delta_generator -in_file=%s -signature_size=%s "
308 "-out_hash_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800309 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700310 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800311 hash_file.c_str())));
312
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700313 // Pad the hash
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800314 chromeos::Blob hash;
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700315 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700316 ASSERT_TRUE(PayloadVerifier::PadRSA2048SHA256Hash(&hash));
Alex Deymo10875d92014-11-10 21:52:57 -0800317 ASSERT_TRUE(test_utils::WriteFileVector(hash_file, hash));
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700318
Darin Petkovcbfb0172011-01-14 15:24:45 -0800319 string sig_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700320 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800321 ScopedPathUnlinker sig_unlinker(sig_file);
322 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700323 System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400324 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800325 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800326 hash_file.c_str(),
327 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700328 string sig_file2;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700329 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file2, nullptr));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700330 ScopedPathUnlinker sig2_unlinker(sig_file2);
331 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
332 signature_test == kSignatureGeneratedShellRotateCl2) {
333 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700334 System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400335 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700336 kUnittestPrivateKey2Path,
337 hash_file.c_str(),
338 sig_file2.c_str())));
339 // Append second sig file to first path
340 sig_file += ":" + sig_file2;
341 }
342
Darin Petkovcbfb0172011-01-14 15:24:45 -0800343 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700344 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700345 "./delta_generator -in_file=%s -signature_file=%s "
346 "-out_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800347 payload_path.c_str(),
348 sig_file.c_str(),
349 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800350 int verify_result =
Alex Vakulenko75039d72014-03-25 12:36:28 -0700351 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700352 "./delta_generator -in_file=%s -public_key=%s -public_key_version=%d",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700353 payload_path.c_str(),
354 signature_test == kSignatureGeneratedShellRotateCl2 ?
355 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
356 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800357 if (signature_test == kSignatureGeneratedShellBadKey) {
358 ASSERT_NE(0, verify_result);
359 } else {
360 ASSERT_EQ(0, verify_result);
361 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800362}
363
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800364static void GenerateDeltaFile(bool full_kernel,
365 bool full_rootfs,
366 bool noop,
Alex Deymo2d3b2d62015-07-17 17:34:36 -0700367 ssize_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800368 SignatureTest signature_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800369 DeltaState *state,
370 uint32_t minor_version) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700371 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
372 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
Allie Wood9f6f0a52015-03-30 11:25:47 -0700373
374 // result_img is used in minor version 2. Instead of applying the update
375 // in-place on A, we apply it to a new image, result_img.
376 EXPECT_TRUE(
377 utils::MakeTempFile("result_img.XXXXXX", &state->result_img, nullptr));
Alex Deymo10875d92014-11-10 21:52:57 -0800378 test_utils::CreateExtImageAtPath(state->a_img, nullptr);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700379
Alex Deymoda73df52015-07-22 13:53:29 -0700380 state->image_size = utils::FileSize(state->a_img);
Darin Petkov7ea32332010-10-13 10:46:11 -0700381
382 // Extend the "partitions" holding the file system a bit.
Alex Deymoda73df52015-07-22 13:53:29 -0700383 EXPECT_EQ(0, HANDLE_EINTR(truncate(state->a_img.c_str(),
384 state->image_size + 1024 * 1024)));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800385 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700386
Don Garrett0dd39852013-04-03 16:55:42 -0700387 // Create ImageInfo A & B
388 ImageInfo old_image_info;
389 ImageInfo new_image_info;
390
391 if (!full_rootfs) {
392 old_image_info.set_channel("src-channel");
393 old_image_info.set_board("src-board");
394 old_image_info.set_version("src-version");
395 old_image_info.set_key("src-key");
396 old_image_info.set_build_channel("src-build-channel");
397 old_image_info.set_build_version("src-build-version");
398 }
399
400 new_image_info.set_channel("test-channel");
401 new_image_info.set_board("test-board");
402 new_image_info.set_version("test-version");
403 new_image_info.set_key("test-key");
404 new_image_info.set_build_channel("test-build-channel");
405 new_image_info.set_build_version("test-build-version");
406
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700407 // Make some changes to the A image.
408 {
409 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800410 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700411
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800412 chromeos::Blob hardtocompress;
Darin Petkov8e447e02013-04-16 16:23:50 +0200413 while (hardtocompress.size() < 3 * kBlockSize) {
414 hardtocompress.insert(hardtocompress.end(),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800415 std::begin(kRandomString), std::end(kRandomString));
Darin Petkov8e447e02013-04-16 16:23:50 +0200416 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700417 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800418 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700419 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200420 hardtocompress.size()));
421
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800422 chromeos::Blob zeros(16 * 1024, 0);
Darin Petkov8a075a72013-04-25 14:46:09 +0200423 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700424 base::WriteFile(base::FilePath(base::StringPrintf(
425 "%s/move-to-sparse", a_mnt.c_str())),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800426 reinterpret_cast<const char*>(zeros.data()),
427 zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200428
429 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700430 WriteSparseFile(base::StringPrintf("%s/move-from-sparse",
431 a_mnt.c_str()), 16 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200432
Alex Vakulenko75039d72014-03-25 12:36:28 -0700433 EXPECT_EQ(0,
Alex Deymo10875d92014-11-10 21:52:57 -0800434 System(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
Alex Deymo1f93d032015-03-10 18:58:32 -0700435 " bs=1 seek=4096 count=1 status=none",
Alex Deymo10875d92014-11-10 21:52:57 -0800436 a_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200437
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700438 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
439 // patch fails to zero out the final block.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800440 chromeos::Blob ones(1024 * 1024, 0xff);
Alex Vakulenko75039d72014-03-25 12:36:28 -0700441 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/ones",
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800442 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700443 ones.data(),
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700444 ones.size()));
445 }
446
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700447 if (noop) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700448 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img),
449 base::FilePath(state->b_img)));
Don Garrett0dd39852013-04-03 16:55:42 -0700450 old_image_info = new_image_info;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700451 } else {
Allie Wood9f6f0a52015-03-30 11:25:47 -0700452 if (minor_version == kSourceMinorPayloadVersion) {
453 // Create a result image with image_size bytes of garbage, followed by
454 // zeroes after the rootfs, like image A and B have.
455 chromeos::Blob ones(state->image_size, 0xff);
456 ones.insert(ones.end(), 1024 * 1024, 0);
457 EXPECT_TRUE(utils::WriteFile(state->result_img.c_str(),
458 ones.data(),
459 ones.size()));
460 EXPECT_EQ(utils::FileSize(state->a_img),
461 utils::FileSize(state->result_img));
462 }
463
Alex Deymo10875d92014-11-10 21:52:57 -0800464 test_utils::CreateExtImageAtPath(state->b_img, nullptr);
Alex Deymoda73df52015-07-22 13:53:29 -0700465 EXPECT_EQ(0, HANDLE_EINTR(truncate(state->b_img.c_str(),
466 state->image_size + 1024 * 1024)));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800467 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700468
469 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700470 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800471 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700472
Alex Deymo10875d92014-11-10 21:52:57 -0800473 EXPECT_EQ(0, System(base::StringPrintf("cp %s/hello %s/hello2",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700474 b_mnt.c_str(),
475 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800476 EXPECT_EQ(0, System(base::StringPrintf("rm %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700477 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800478 EXPECT_EQ(0, System(base::StringPrintf("mv %s/hello2 %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700479 b_mnt.c_str(),
480 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800481 EXPECT_EQ(0, System(base::StringPrintf("echo foo > %s/foo",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700482 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800483 EXPECT_EQ(0, System(base::StringPrintf("touch %s/emptyfile",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700484 b_mnt.c_str()).c_str()));
485 EXPECT_TRUE(WriteSparseFile(base::StringPrintf("%s/fullsparse",
486 b_mnt.c_str()),
487 1024 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200488
489 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700490 WriteSparseFile(base::StringPrintf("%s/move-to-sparse", b_mnt.c_str()),
Darin Petkov8a075a72013-04-25 14:46:09 +0200491 16 * 1024));
492
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800493 chromeos::Blob zeros(16 * 1024, 0);
Darin Petkov8a075a72013-04-25 14:46:09 +0200494 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700495 base::WriteFile(base::FilePath(base::StringPrintf(
496 "%s/move-from-sparse", b_mnt.c_str())),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800497 reinterpret_cast<const char*>(zeros.data()),
498 zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200499
Alex Deymo10875d92014-11-10 21:52:57 -0800500 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700501 "of=%s/move-semi-sparse "
Alex Deymo1f93d032015-03-10 18:58:32 -0700502 "bs=1 seek=4096 count=1 status=none",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700503 b_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200504
Alex Deymo10875d92014-11-10 21:52:57 -0800505 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700506 "of=%s/partsparse bs=1 "
Alex Deymo1f93d032015-03-10 18:58:32 -0700507 "seek=4096 count=1 status=none",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700508 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800509 EXPECT_EQ(0, System(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700510 "mv %s/tmp %s/srchardlink1",
511 b_mnt.c_str(),
512 b_mnt.c_str(),
513 b_mnt.c_str(),
514 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800515 EXPECT_EQ(0, System(
516 base::StringPrintf("rm %s/boguslink && echo foobar > %s/boguslink",
517 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Darin Petkov8e447e02013-04-16 16:23:50 +0200518
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800519 chromeos::Blob hardtocompress;
Darin Petkov8e447e02013-04-16 16:23:50 +0200520 while (hardtocompress.size() < 3 * kBlockSize) {
521 hardtocompress.insert(hardtocompress.end(),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800522 std::begin(kRandomString), std::end(kRandomString));
Darin Petkov8e447e02013-04-16 16:23:50 +0200523 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700524 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700525 b_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700526 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200527 hardtocompress.size()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700528 }
529
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700530 string old_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800531 EXPECT_TRUE(utils::MakeTempFile("old_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800532 &state->old_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700533 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700534
535 string new_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800536 EXPECT_TRUE(utils::MakeTempFile("new_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800537 &state->new_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700538 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700539
Allie Wood9f6f0a52015-03-30 11:25:47 -0700540 string result_kernel;
541 EXPECT_TRUE(utils::MakeTempFile("result_kernel.XXXXXX",
542 &state->result_kernel,
543 nullptr));
544
Alex Deymoda73df52015-07-22 13:53:29 -0700545 state->kernel_size = kDefaultKernelSize;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800546 state->old_kernel_data.resize(kDefaultKernelSize);
547 state->new_kernel_data.resize(state->old_kernel_data.size());
Allie Wood9f6f0a52015-03-30 11:25:47 -0700548 state->result_kernel_data.resize(state->old_kernel_data.size());
Alex Deymo10875d92014-11-10 21:52:57 -0800549 test_utils::FillWithData(&state->old_kernel_data);
550 test_utils::FillWithData(&state->new_kernel_data);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700551 test_utils::FillWithData(&state->result_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700552
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700553 // change the new kernel data
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800554 std::copy(std::begin(kNewData), std::end(kNewData),
555 state->new_kernel_data.begin());
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700556
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700557 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800558 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700559 }
560
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700561 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800562 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700563 state->old_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800564 state->old_kernel_data.size()));
565 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700566 state->new_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800567 state->new_kernel_data.size()));
Allie Wood9f6f0a52015-03-30 11:25:47 -0700568 EXPECT_TRUE(utils::WriteFile(state->result_kernel.c_str(),
569 state->result_kernel_data.data(),
570 state->result_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700571
Gilad Arnolda6742b32014-01-11 00:18:34 -0800572 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800573 &state->delta_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700574 nullptr));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800575 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700576 {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800577 const string private_key =
578 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Alex Deymof1cbe172015-03-05 15:58:37 -0800579
580 PayloadGenerationConfig payload_config;
581 payload_config.is_delta = !full_rootfs;
Alex Deymo2d3b2d62015-07-17 17:34:36 -0700582 payload_config.hard_chunk_size = chunk_size;
Alex Deymo9b244df2015-03-11 21:51:18 -0700583 payload_config.rootfs_partition_size = kRootFSPartitionSize;
Sen Jiang46e9b172015-08-31 14:11:01 -0700584 payload_config.major_version = kChromeOSMajorPayloadVersion;
Allie Woodfdf00512015-03-02 13:34:55 -0800585 payload_config.minor_version = minor_version;
Alex Deymof1cbe172015-03-05 15:58:37 -0800586 if (!full_rootfs) {
Alex Deymo35589c22015-06-07 17:33:18 +0200587 payload_config.source.rootfs.path = state->a_img;
Alex Deymof1cbe172015-03-05 15:58:37 -0800588 if (!full_kernel)
Alex Deymo35589c22015-06-07 17:33:18 +0200589 payload_config.source.kernel.path = state->old_kernel;
Alex Deymof1cbe172015-03-05 15:58:37 -0800590 payload_config.source.image_info = old_image_info;
591 EXPECT_TRUE(payload_config.source.LoadImageSize());
Alex Deymob42b98d2015-07-06 17:42:38 -0700592 EXPECT_TRUE(payload_config.source.rootfs.OpenFilesystem());
593 EXPECT_TRUE(payload_config.source.kernel.OpenFilesystem());
Alex Deymof1cbe172015-03-05 15:58:37 -0800594 } else {
Alex Deymo2d3b2d62015-07-17 17:34:36 -0700595 if (payload_config.hard_chunk_size == -1)
596 // Use 1 MiB chunk size for the full unittests.
597 payload_config.hard_chunk_size = 1024 * 1024;
Alex Deymof1cbe172015-03-05 15:58:37 -0800598 }
Alex Deymo35589c22015-06-07 17:33:18 +0200599 payload_config.target.rootfs.path = state->b_img;
600 payload_config.target.kernel.path = state->new_kernel;
Alex Deymof1cbe172015-03-05 15:58:37 -0800601 payload_config.target.image_info = new_image_info;
602 EXPECT_TRUE(payload_config.target.LoadImageSize());
Alex Deymob42b98d2015-07-06 17:42:38 -0700603 EXPECT_TRUE(payload_config.target.rootfs.OpenFilesystem());
604 EXPECT_TRUE(payload_config.target.kernel.OpenFilesystem());
Alex Deymof1cbe172015-03-05 15:58:37 -0800605
606 EXPECT_TRUE(payload_config.Validate());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700607 EXPECT_TRUE(
Alex Deymo477aec22015-03-24 23:40:48 -0700608 GenerateUpdatePayloadFile(
Alex Deymof1cbe172015-03-05 15:58:37 -0800609 payload_config,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800610 state->delta_path,
611 private_key,
612 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800613 }
614
Don Garrett2ae37872013-10-25 13:33:20 -0700615 if (signature_test == kSignatureGeneratedPlaceholder ||
616 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Don Garrett2ae37872013-10-25 13:33:20 -0700617 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
618 LOG(INFO) << "Inserting placeholder signature.";
619 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
620 &state->metadata_size));
621
622 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
623 signature_size -= 1;
624 LOG(INFO) << "Inserting mismatched placeholder signature.";
625 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
626 &state->metadata_size));
627 return;
628 }
629 }
630
631 if (signature_test == kSignatureGenerated ||
632 signature_test == kSignatureGeneratedPlaceholder ||
633 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800634 // Generate the signed payload and update the metadata size in state to
635 // reflect the new size after adding the signature operation to the
636 // manifest.
Don Garrett2ae37872013-10-25 13:33:20 -0700637 LOG(INFO) << "Signing payload.";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800638 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800639 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700640 signature_test == kSignatureGeneratedShellBadKey ||
641 signature_test == kSignatureGeneratedShellRotateCl1 ||
642 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800643 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700644 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800645}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700646
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800647static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
648 SignatureTest signature_test, DeltaState* state,
649 bool hash_checks_mandatory,
650 OperationHashTest op_hash_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800651 DeltaPerformer** performer,
652 uint32_t minor_version) {
Darin Petkov36a58222010-10-07 22:00:09 -0700653 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700654 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700655 DeltaArchiveManifest manifest;
Alex Deymo923d8fa2014-07-15 17:58:51 -0700656 EXPECT_TRUE(PayloadVerifier::LoadPayload(state->delta_path,
657 &state->delta,
658 &manifest,
659 &state->metadata_size));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800660 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700661
Don Garrett0dd39852013-04-03 16:55:42 -0700662
663
Darin Petkovcbfb0172011-01-14 15:24:45 -0800664 if (signature_test == kSignatureNone) {
665 EXPECT_FALSE(manifest.has_signatures_offset());
666 EXPECT_FALSE(manifest.has_signatures_size());
667 } else {
668 EXPECT_TRUE(manifest.has_signatures_offset());
669 EXPECT_TRUE(manifest.has_signatures_size());
670 Signatures sigs_message;
671 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800672 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800673 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700674 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
675 signature_test == kSignatureGeneratedShellRotateCl2)
676 EXPECT_EQ(2, sigs_message.signatures_size());
677 else
678 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800679 const Signatures_Signature& signature = sigs_message.signatures(0);
680 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700681
Darin Petkovcbfb0172011-01-14 15:24:45 -0800682 uint64_t expected_sig_data_length = 0;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700683 vector<string> key_paths{kUnittestPrivateKeyPath};
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700684 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
685 signature_test == kSignatureGeneratedShellRotateCl2) {
686 key_paths.push_back(kUnittestPrivateKey2Path);
687 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800688 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700689 key_paths,
690 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800691 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
692 EXPECT_FALSE(signature.data().empty());
693 }
Darin Petkov36a58222010-10-07 22:00:09 -0700694
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700695 if (noop) {
Gilad Arnold063181c2015-02-05 12:24:49 -0800696 EXPECT_EQ(0, manifest.install_operations_size());
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700697 EXPECT_EQ(1, manifest.kernel_install_operations_size());
698 }
699
Darin Petkovd43d6902010-10-14 11:17:50 -0700700 if (full_kernel) {
701 EXPECT_FALSE(manifest.has_old_kernel_info());
702 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800703 EXPECT_EQ(state->old_kernel_data.size(),
704 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700705 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
706 }
Darin Petkov698d0412010-10-13 10:59:44 -0700707
Don Garrett0dd39852013-04-03 16:55:42 -0700708 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
709 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
710 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
711 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
712 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
713 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
714
715 if (!full_rootfs) {
Don Garrett0dd39852013-04-03 16:55:42 -0700716 if (noop) {
717 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
718 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
719 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
720 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
721 EXPECT_EQ(manifest.old_image_info().build_channel(),
722 "test-build-channel");
723 EXPECT_EQ(manifest.old_image_info().build_version(),
724 "test-build-version");
725 } else {
726 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
727 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
728 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
729 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
730 EXPECT_EQ(manifest.old_image_info().build_channel(),
731 "src-build-channel");
732 EXPECT_EQ(manifest.old_image_info().build_version(),
733 "src-build-version");
734 }
735 }
736
737
Darin Petkov7a22d792010-11-08 14:10:00 -0800738 if (full_rootfs) {
739 EXPECT_FALSE(manifest.has_old_rootfs_info());
Don Garrett0dd39852013-04-03 16:55:42 -0700740 EXPECT_FALSE(manifest.has_old_image_info());
741 EXPECT_TRUE(manifest.has_new_image_info());
Darin Petkov7a22d792010-11-08 14:10:00 -0800742 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800743 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800744 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
745 }
746
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800747 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
748 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700749
Darin Petkov36a58222010-10-07 22:00:09 -0700750 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700751 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700752 }
753
Alex Deymo8427b4a2014-11-05 14:00:32 -0800754 MockPrefs prefs;
Darin Petkov73058b42010-10-06 16:32:19 -0700755 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800756 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700757 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
758 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700759 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
760 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700761 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
762 .WillRepeatedly(Return(true));
David Zeuthen41996ad2013-09-24 15:43:24 -0700763 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
764 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700765 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700766 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800767 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800768 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
769 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700770 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
771 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800772 }
Darin Petkov73058b42010-10-06 16:32:19 -0700773
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700774 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700775 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800776 install_plan.hash_checks_mandatory = hash_checks_mandatory;
777 install_plan.metadata_size = state->metadata_size;
Don Garrettb8dd1d92013-11-22 17:40:02 -0800778 install_plan.is_full_update = full_kernel && full_rootfs;
Allie Woodfdf00512015-03-02 13:34:55 -0800779 install_plan.source_path = state->a_img.c_str();
780 install_plan.kernel_source_path = state->old_kernel.c_str();
Don Garrettb8dd1d92013-11-22 17:40:02 -0800781
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800782 LOG(INFO) << "Setting payload metadata size in Omaha = "
783 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700784 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700785 state->delta.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800786 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700787 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700788 &install_plan.metadata_signature));
789 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700790
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800791 *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700792 &state->fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800793 &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700794 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800795 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Allie Woodfdf00512015-03-02 13:34:55 -0800796 DeltaPerformerTest::SetSupportedVersion(*performer, minor_version);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700797
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800798 EXPECT_EQ(state->image_size,
Allie Woodeb9e6d82015-04-17 13:55:30 -0700799 OmahaHashCalculator::RawHashOfFile(
800 state->a_img,
801 state->image_size,
802 &install_plan.source_rootfs_hash));
803 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(
804 state->old_kernel_data,
805 &install_plan.source_kernel_hash));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700806
Allie Wood9f6f0a52015-03-30 11:25:47 -0700807 // With minor version 2, we want the target to be the new image, result_img,
808 // but with version 1, we want to update A in place.
809 if (minor_version == kSourceMinorPayloadVersion) {
810 EXPECT_EQ(0, (*performer)->Open(state->result_img.c_str(), 0, 0));
811 EXPECT_TRUE((*performer)->OpenKernel(state->result_kernel.c_str()));
812 } else {
813 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
814 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
815 }
816
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800817
David Zeuthena99981f2013-04-29 13:42:47 -0700818 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800819 bool continue_writing;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700820 switch (op_hash_test) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800821 case kInvalidOperationData: {
822 // Muck with some random offset post the metadata size so that
823 // some operation hash will result in a mismatch.
824 int some_offset = state->metadata_size + 300;
825 LOG(INFO) << "Tampered value at offset: " << some_offset;
826 state->delta[some_offset]++;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700827 expected_error = ErrorCode::kDownloadOperationHashMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800828 continue_writing = false;
829 break;
830 }
831
832 case kValidOperationData:
833 default:
834 // no change.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700835 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800836 continue_writing = true;
837 break;
838 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700839
840 // Write at some number of bytes per operation. Arbitrarily chose 5.
841 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800842 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
Alex Deymof329b932014-10-30 01:37:48 -0700843 size_t count = std::min(state->delta.size() - i, kBytesPerWrite);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800844 bool write_succeeded = ((*performer)->Write(&state->delta[i],
845 count,
846 &actual_error));
847 // Normally write_succeeded should be true every time and
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700848 // actual_error should be ErrorCode::kSuccess. If so, continue the loop.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800849 // But if we seeded an operation hash error above, then write_succeeded
850 // will be false. The failure may happen at any operation n. So, all
851 // Writes until n-1 should succeed and the nth operation will fail with
852 // actual_error. In this case, we should bail out of the loop because
853 // we cannot proceed applying the delta.
854 if (!write_succeeded) {
855 LOG(INFO) << "Write failed. Checking if it failed with expected error";
856 EXPECT_EQ(expected_error, actual_error);
857 if (!continue_writing) {
858 LOG(INFO) << "Cannot continue writing. Bailing out.";
859 break;
860 }
861 }
862
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700863 EXPECT_EQ(ErrorCode::kSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700864 }
865
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800866 // If we had continued all the way through, Close should succeed.
867 // Otherwise, it should fail. Check appropriately.
868 bool close_result = (*performer)->Close();
869 if (continue_writing)
870 EXPECT_EQ(0, close_result);
871 else
872 EXPECT_LE(0, close_result);
873}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700874
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800875void VerifyPayloadResult(DeltaPerformer* performer,
876 DeltaState* state,
Allie Wood9f6f0a52015-03-30 11:25:47 -0700877 ErrorCode expected_result,
878 uint32_t minor_version) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800879 if (!performer) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700880 EXPECT_TRUE(!"Skipping payload verification since performer is null.");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800881 return;
882 }
883
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700884 int expected_times = (expected_result == ErrorCode::kSuccess) ? 1 : 0;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700885 EXPECT_CALL(*(state->fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800886 DownloadComplete()).Times(expected_times);
887
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800888 LOG(INFO) << "Verifying payload for expected result "
889 << expected_result;
890 EXPECT_EQ(expected_result, performer->VerifyPayload(
891 OmahaHashCalculator::OmahaHashOfData(state->delta),
892 state->delta.size()));
893 LOG(INFO) << "Verified payload.";
894
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700895 if (expected_result != ErrorCode::kSuccess) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800896 // no need to verify new partition if VerifyPayload failed.
897 return;
898 }
899
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800900 chromeos::Blob updated_kernel_partition;
Allie Wood9f6f0a52015-03-30 11:25:47 -0700901 if (minor_version == kSourceMinorPayloadVersion) {
Alex Deymoda73df52015-07-22 13:53:29 -0700902 CompareFilesByBlock(state->result_kernel, state->new_kernel,
903 state->kernel_size);
904 CompareFilesByBlock(state->result_img, state->b_img,
905 state->image_size);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700906 EXPECT_TRUE(utils::ReadFile(state->result_kernel,
907 &updated_kernel_partition));
908 } else {
Alex Deymoda73df52015-07-22 13:53:29 -0700909 CompareFilesByBlock(state->old_kernel, state->new_kernel,
910 state->kernel_size);
911 CompareFilesByBlock(state->a_img, state->b_img,
912 state->image_size);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700913 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
914 }
915
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800916 ASSERT_GE(updated_kernel_partition.size(), arraysize(kNewData));
917 EXPECT_TRUE(std::equal(std::begin(kNewData), std::end(kNewData),
918 updated_kernel_partition.begin()));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700919
920 uint64_t new_kernel_size;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800921 chromeos::Blob new_kernel_hash;
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700922 uint64_t new_rootfs_size;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800923 chromeos::Blob new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800924 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Don Garrett0dd39852013-04-03 16:55:42 -0700925 &new_kernel_hash,
926 &new_rootfs_size,
927 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800928 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800929 chromeos::Blob expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800930 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700931 &expected_new_kernel_hash));
932 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800933 EXPECT_EQ(state->image_size, new_rootfs_size);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800934 chromeos::Blob expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800935 EXPECT_EQ(state->image_size,
936 OmahaHashCalculator::RawHashOfFile(state->b_img,
937 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700938 &expected_new_rootfs_hash));
939 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
940}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800941
942void VerifyPayload(DeltaPerformer* performer,
943 DeltaState* state,
Allie Wood9f6f0a52015-03-30 11:25:47 -0700944 SignatureTest signature_test,
945 uint32_t minor_version) {
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700946 ErrorCode expected_result = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800947 switch (signature_test) {
948 case kSignatureNone:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700949 expected_result = ErrorCode::kSignedDeltaPayloadExpectedError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800950 break;
951 case kSignatureGeneratedShellBadKey:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700952 expected_result = ErrorCode::kDownloadPayloadPubKeyVerificationError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800953 break;
954 default: break; // appease gcc
955 }
956
Allie Wood9f6f0a52015-03-30 11:25:47 -0700957 VerifyPayloadResult(performer, state, expected_result, minor_version);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800958}
959
960void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
Alex Deymo2d3b2d62015-07-17 17:34:36 -0700961 ssize_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800962 SignatureTest signature_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800963 bool hash_checks_mandatory, uint32_t minor_version) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800964 DeltaState state;
Alex Deymo52146ce2014-05-29 11:09:45 -0700965 DeltaPerformer *performer = nullptr;
Darin Petkov8e447e02013-04-16 16:23:50 +0200966 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
Allie Woodfdf00512015-03-02 13:34:55 -0800967 signature_test, &state, minor_version);
Don Garrett0dd39852013-04-03 16:55:42 -0700968
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800969 ScopedPathUnlinker a_img_unlinker(state.a_img);
970 ScopedPathUnlinker b_img_unlinker(state.b_img);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700971 ScopedPathUnlinker new_img_unlinker(state.result_img);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800972 ScopedPathUnlinker delta_unlinker(state.delta_path);
973 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
974 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700975 ScopedPathUnlinker result_kernel_unlinker(state.result_kernel);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800976 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
977 &state, hash_checks_mandatory, kValidOperationData,
Allie Woodfdf00512015-03-02 13:34:55 -0800978 &performer, minor_version);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700979 VerifyPayload(performer, &state, signature_test, minor_version);
Alex Deymo52146ce2014-05-29 11:09:45 -0700980 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800981}
982
983// Calls delta performer's Write method by pretending to pass in bytes from a
984// delta file whose metadata size is actual_metadata_size and tests if all
985// checks are correctly performed if the install plan contains
986// expected_metadata_size and that the result of the parsing are as per
987// hash_checks_mandatory flag.
988void DoMetadataSizeTest(uint64_t expected_metadata_size,
989 uint64_t actual_metadata_size,
990 bool hash_checks_mandatory) {
Alex Deymo8427b4a2014-11-05 14:00:32 -0800991 MockPrefs prefs;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800992 InstallPlan install_plan;
993 install_plan.hash_checks_mandatory = hash_checks_mandatory;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700994 FakeSystemState fake_system_state;
995 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800996 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
997 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
998
999 // Set a valid magic string and version number 1.
1000 EXPECT_TRUE(performer.Write("CrAU", 4));
1001 uint64_t version = htobe64(1);
1002 EXPECT_TRUE(performer.Write(&version, 8));
1003
1004 install_plan.metadata_size = expected_metadata_size;
David Zeuthena99981f2013-04-29 13:42:47 -07001005 ErrorCode error_code;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001006 // When filling in size in manifest, exclude the size of the 20-byte header.
1007 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
1008 bool result = performer.Write(&size_in_manifest, 8, &error_code);
1009 if (expected_metadata_size == actual_metadata_size ||
1010 !hash_checks_mandatory) {
1011 EXPECT_TRUE(result);
1012 } else {
1013 EXPECT_FALSE(result);
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001014 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001015 }
1016
1017 EXPECT_LT(performer.Close(), 0);
1018}
1019
1020// Generates a valid delta file but tests the delta performer by suppling
1021// different metadata signatures as per omaha_metadata_signature flag and
1022// sees if the result of the parsing are as per hash_checks_mandatory flag.
1023void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
Sen Jiangd78b3892015-09-25 15:19:31 -07001024 bool sign_payload,
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001025 bool hash_checks_mandatory) {
Sen Jiangd78b3892015-09-25 15:19:31 -07001026 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001027
1028 // Loads the payload and parses the manifest.
Sen Jiangd78b3892015-09-25 15:19:31 -07001029 chromeos::Blob payload = DeltaPerformerTest::GeneratePayload(chromeos::Blob(),
1030 vector<AnnotatedOperation>(), sign_payload,
1031 DeltaPerformer::kFullPayloadMinorVersion, &install_plan.metadata_size);
1032
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001033 LOG(INFO) << "Payload size: " << payload.size();
1034
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001035 install_plan.hash_checks_mandatory = hash_checks_mandatory;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001036
1037 DeltaPerformer::MetadataParseResult expected_result, actual_result;
David Zeuthena99981f2013-04-29 13:42:47 -07001038 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001039
1040 // Fill up the metadata signature in install plan according to the test.
1041 switch (metadata_signature_test) {
1042 case kEmptyMetadataSignature:
1043 install_plan.metadata_signature.clear();
1044 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001045 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001046 break;
1047
1048 case kInvalidMetadataSignature:
1049 install_plan.metadata_signature = kBogusMetadataSignature1;
1050 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001051 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001052 break;
1053
1054 case kValidMetadataSignature:
1055 default:
1056 // Set the install plan's metadata size to be the same as the one
1057 // in the manifest so that we pass the metadata size checks. Only
1058 // then we can get to manifest signature checks.
1059 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -07001060 payload.data(),
Sen Jiangd78b3892015-09-25 15:19:31 -07001061 install_plan.metadata_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001062 kUnittestPrivateKeyPath,
1063 &install_plan.metadata_signature));
1064 EXPECT_FALSE(install_plan.metadata_signature.empty());
1065 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001066 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001067 break;
1068 }
1069
1070 // Ignore the expected result/error if hash checks are not mandatory.
1071 if (!hash_checks_mandatory) {
1072 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001073 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001074 }
1075
1076 // Create the delta performer object.
Alex Deymo8427b4a2014-11-05 14:00:32 -08001077 MockPrefs prefs;
Sen Jiangd78b3892015-09-25 15:19:31 -07001078 FakeSystemState fake_system_state;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001079 DeltaPerformer delta_performer(&prefs,
Sen Jiangd78b3892015-09-25 15:19:31 -07001080 &fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001081 &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001082
1083 // Use the public key corresponding to the private key used above to
1084 // sign the metadata.
1085 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
1086 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
1087
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001088 // Init actual_error with an invalid value so that we make sure
1089 // ParsePayloadMetadata properly populates it in all cases.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001090 actual_error = ErrorCode::kUmaReportedMax;
Gilad Arnolddaa27402014-01-23 11:56:17 -08001091 actual_result = delta_performer.ParsePayloadMetadata(payload, &actual_error);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001092
1093 EXPECT_EQ(expected_result, actual_result);
1094 EXPECT_EQ(expected_error, actual_error);
1095
1096 // Check that the parsed metadata size is what's expected. This test
1097 // implicitly confirms that the metadata signature is valid, if required.
Sen Jiangd78b3892015-09-25 15:19:31 -07001098 EXPECT_EQ(install_plan.metadata_size, delta_performer.GetMetadataSize());
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001099}
1100
1101void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
1102 bool hash_checks_mandatory) {
1103 DeltaState state;
Allie Woodfdf00512015-03-02 13:34:55 -08001104 uint64_t minor_version = DeltaPerformer::kFullPayloadMinorVersion;
1105 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state,
1106 minor_version);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001107 ScopedPathUnlinker a_img_unlinker(state.a_img);
1108 ScopedPathUnlinker b_img_unlinker(state.b_img);
1109 ScopedPathUnlinker delta_unlinker(state.delta_path);
1110 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
1111 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Alex Deymo52146ce2014-05-29 11:09:45 -07001112 DeltaPerformer *performer = nullptr;
Allie Woodfdf00512015-03-02 13:34:55 -08001113 ApplyDeltaFile(true, true, false, kSignatureGenerated, &state,
1114 hash_checks_mandatory, op_hash_test, &performer,
1115 minor_version);
Alex Deymo52146ce2014-05-29 11:09:45 -07001116 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001117}
1118
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001119TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
Allie Wood56873452015-03-27 17:48:40 -07001120 uint64_t test[] = {1, 1, 4, 2, 0, 1};
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001121 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
1122 const uint64_t block_size = 4096;
Allie Wood56873452015-03-27 17:48:40 -07001123 const uint64_t file_length = 4 * block_size - 13;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001124
1125 google::protobuf::RepeatedPtrField<Extent> extents;
1126 for (size_t i = 0; i < arraysize(test); i += 2) {
1127 Extent* extent = extents.Add();
1128 extent->set_start_block(test[i]);
1129 extent->set_num_blocks(test[i + 1]);
1130 }
1131
Allie Wood56873452015-03-27 17:48:40 -07001132 string expected_output = "4096:4096,16384:8192,0:4083";
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001133 string actual_output;
1134 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
1135 block_size,
1136 file_length,
1137 &actual_output));
1138 EXPECT_EQ(expected_output, actual_output);
1139}
Darin Petkov68c10d12010-10-14 09:24:37 -07001140
Don Garrettb8dd1d92013-11-22 17:40:02 -08001141TEST(DeltaPerformerTest, ValidateManifestFullGoodTest) {
1142 // The Manifest we are validating.
1143 DeltaArchiveManifest manifest;
1144 manifest.mutable_new_kernel_info();
1145 manifest.mutable_new_rootfs_info();
1146 manifest.set_minor_version(DeltaPerformer::kFullPayloadMinorVersion);
1147
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001148 DeltaPerformerTest::RunManifestValidation(manifest, true,
1149 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001150}
1151
1152TEST(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
1153 // The Manifest we are validating.
1154 DeltaArchiveManifest manifest;
1155 manifest.mutable_old_kernel_info();
1156 manifest.mutable_old_rootfs_info();
1157 manifest.mutable_new_kernel_info();
1158 manifest.mutable_new_rootfs_info();
1159 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1160
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001161 DeltaPerformerTest::RunManifestValidation(manifest, false,
1162 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001163}
1164
1165TEST(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
1166 // The Manifest we are validating.
1167 DeltaArchiveManifest manifest;
1168
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001169 DeltaPerformerTest::RunManifestValidation(manifest, true,
1170 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001171}
1172
1173TEST(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
1174 // The Manifest we are validating.
1175 DeltaArchiveManifest manifest;
1176
1177 DeltaPerformerTest::RunManifestValidation(
1178 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001179 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001180}
1181
1182TEST(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
1183 // The Manifest we are validating.
1184 DeltaArchiveManifest manifest;
1185 manifest.mutable_old_kernel_info();
1186 manifest.mutable_new_kernel_info();
1187 manifest.mutable_new_rootfs_info();
1188 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1189
1190 DeltaPerformerTest::RunManifestValidation(
1191 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001192 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001193}
1194
1195TEST(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
1196 // The Manifest we are validating.
1197 DeltaArchiveManifest manifest;
1198 manifest.mutable_old_rootfs_info();
1199 manifest.mutable_new_kernel_info();
1200 manifest.mutable_new_rootfs_info();
1201 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1202
1203 DeltaPerformerTest::RunManifestValidation(
1204 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001205 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001206}
1207
1208TEST(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
1209 // The Manifest we are validating.
1210 DeltaArchiveManifest manifest;
1211
1212 // Generate a bad version number.
1213 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
1214 10000);
1215
1216 DeltaPerformerTest::RunManifestValidation(
1217 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001218 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001219}
1220
Darin Petkov68c10d12010-10-14 09:24:37 -07001221TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001222 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001223 false, kInPlaceMinorPayloadVersion);
Darin Petkov8e447e02013-04-16 16:23:50 +02001224}
1225
Don Garrett2ae37872013-10-25 13:33:20 -07001226TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
1227 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
Allie Woodfdf00512015-03-02 13:34:55 -08001228 false, kInPlaceMinorPayloadVersion);
Don Garrett2ae37872013-10-25 13:33:20 -07001229}
1230
1231TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
1232 DeltaState state;
1233 GenerateDeltaFile(false, false, false, -1,
Allie Woodfdf00512015-03-02 13:34:55 -08001234 kSignatureGeneratedPlaceholderMismatch, &state,
1235 kInPlaceMinorPayloadVersion);
Don Garrett2ae37872013-10-25 13:33:20 -07001236}
1237
Darin Petkov8e447e02013-04-16 16:23:50 +02001238TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001239 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001240 false, kInPlaceMinorPayloadVersion);
Darin Petkov68c10d12010-10-14 09:24:37 -07001241}
1242
1243TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001244 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001245 false, kInPlaceMinorPayloadVersion);
Darin Petkov7a22d792010-11-08 14:10:00 -08001246}
1247
1248TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001249 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001250 true, DeltaPerformer::kFullPayloadMinorVersion);
Darin Petkov9fa7ec52010-10-18 11:45:23 -07001251}
1252
1253TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001254 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001255 false, kInPlaceMinorPayloadVersion);
Darin Petkov9574f7e2011-01-13 10:48:12 -08001256}
1257
Darin Petkovcbfb0172011-01-14 15:24:45 -08001258TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001259 DoSmallImageTest(false, false, false, -1, kSignatureNone,
Allie Woodfdf00512015-03-02 13:34:55 -08001260 false, kInPlaceMinorPayloadVersion);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001261}
1262
1263TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001264 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
Allie Woodfdf00512015-03-02 13:34:55 -08001265 true, kInPlaceMinorPayloadVersion);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001266}
1267
1268TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001269 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
Allie Woodfdf00512015-03-02 13:34:55 -08001270 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -07001271}
1272
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001273TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001274 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
Allie Woodfdf00512015-03-02 13:34:55 -08001275 false, kInPlaceMinorPayloadVersion);
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001276}
1277
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001278TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001279 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
Allie Woodfdf00512015-03-02 13:34:55 -08001280 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001281}
1282
1283TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001284 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
Allie Woodfdf00512015-03-02 13:34:55 -08001285 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001286}
1287
Allie Wood9f6f0a52015-03-30 11:25:47 -07001288TEST(DeltaPerformerTest, RunAsRootSmallImageSourceOpsTest) {
1289 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
1290 false, kSourceMinorPayloadVersion);
1291}
1292
Darin Petkov934bb412010-11-18 11:21:35 -08001293TEST(DeltaPerformerTest, BadDeltaMagicTest) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001294 MockPrefs prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001295 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001296 FakeSystemState fake_system_state;
1297 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -08001298 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1299 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -08001300 EXPECT_TRUE(performer.Write("junk", 4));
1301 EXPECT_TRUE(performer.Write("morejunk", 8));
1302 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -08001303 EXPECT_LT(performer.Close(), 0);
1304}
1305
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001306TEST(DeltaPerformerTest, WriteUpdatesPayloadState) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001307 MockPrefs prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001308 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001309 FakeSystemState fake_system_state;
1310 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001311 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1312 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
1313
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001314 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001315 DownloadProgress(4)).Times(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001316 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001317 DownloadProgress(8)).Times(2);
1318
1319 EXPECT_TRUE(performer.Write("junk", 4));
1320 EXPECT_TRUE(performer.Write("morejunk", 8));
1321 EXPECT_FALSE(performer.Write("morejunk", 8));
1322 EXPECT_LT(performer.Close(), 0);
1323}
1324
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001325TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
1326 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001327}
1328
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001329TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
1330 DoMetadataSizeTest(0, 123456, false);
1331}
1332
1333TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
1334 DoMetadataSizeTest(13000, 140000, true);
1335}
1336
1337TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
1338 DoMetadataSizeTest(40000, 50000, false);
1339}
1340
1341TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
1342 DoMetadataSizeTest(85376, 85376, true);
1343}
1344
1345TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -07001346 DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001347}
1348
1349TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -07001350 DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001351}
1352
1353TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -07001354 DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001355}
1356
1357TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -07001358 DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001359}
1360
1361TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
Sen Jiangd78b3892015-09-25 15:19:31 -07001362 DoMetadataSignatureTest(kValidMetadataSignature, false, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001363}
1364
1365TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
Sen Jiangd78b3892015-09-25 15:19:31 -07001366 DoMetadataSignatureTest(kValidMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001367}
1368
1369TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -07001370 DoMetadataSignatureTest(kValidMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001371}
1372
1373TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
1374 DoOperationHashMismatchTest(kInvalidOperationData, true);
1375}
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001376
David Zeuthene7f89172013-10-31 10:21:04 -07001377TEST(DeltaPerformerTest, UsePublicKeyFromResponse) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001378 MockPrefs prefs;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001379 FakeSystemState fake_system_state;
David Zeuthene7f89172013-10-31 10:21:04 -07001380 InstallPlan install_plan;
1381 base::FilePath key_path;
1382
1383 // The result of the GetPublicKeyResponse() method is based on three things
1384 //
1385 // 1. Whether it's an official build; and
1386 // 2. Whether the Public RSA key to be used is in the root filesystem; and
Alex Vakulenko072359c2014-07-18 11:41:07 -07001387 // 3. Whether the response has a public key
David Zeuthene7f89172013-10-31 10:21:04 -07001388 //
1389 // We test all eight combinations to ensure that we only use the
1390 // public key in the response if
1391 //
1392 // a. it's not an official build; and
1393 // b. there is no key in the root filesystem.
1394
1395 DeltaPerformer *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001396 &fake_system_state,
David Zeuthene7f89172013-10-31 10:21:04 -07001397 &install_plan);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001398 FakeHardware* fake_hardware = fake_system_state.fake_hardware();
David Zeuthene7f89172013-10-31 10:21:04 -07001399
1400 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -08001401 EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
David Zeuthene7f89172013-10-31 10:21:04 -07001402 &temp_dir));
1403 string non_existing_file = temp_dir + "/non-existing";
1404 string existing_file = temp_dir + "/existing";
Alex Vakulenko75039d72014-03-25 12:36:28 -07001405 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
David Zeuthene7f89172013-10-31 10:21:04 -07001406
1407 // Non-official build, non-existing public-key, key in response -> true
Don Garrett6646b442013-11-13 15:29:11 -08001408 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001409 performer->public_key_path_ = non_existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001410 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001411 EXPECT_TRUE(performer->GetPublicKeyFromResponse(&key_path));
1412 EXPECT_FALSE(key_path.empty());
1413 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
1414 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001415 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001416 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1417
1418 // Non-official build, existing public-key, key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001419 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001420 performer->public_key_path_ = existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001421 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001422 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1423 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001424 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001425 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1426
1427 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001428 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001429 performer->public_key_path_ = non_existing_file;
1430 install_plan.public_key_rsa = "";
1431 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1432 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001433 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001434 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1435
1436 // Non-official build, existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001437 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001438 performer->public_key_path_ = existing_file;
1439 install_plan.public_key_rsa = "";
1440 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1441 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001442 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001443 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1444
1445 // Non-official build, non-existing public-key, key in response
1446 // but invalid base64 -> false
Don Garrett6646b442013-11-13 15:29:11 -08001447 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001448 performer->public_key_path_ = non_existing_file;
1449 install_plan.public_key_rsa = "not-valid-base64";
1450 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1451
1452 delete performer;
Alex Deymo10875d92014-11-10 21:52:57 -08001453 EXPECT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
David Zeuthene7f89172013-10-31 10:21:04 -07001454}
1455
Allie Wood78750a42015-02-11 15:42:11 -08001456TEST(DeltaPerformerTest, MinorVersionsMatch) {
1457 // Test that the minor version in update_engine.conf that is installed to
1458 // the image matches the supported delta minor version in the update engine.
1459 uint32_t minor_version;
Alex Deymob42b98d2015-07-06 17:42:38 -07001460 chromeos::KeyValueStore store;
1461 EXPECT_TRUE(store.Load(base::FilePath("update_engine.conf")));
1462 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
1463 EXPECT_EQ(DeltaPerformer::kSupportedMinorPayloadVersion, minor_version);
Allie Wood78750a42015-02-11 15:42:11 -08001464}
1465
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001466} // namespace chromeos_update_engine