blob: f0f399d85664b556bfa44f19bffb01553daadd04 [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"
Alex Deymo923d8fa2014-07-15 17:58:51 -070039#include "update_engine/payload_generator/payload_signer.h"
40#include "update_engine/payload_verifier.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070041#include "update_engine/test_utils.h"
42#include "update_engine/update_metadata.pb.h"
43#include "update_engine/utils.h"
44
45namespace chromeos_update_engine {
46
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070047using std::string;
48using std::vector;
Darin Petkov73058b42010-10-06 16:32:19 -070049using testing::Return;
Alex Deymo161c4a12014-05-16 15:56:21 -070050using testing::_;
Alex Deymo10875d92014-11-10 21:52:57 -080051using test_utils::kRandomString;
52using test_utils::ScopedLoopMounter;
53using test_utils::System;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070054
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070055extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070056extern const char* kUnittestPublicKeyPath;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070057extern const char* kUnittestPrivateKey2Path;
58extern const char* kUnittestPublicKey2Path;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070059
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -070060static const char* kBogusMetadataSignature1 =
61 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
62 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
63 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
64 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
65 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
66 "pLRtClp97kN2+tXGNBQqkA==";
Jay Srinivasan738fdf32012-12-07 17:40:54 -080067
Alex Vakulenkod2779df2014-06-16 13:19:00 -070068static const int kDefaultKernelSize = 4096; // Something small for a test
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080069static const uint8_t kNewData[] = {'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
70 'n', 'e', 'w', ' ', 'd', 'a', 't', 'a', '.'};
Jay Srinivasan738fdf32012-12-07 17:40:54 -080071
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070072namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080073struct DeltaState {
74 string a_img;
75 string b_img;
Allie Wood9f6f0a52015-03-30 11:25:47 -070076 string result_img;
Alex Deymoda73df52015-07-22 13:53:29 -070077 size_t image_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070078
Jay Srinivasan738fdf32012-12-07 17:40:54 -080079 string delta_path;
80 uint64_t metadata_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070081
Jay Srinivasan738fdf32012-12-07 17:40:54 -080082 string old_kernel;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080083 chromeos::Blob old_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070084
Jay Srinivasan738fdf32012-12-07 17:40:54 -080085 string new_kernel;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080086 chromeos::Blob new_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070087
Allie Wood9f6f0a52015-03-30 11:25:47 -070088 string result_kernel;
89 chromeos::Blob result_kernel_data;
Alex Deymoda73df52015-07-22 13:53:29 -070090 size_t kernel_size;
Allie Wood9f6f0a52015-03-30 11:25:47 -070091
Jay Srinivasan738fdf32012-12-07 17:40:54 -080092 // The in-memory copy of delta file.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080093 chromeos::Blob delta;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080094
95 // The mock system state object with which we initialize the
96 // delta performer.
Gilad Arnold5bb4c902014-04-10 12:32:13 -070097 FakeSystemState fake_system_state;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080098};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070099
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800100enum SignatureTest {
101 kSignatureNone, // No payload signing.
102 kSignatureGenerator, // Sign the payload at generation time.
103 kSignatureGenerated, // Sign the payload after it's generated.
Don Garrett2ae37872013-10-25 13:33:20 -0700104 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700105 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800106 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
107 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
108 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
109 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
110};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700111
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800112// Different options that determine what we should fill into the
113// install_plan.metadata_signature to simulate the contents received in the
114// Omaha response.
115enum MetadataSignatureTest {
116 kEmptyMetadataSignature,
117 kInvalidMetadataSignature,
118 kValidMetadataSignature,
119};
120
121enum OperationHashTest {
122 kInvalidOperationData,
123 kValidOperationData,
124};
125
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700126} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800127
Allie Woodfdf00512015-03-02 13:34:55 -0800128class DeltaPerformerTest : public ::testing::Test {
129 public:
130 // Test helper placed where it can easily be friended from DeltaPerformer.
131 static void RunManifestValidation(const DeltaArchiveManifest& manifest,
132 bool full_payload,
133 ErrorCode expected) {
134 MockPrefs prefs;
135 InstallPlan install_plan;
136 FakeSystemState fake_system_state;
137 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
138
139 // The install plan is for Full or Delta.
140 install_plan.is_full_update = full_payload;
141
142 // The Manifest we are validating.
143 performer.manifest_.CopyFrom(manifest);
144
145 EXPECT_EQ(expected, performer.ValidateManifest());
146 }
147
148 static void SetSupportedVersion(DeltaPerformer* performer,
149 uint64_t minor_version) {
150 performer->supported_minor_version_ = minor_version;
151 }
152};
153
Alex Deymoda73df52015-07-22 13:53:29 -0700154static void CompareFilesByBlock(const string& a_file, const string& b_file,
155 size_t image_size) {
156 EXPECT_EQ(0, image_size % kBlockSize);
157
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800158 chromeos::Blob a_data, b_data;
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700159 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
160 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700161
Alex Deymoda73df52015-07-22 13:53:29 -0700162 EXPECT_GE(a_data.size(), image_size);
163 EXPECT_GE(b_data.size(), image_size);
164 for (size_t i = 0; i < image_size; i += kBlockSize) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700165 EXPECT_EQ(0, i % kBlockSize);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800166 chromeos::Blob a_sub(&a_data[i], &a_data[i + kBlockSize]);
167 chromeos::Blob b_sub(&b_data[i], &b_data[i + kBlockSize]);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700168 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
169 }
Alex Deymoda73df52015-07-22 13:53:29 -0700170 if (::testing::Test::HasNonfatalFailure()) {
171 LOG(INFO) << "Compared filesystems with size " << image_size
172 << ", partition A " << a_file << " size: " << a_data.size()
173 << ", partition B " << b_file << " size: " << b_data.size();
174 }
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700175}
176
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800177static bool WriteSparseFile(const string& path, off_t size) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700178 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
179 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
180 ScopedFdCloser fd_closer(&fd);
181 off_t rc = lseek(fd, size + 1, SEEK_SET);
182 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
183 int return_code = ftruncate(fd, size);
184 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
185 return true;
186}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700187
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800188static size_t GetSignatureSize(const string& private_key_path) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800189 const chromeos::Blob data(1, 'x');
190 chromeos::Blob hash;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800191 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(data, &hash));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800192 chromeos::Blob signature;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800193 EXPECT_TRUE(PayloadSigner::SignHash(hash,
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800194 private_key_path,
Darin Petkovcbfb0172011-01-14 15:24:45 -0800195 &signature));
196 return signature.size();
197}
198
Don Garrett2ae37872013-10-25 13:33:20 -0700199static bool InsertSignaturePlaceholder(int signature_size,
200 const string& payload_path,
201 uint64_t* out_metadata_size) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800202 vector<chromeos::Blob> signatures;
203 signatures.push_back(chromeos::Blob(signature_size, 0));
Don Garrett2ae37872013-10-25 13:33:20 -0700204
205 return PayloadSigner::AddSignatureToPayload(
206 payload_path,
207 signatures,
208 payload_path,
209 out_metadata_size);
210}
211
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800212static void SignGeneratedPayload(const string& payload_path,
213 uint64_t* out_metadata_size) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800214 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800215 chromeos::Blob hash;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700216 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
217 payload_path,
218 vector<int>(1, signature_size),
219 &hash));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800220 chromeos::Blob signature;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800221 ASSERT_TRUE(PayloadSigner::SignHash(hash,
222 kUnittestPrivateKeyPath,
223 &signature));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700224 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
225 payload_path,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800226 vector<chromeos::Blob>(1, signature),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800227 payload_path,
228 out_metadata_size));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700229 EXPECT_TRUE(PayloadVerifier::VerifySignedPayload(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700230 payload_path,
231 kUnittestPublicKeyPath,
232 kSignatureMessageOriginalVersion));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800233}
234
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800235static void SignGeneratedShellPayload(SignatureTest signature_test,
236 const string& payload_path) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800237 string private_key_path = kUnittestPrivateKeyPath;
238 if (signature_test == kSignatureGeneratedShellBadKey) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800239 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800240 &private_key_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700241 nullptr));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800242 } else {
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700243 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
244 signature_test == kSignatureGeneratedShellRotateCl1 ||
245 signature_test == kSignatureGeneratedShellRotateCl2);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800246 }
247 ScopedPathUnlinker key_unlinker(private_key_path);
248 key_unlinker.set_should_remove(signature_test ==
249 kSignatureGeneratedShellBadKey);
250 // Generates a new private key that will not match the public key.
251 if (signature_test == kSignatureGeneratedShellBadKey) {
252 LOG(INFO) << "Generating a mismatched private key.";
Alex Deymo719bfff2014-07-11 12:12:32 -0700253 ASSERT_EQ(0, System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400254 "openssl genrsa -out %s 2048", private_key_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800255 }
256 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800257 string hash_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700258 ASSERT_TRUE(utils::MakeTempFile("hash.XXXXXX", &hash_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800259 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700260 string signature_size_string;
261 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
262 signature_test == kSignatureGeneratedShellRotateCl2)
Alex Vakulenko75039d72014-03-25 12:36:28 -0700263 signature_size_string = base::StringPrintf("%d:%d",
264 signature_size, signature_size);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700265 else
Alex Vakulenko75039d72014-03-25 12:36:28 -0700266 signature_size_string = base::StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800267 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700268 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700269 "./delta_generator -in_file=%s -signature_size=%s "
270 "-out_hash_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800271 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700272 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800273 hash_file.c_str())));
274
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700275 // Pad the hash
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800276 chromeos::Blob hash;
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700277 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700278 ASSERT_TRUE(PayloadVerifier::PadRSA2048SHA256Hash(&hash));
Alex Deymo10875d92014-11-10 21:52:57 -0800279 ASSERT_TRUE(test_utils::WriteFileVector(hash_file, hash));
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700280
Darin Petkovcbfb0172011-01-14 15:24:45 -0800281 string sig_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700282 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800283 ScopedPathUnlinker sig_unlinker(sig_file);
284 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700285 System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400286 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800287 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800288 hash_file.c_str(),
289 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700290 string sig_file2;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700291 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file2, nullptr));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700292 ScopedPathUnlinker sig2_unlinker(sig_file2);
293 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
294 signature_test == kSignatureGeneratedShellRotateCl2) {
295 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700296 System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400297 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700298 kUnittestPrivateKey2Path,
299 hash_file.c_str(),
300 sig_file2.c_str())));
301 // Append second sig file to first path
302 sig_file += ":" + sig_file2;
303 }
304
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_file=%s "
308 "-out_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800309 payload_path.c_str(),
310 sig_file.c_str(),
311 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800312 int verify_result =
Alex Vakulenko75039d72014-03-25 12:36:28 -0700313 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700314 "./delta_generator -in_file=%s -public_key=%s -public_key_version=%d",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700315 payload_path.c_str(),
316 signature_test == kSignatureGeneratedShellRotateCl2 ?
317 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
318 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800319 if (signature_test == kSignatureGeneratedShellBadKey) {
320 ASSERT_NE(0, verify_result);
321 } else {
322 ASSERT_EQ(0, verify_result);
323 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800324}
325
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800326static void GenerateDeltaFile(bool full_kernel,
327 bool full_rootfs,
328 bool noop,
Alex Deymo2d3b2d62015-07-17 17:34:36 -0700329 ssize_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800330 SignatureTest signature_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800331 DeltaState *state,
332 uint32_t minor_version) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700333 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
334 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
Allie Wood9f6f0a52015-03-30 11:25:47 -0700335
336 // result_img is used in minor version 2. Instead of applying the update
337 // in-place on A, we apply it to a new image, result_img.
338 EXPECT_TRUE(
339 utils::MakeTempFile("result_img.XXXXXX", &state->result_img, nullptr));
Alex Deymo10875d92014-11-10 21:52:57 -0800340 test_utils::CreateExtImageAtPath(state->a_img, nullptr);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700341
Alex Deymoda73df52015-07-22 13:53:29 -0700342 state->image_size = utils::FileSize(state->a_img);
Darin Petkov7ea32332010-10-13 10:46:11 -0700343
344 // Extend the "partitions" holding the file system a bit.
Alex Deymoda73df52015-07-22 13:53:29 -0700345 EXPECT_EQ(0, HANDLE_EINTR(truncate(state->a_img.c_str(),
346 state->image_size + 1024 * 1024)));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800347 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700348
Don Garrett0dd39852013-04-03 16:55:42 -0700349 // Create ImageInfo A & B
350 ImageInfo old_image_info;
351 ImageInfo new_image_info;
352
353 if (!full_rootfs) {
354 old_image_info.set_channel("src-channel");
355 old_image_info.set_board("src-board");
356 old_image_info.set_version("src-version");
357 old_image_info.set_key("src-key");
358 old_image_info.set_build_channel("src-build-channel");
359 old_image_info.set_build_version("src-build-version");
360 }
361
362 new_image_info.set_channel("test-channel");
363 new_image_info.set_board("test-board");
364 new_image_info.set_version("test-version");
365 new_image_info.set_key("test-key");
366 new_image_info.set_build_channel("test-build-channel");
367 new_image_info.set_build_version("test-build-version");
368
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700369 // Make some changes to the A image.
370 {
371 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800372 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700373
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800374 chromeos::Blob hardtocompress;
Darin Petkov8e447e02013-04-16 16:23:50 +0200375 while (hardtocompress.size() < 3 * kBlockSize) {
376 hardtocompress.insert(hardtocompress.end(),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800377 std::begin(kRandomString), std::end(kRandomString));
Darin Petkov8e447e02013-04-16 16:23:50 +0200378 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700379 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800380 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700381 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200382 hardtocompress.size()));
383
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800384 chromeos::Blob zeros(16 * 1024, 0);
Darin Petkov8a075a72013-04-25 14:46:09 +0200385 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700386 base::WriteFile(base::FilePath(base::StringPrintf(
387 "%s/move-to-sparse", a_mnt.c_str())),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800388 reinterpret_cast<const char*>(zeros.data()),
389 zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200390
391 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700392 WriteSparseFile(base::StringPrintf("%s/move-from-sparse",
393 a_mnt.c_str()), 16 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200394
Alex Vakulenko75039d72014-03-25 12:36:28 -0700395 EXPECT_EQ(0,
Alex Deymo10875d92014-11-10 21:52:57 -0800396 System(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
Alex Deymo1f93d032015-03-10 18:58:32 -0700397 " bs=1 seek=4096 count=1 status=none",
Alex Deymo10875d92014-11-10 21:52:57 -0800398 a_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200399
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700400 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
401 // patch fails to zero out the final block.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800402 chromeos::Blob ones(1024 * 1024, 0xff);
Alex Vakulenko75039d72014-03-25 12:36:28 -0700403 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/ones",
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800404 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700405 ones.data(),
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700406 ones.size()));
407 }
408
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700409 if (noop) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700410 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img),
411 base::FilePath(state->b_img)));
Don Garrett0dd39852013-04-03 16:55:42 -0700412 old_image_info = new_image_info;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700413 } else {
Allie Wood9f6f0a52015-03-30 11:25:47 -0700414 if (minor_version == kSourceMinorPayloadVersion) {
415 // Create a result image with image_size bytes of garbage, followed by
416 // zeroes after the rootfs, like image A and B have.
417 chromeos::Blob ones(state->image_size, 0xff);
418 ones.insert(ones.end(), 1024 * 1024, 0);
419 EXPECT_TRUE(utils::WriteFile(state->result_img.c_str(),
420 ones.data(),
421 ones.size()));
422 EXPECT_EQ(utils::FileSize(state->a_img),
423 utils::FileSize(state->result_img));
424 }
425
Alex Deymo10875d92014-11-10 21:52:57 -0800426 test_utils::CreateExtImageAtPath(state->b_img, nullptr);
Alex Deymoda73df52015-07-22 13:53:29 -0700427 EXPECT_EQ(0, HANDLE_EINTR(truncate(state->b_img.c_str(),
428 state->image_size + 1024 * 1024)));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800429 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700430
431 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700432 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800433 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700434
Alex Deymo10875d92014-11-10 21:52:57 -0800435 EXPECT_EQ(0, System(base::StringPrintf("cp %s/hello %s/hello2",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700436 b_mnt.c_str(),
437 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800438 EXPECT_EQ(0, System(base::StringPrintf("rm %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700439 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800440 EXPECT_EQ(0, System(base::StringPrintf("mv %s/hello2 %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700441 b_mnt.c_str(),
442 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800443 EXPECT_EQ(0, System(base::StringPrintf("echo foo > %s/foo",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700444 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800445 EXPECT_EQ(0, System(base::StringPrintf("touch %s/emptyfile",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700446 b_mnt.c_str()).c_str()));
447 EXPECT_TRUE(WriteSparseFile(base::StringPrintf("%s/fullsparse",
448 b_mnt.c_str()),
449 1024 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200450
451 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700452 WriteSparseFile(base::StringPrintf("%s/move-to-sparse", b_mnt.c_str()),
Darin Petkov8a075a72013-04-25 14:46:09 +0200453 16 * 1024));
454
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800455 chromeos::Blob zeros(16 * 1024, 0);
Darin Petkov8a075a72013-04-25 14:46:09 +0200456 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700457 base::WriteFile(base::FilePath(base::StringPrintf(
458 "%s/move-from-sparse", b_mnt.c_str())),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800459 reinterpret_cast<const char*>(zeros.data()),
460 zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200461
Alex Deymo10875d92014-11-10 21:52:57 -0800462 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700463 "of=%s/move-semi-sparse "
Alex Deymo1f93d032015-03-10 18:58:32 -0700464 "bs=1 seek=4096 count=1 status=none",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700465 b_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200466
Alex Deymo10875d92014-11-10 21:52:57 -0800467 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700468 "of=%s/partsparse bs=1 "
Alex Deymo1f93d032015-03-10 18:58:32 -0700469 "seek=4096 count=1 status=none",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700470 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800471 EXPECT_EQ(0, System(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700472 "mv %s/tmp %s/srchardlink1",
473 b_mnt.c_str(),
474 b_mnt.c_str(),
475 b_mnt.c_str(),
476 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800477 EXPECT_EQ(0, System(
478 base::StringPrintf("rm %s/boguslink && echo foobar > %s/boguslink",
479 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Darin Petkov8e447e02013-04-16 16:23:50 +0200480
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800481 chromeos::Blob hardtocompress;
Darin Petkov8e447e02013-04-16 16:23:50 +0200482 while (hardtocompress.size() < 3 * kBlockSize) {
483 hardtocompress.insert(hardtocompress.end(),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800484 std::begin(kRandomString), std::end(kRandomString));
Darin Petkov8e447e02013-04-16 16:23:50 +0200485 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700486 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700487 b_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700488 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200489 hardtocompress.size()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700490 }
491
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700492 string old_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800493 EXPECT_TRUE(utils::MakeTempFile("old_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800494 &state->old_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700495 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700496
497 string new_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800498 EXPECT_TRUE(utils::MakeTempFile("new_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800499 &state->new_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700500 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700501
Allie Wood9f6f0a52015-03-30 11:25:47 -0700502 string result_kernel;
503 EXPECT_TRUE(utils::MakeTempFile("result_kernel.XXXXXX",
504 &state->result_kernel,
505 nullptr));
506
Alex Deymoda73df52015-07-22 13:53:29 -0700507 state->kernel_size = kDefaultKernelSize;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800508 state->old_kernel_data.resize(kDefaultKernelSize);
509 state->new_kernel_data.resize(state->old_kernel_data.size());
Allie Wood9f6f0a52015-03-30 11:25:47 -0700510 state->result_kernel_data.resize(state->old_kernel_data.size());
Alex Deymo10875d92014-11-10 21:52:57 -0800511 test_utils::FillWithData(&state->old_kernel_data);
512 test_utils::FillWithData(&state->new_kernel_data);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700513 test_utils::FillWithData(&state->result_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700514
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700515 // change the new kernel data
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800516 std::copy(std::begin(kNewData), std::end(kNewData),
517 state->new_kernel_data.begin());
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700518
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700519 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800520 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700521 }
522
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700523 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800524 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700525 state->old_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800526 state->old_kernel_data.size()));
527 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700528 state->new_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800529 state->new_kernel_data.size()));
Allie Wood9f6f0a52015-03-30 11:25:47 -0700530 EXPECT_TRUE(utils::WriteFile(state->result_kernel.c_str(),
531 state->result_kernel_data.data(),
532 state->result_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700533
Gilad Arnolda6742b32014-01-11 00:18:34 -0800534 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800535 &state->delta_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700536 nullptr));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800537 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700538 {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800539 const string private_key =
540 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Alex Deymof1cbe172015-03-05 15:58:37 -0800541
542 PayloadGenerationConfig payload_config;
543 payload_config.is_delta = !full_rootfs;
Alex Deymo2d3b2d62015-07-17 17:34:36 -0700544 payload_config.hard_chunk_size = chunk_size;
Alex Deymo9b244df2015-03-11 21:51:18 -0700545 payload_config.rootfs_partition_size = kRootFSPartitionSize;
Sen Jiang46e9b172015-08-31 14:11:01 -0700546 payload_config.major_version = kChromeOSMajorPayloadVersion;
Allie Woodfdf00512015-03-02 13:34:55 -0800547 payload_config.minor_version = minor_version;
Alex Deymof1cbe172015-03-05 15:58:37 -0800548 if (!full_rootfs) {
Alex Deymo35589c22015-06-07 17:33:18 +0200549 payload_config.source.rootfs.path = state->a_img;
Alex Deymof1cbe172015-03-05 15:58:37 -0800550 if (!full_kernel)
Alex Deymo35589c22015-06-07 17:33:18 +0200551 payload_config.source.kernel.path = state->old_kernel;
Alex Deymof1cbe172015-03-05 15:58:37 -0800552 payload_config.source.image_info = old_image_info;
553 EXPECT_TRUE(payload_config.source.LoadImageSize());
Alex Deymob42b98d2015-07-06 17:42:38 -0700554 EXPECT_TRUE(payload_config.source.rootfs.OpenFilesystem());
555 EXPECT_TRUE(payload_config.source.kernel.OpenFilesystem());
Alex Deymof1cbe172015-03-05 15:58:37 -0800556 } else {
Alex Deymo2d3b2d62015-07-17 17:34:36 -0700557 if (payload_config.hard_chunk_size == -1)
558 // Use 1 MiB chunk size for the full unittests.
559 payload_config.hard_chunk_size = 1024 * 1024;
Alex Deymof1cbe172015-03-05 15:58:37 -0800560 }
Alex Deymo35589c22015-06-07 17:33:18 +0200561 payload_config.target.rootfs.path = state->b_img;
562 payload_config.target.kernel.path = state->new_kernel;
Alex Deymof1cbe172015-03-05 15:58:37 -0800563 payload_config.target.image_info = new_image_info;
564 EXPECT_TRUE(payload_config.target.LoadImageSize());
Alex Deymob42b98d2015-07-06 17:42:38 -0700565 EXPECT_TRUE(payload_config.target.rootfs.OpenFilesystem());
566 EXPECT_TRUE(payload_config.target.kernel.OpenFilesystem());
Alex Deymof1cbe172015-03-05 15:58:37 -0800567
568 EXPECT_TRUE(payload_config.Validate());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700569 EXPECT_TRUE(
Alex Deymo477aec22015-03-24 23:40:48 -0700570 GenerateUpdatePayloadFile(
Alex Deymof1cbe172015-03-05 15:58:37 -0800571 payload_config,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800572 state->delta_path,
573 private_key,
574 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800575 }
576
Don Garrett2ae37872013-10-25 13:33:20 -0700577 if (signature_test == kSignatureGeneratedPlaceholder ||
578 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Don Garrett2ae37872013-10-25 13:33:20 -0700579 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
580 LOG(INFO) << "Inserting placeholder signature.";
581 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
582 &state->metadata_size));
583
584 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
585 signature_size -= 1;
586 LOG(INFO) << "Inserting mismatched placeholder signature.";
587 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
588 &state->metadata_size));
589 return;
590 }
591 }
592
593 if (signature_test == kSignatureGenerated ||
594 signature_test == kSignatureGeneratedPlaceholder ||
595 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800596 // Generate the signed payload and update the metadata size in state to
597 // reflect the new size after adding the signature operation to the
598 // manifest.
Don Garrett2ae37872013-10-25 13:33:20 -0700599 LOG(INFO) << "Signing payload.";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800600 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800601 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700602 signature_test == kSignatureGeneratedShellBadKey ||
603 signature_test == kSignatureGeneratedShellRotateCl1 ||
604 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800605 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700606 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800607}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700608
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800609static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
610 SignatureTest signature_test, DeltaState* state,
611 bool hash_checks_mandatory,
612 OperationHashTest op_hash_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800613 DeltaPerformer** performer,
614 uint32_t minor_version) {
Darin Petkov36a58222010-10-07 22:00:09 -0700615 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700616 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700617 DeltaArchiveManifest manifest;
Alex Deymo923d8fa2014-07-15 17:58:51 -0700618 EXPECT_TRUE(PayloadVerifier::LoadPayload(state->delta_path,
619 &state->delta,
620 &manifest,
621 &state->metadata_size));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800622 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700623
Don Garrett0dd39852013-04-03 16:55:42 -0700624
625
Darin Petkovcbfb0172011-01-14 15:24:45 -0800626 if (signature_test == kSignatureNone) {
627 EXPECT_FALSE(manifest.has_signatures_offset());
628 EXPECT_FALSE(manifest.has_signatures_size());
629 } else {
630 EXPECT_TRUE(manifest.has_signatures_offset());
631 EXPECT_TRUE(manifest.has_signatures_size());
632 Signatures sigs_message;
633 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800634 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800635 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700636 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
637 signature_test == kSignatureGeneratedShellRotateCl2)
638 EXPECT_EQ(2, sigs_message.signatures_size());
639 else
640 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800641 const Signatures_Signature& signature = sigs_message.signatures(0);
642 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700643
Darin Petkovcbfb0172011-01-14 15:24:45 -0800644 uint64_t expected_sig_data_length = 0;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700645 vector<string> key_paths{kUnittestPrivateKeyPath};
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700646 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
647 signature_test == kSignatureGeneratedShellRotateCl2) {
648 key_paths.push_back(kUnittestPrivateKey2Path);
649 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800650 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700651 key_paths,
652 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800653 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
654 EXPECT_FALSE(signature.data().empty());
655 }
Darin Petkov36a58222010-10-07 22:00:09 -0700656
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700657 if (noop) {
Gilad Arnold063181c2015-02-05 12:24:49 -0800658 EXPECT_EQ(0, manifest.install_operations_size());
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700659 EXPECT_EQ(1, manifest.kernel_install_operations_size());
660 }
661
Darin Petkovd43d6902010-10-14 11:17:50 -0700662 if (full_kernel) {
663 EXPECT_FALSE(manifest.has_old_kernel_info());
664 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800665 EXPECT_EQ(state->old_kernel_data.size(),
666 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700667 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
668 }
Darin Petkov698d0412010-10-13 10:59:44 -0700669
Don Garrett0dd39852013-04-03 16:55:42 -0700670 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
671 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
672 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
673 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
674 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
675 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
676
677 if (!full_rootfs) {
Don Garrett0dd39852013-04-03 16:55:42 -0700678 if (noop) {
679 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
680 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
681 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
682 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
683 EXPECT_EQ(manifest.old_image_info().build_channel(),
684 "test-build-channel");
685 EXPECT_EQ(manifest.old_image_info().build_version(),
686 "test-build-version");
687 } else {
688 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
689 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
690 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
691 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
692 EXPECT_EQ(manifest.old_image_info().build_channel(),
693 "src-build-channel");
694 EXPECT_EQ(manifest.old_image_info().build_version(),
695 "src-build-version");
696 }
697 }
698
699
Darin Petkov7a22d792010-11-08 14:10:00 -0800700 if (full_rootfs) {
701 EXPECT_FALSE(manifest.has_old_rootfs_info());
Don Garrett0dd39852013-04-03 16:55:42 -0700702 EXPECT_FALSE(manifest.has_old_image_info());
703 EXPECT_TRUE(manifest.has_new_image_info());
Darin Petkov7a22d792010-11-08 14:10:00 -0800704 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800705 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800706 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
707 }
708
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800709 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
710 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700711
Darin Petkov36a58222010-10-07 22:00:09 -0700712 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700713 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700714 }
715
Alex Deymo8427b4a2014-11-05 14:00:32 -0800716 MockPrefs prefs;
Darin Petkov73058b42010-10-06 16:32:19 -0700717 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800718 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700719 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
720 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700721 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
722 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700723 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
724 .WillRepeatedly(Return(true));
David Zeuthen41996ad2013-09-24 15:43:24 -0700725 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
726 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700727 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700728 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800729 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800730 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
731 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700732 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
733 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800734 }
Darin Petkov73058b42010-10-06 16:32:19 -0700735
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700736 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700737 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800738 install_plan.hash_checks_mandatory = hash_checks_mandatory;
739 install_plan.metadata_size = state->metadata_size;
Don Garrettb8dd1d92013-11-22 17:40:02 -0800740 install_plan.is_full_update = full_kernel && full_rootfs;
Allie Woodfdf00512015-03-02 13:34:55 -0800741 install_plan.source_path = state->a_img.c_str();
742 install_plan.kernel_source_path = state->old_kernel.c_str();
Don Garrettb8dd1d92013-11-22 17:40:02 -0800743
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800744 LOG(INFO) << "Setting payload metadata size in Omaha = "
745 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700746 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700747 state->delta.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800748 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700749 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700750 &install_plan.metadata_signature));
751 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700752
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800753 *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700754 &state->fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800755 &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700756 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800757 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Allie Woodfdf00512015-03-02 13:34:55 -0800758 DeltaPerformerTest::SetSupportedVersion(*performer, minor_version);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700759
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800760 EXPECT_EQ(state->image_size,
Allie Woodeb9e6d82015-04-17 13:55:30 -0700761 OmahaHashCalculator::RawHashOfFile(
762 state->a_img,
763 state->image_size,
764 &install_plan.source_rootfs_hash));
765 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(
766 state->old_kernel_data,
767 &install_plan.source_kernel_hash));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700768
Allie Wood9f6f0a52015-03-30 11:25:47 -0700769 // With minor version 2, we want the target to be the new image, result_img,
770 // but with version 1, we want to update A in place.
771 if (minor_version == kSourceMinorPayloadVersion) {
772 EXPECT_EQ(0, (*performer)->Open(state->result_img.c_str(), 0, 0));
773 EXPECT_TRUE((*performer)->OpenKernel(state->result_kernel.c_str()));
774 } else {
775 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
776 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
777 }
778
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800779
David Zeuthena99981f2013-04-29 13:42:47 -0700780 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800781 bool continue_writing;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700782 switch (op_hash_test) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800783 case kInvalidOperationData: {
784 // Muck with some random offset post the metadata size so that
785 // some operation hash will result in a mismatch.
786 int some_offset = state->metadata_size + 300;
787 LOG(INFO) << "Tampered value at offset: " << some_offset;
788 state->delta[some_offset]++;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700789 expected_error = ErrorCode::kDownloadOperationHashMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800790 continue_writing = false;
791 break;
792 }
793
794 case kValidOperationData:
795 default:
796 // no change.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700797 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800798 continue_writing = true;
799 break;
800 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700801
802 // Write at some number of bytes per operation. Arbitrarily chose 5.
803 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800804 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
Alex Deymof329b932014-10-30 01:37:48 -0700805 size_t count = std::min(state->delta.size() - i, kBytesPerWrite);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800806 bool write_succeeded = ((*performer)->Write(&state->delta[i],
807 count,
808 &actual_error));
809 // Normally write_succeeded should be true every time and
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700810 // actual_error should be ErrorCode::kSuccess. If so, continue the loop.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800811 // But if we seeded an operation hash error above, then write_succeeded
812 // will be false. The failure may happen at any operation n. So, all
813 // Writes until n-1 should succeed and the nth operation will fail with
814 // actual_error. In this case, we should bail out of the loop because
815 // we cannot proceed applying the delta.
816 if (!write_succeeded) {
817 LOG(INFO) << "Write failed. Checking if it failed with expected error";
818 EXPECT_EQ(expected_error, actual_error);
819 if (!continue_writing) {
820 LOG(INFO) << "Cannot continue writing. Bailing out.";
821 break;
822 }
823 }
824
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700825 EXPECT_EQ(ErrorCode::kSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700826 }
827
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800828 // If we had continued all the way through, Close should succeed.
829 // Otherwise, it should fail. Check appropriately.
830 bool close_result = (*performer)->Close();
831 if (continue_writing)
832 EXPECT_EQ(0, close_result);
833 else
834 EXPECT_LE(0, close_result);
835}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700836
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800837void VerifyPayloadResult(DeltaPerformer* performer,
838 DeltaState* state,
Allie Wood9f6f0a52015-03-30 11:25:47 -0700839 ErrorCode expected_result,
840 uint32_t minor_version) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800841 if (!performer) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700842 EXPECT_TRUE(!"Skipping payload verification since performer is null.");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800843 return;
844 }
845
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700846 int expected_times = (expected_result == ErrorCode::kSuccess) ? 1 : 0;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700847 EXPECT_CALL(*(state->fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800848 DownloadComplete()).Times(expected_times);
849
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800850 LOG(INFO) << "Verifying payload for expected result "
851 << expected_result;
852 EXPECT_EQ(expected_result, performer->VerifyPayload(
853 OmahaHashCalculator::OmahaHashOfData(state->delta),
854 state->delta.size()));
855 LOG(INFO) << "Verified payload.";
856
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700857 if (expected_result != ErrorCode::kSuccess) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800858 // no need to verify new partition if VerifyPayload failed.
859 return;
860 }
861
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800862 chromeos::Blob updated_kernel_partition;
Allie Wood9f6f0a52015-03-30 11:25:47 -0700863 if (minor_version == kSourceMinorPayloadVersion) {
Alex Deymoda73df52015-07-22 13:53:29 -0700864 CompareFilesByBlock(state->result_kernel, state->new_kernel,
865 state->kernel_size);
866 CompareFilesByBlock(state->result_img, state->b_img,
867 state->image_size);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700868 EXPECT_TRUE(utils::ReadFile(state->result_kernel,
869 &updated_kernel_partition));
870 } else {
Alex Deymoda73df52015-07-22 13:53:29 -0700871 CompareFilesByBlock(state->old_kernel, state->new_kernel,
872 state->kernel_size);
873 CompareFilesByBlock(state->a_img, state->b_img,
874 state->image_size);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700875 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
876 }
877
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800878 ASSERT_GE(updated_kernel_partition.size(), arraysize(kNewData));
879 EXPECT_TRUE(std::equal(std::begin(kNewData), std::end(kNewData),
880 updated_kernel_partition.begin()));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700881
882 uint64_t new_kernel_size;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800883 chromeos::Blob new_kernel_hash;
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700884 uint64_t new_rootfs_size;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800885 chromeos::Blob new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800886 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Don Garrett0dd39852013-04-03 16:55:42 -0700887 &new_kernel_hash,
888 &new_rootfs_size,
889 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800890 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800891 chromeos::Blob expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800892 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700893 &expected_new_kernel_hash));
894 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800895 EXPECT_EQ(state->image_size, new_rootfs_size);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800896 chromeos::Blob expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800897 EXPECT_EQ(state->image_size,
898 OmahaHashCalculator::RawHashOfFile(state->b_img,
899 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700900 &expected_new_rootfs_hash));
901 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
902}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800903
904void VerifyPayload(DeltaPerformer* performer,
905 DeltaState* state,
Allie Wood9f6f0a52015-03-30 11:25:47 -0700906 SignatureTest signature_test,
907 uint32_t minor_version) {
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700908 ErrorCode expected_result = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800909 switch (signature_test) {
910 case kSignatureNone:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700911 expected_result = ErrorCode::kSignedDeltaPayloadExpectedError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800912 break;
913 case kSignatureGeneratedShellBadKey:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700914 expected_result = ErrorCode::kDownloadPayloadPubKeyVerificationError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800915 break;
916 default: break; // appease gcc
917 }
918
Allie Wood9f6f0a52015-03-30 11:25:47 -0700919 VerifyPayloadResult(performer, state, expected_result, minor_version);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800920}
921
922void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
Alex Deymo2d3b2d62015-07-17 17:34:36 -0700923 ssize_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800924 SignatureTest signature_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800925 bool hash_checks_mandatory, uint32_t minor_version) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800926 DeltaState state;
Alex Deymo52146ce2014-05-29 11:09:45 -0700927 DeltaPerformer *performer = nullptr;
Darin Petkov8e447e02013-04-16 16:23:50 +0200928 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
Allie Woodfdf00512015-03-02 13:34:55 -0800929 signature_test, &state, minor_version);
Don Garrett0dd39852013-04-03 16:55:42 -0700930
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800931 ScopedPathUnlinker a_img_unlinker(state.a_img);
932 ScopedPathUnlinker b_img_unlinker(state.b_img);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700933 ScopedPathUnlinker new_img_unlinker(state.result_img);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800934 ScopedPathUnlinker delta_unlinker(state.delta_path);
935 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
936 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700937 ScopedPathUnlinker result_kernel_unlinker(state.result_kernel);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800938 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
939 &state, hash_checks_mandatory, kValidOperationData,
Allie Woodfdf00512015-03-02 13:34:55 -0800940 &performer, minor_version);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700941 VerifyPayload(performer, &state, signature_test, minor_version);
Alex Deymo52146ce2014-05-29 11:09:45 -0700942 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800943}
944
945// Calls delta performer's Write method by pretending to pass in bytes from a
946// delta file whose metadata size is actual_metadata_size and tests if all
947// checks are correctly performed if the install plan contains
948// expected_metadata_size and that the result of the parsing are as per
949// hash_checks_mandatory flag.
950void DoMetadataSizeTest(uint64_t expected_metadata_size,
951 uint64_t actual_metadata_size,
952 bool hash_checks_mandatory) {
Alex Deymo8427b4a2014-11-05 14:00:32 -0800953 MockPrefs prefs;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800954 InstallPlan install_plan;
955 install_plan.hash_checks_mandatory = hash_checks_mandatory;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700956 FakeSystemState fake_system_state;
957 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800958 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
959 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
960
961 // Set a valid magic string and version number 1.
962 EXPECT_TRUE(performer.Write("CrAU", 4));
963 uint64_t version = htobe64(1);
964 EXPECT_TRUE(performer.Write(&version, 8));
965
966 install_plan.metadata_size = expected_metadata_size;
David Zeuthena99981f2013-04-29 13:42:47 -0700967 ErrorCode error_code;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800968 // When filling in size in manifest, exclude the size of the 20-byte header.
969 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
970 bool result = performer.Write(&size_in_manifest, 8, &error_code);
971 if (expected_metadata_size == actual_metadata_size ||
972 !hash_checks_mandatory) {
973 EXPECT_TRUE(result);
974 } else {
975 EXPECT_FALSE(result);
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700976 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800977 }
978
979 EXPECT_LT(performer.Close(), 0);
980}
981
982// Generates a valid delta file but tests the delta performer by suppling
983// different metadata signatures as per omaha_metadata_signature flag and
984// sees if the result of the parsing are as per hash_checks_mandatory flag.
985void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
986 SignatureTest signature_test,
987 bool hash_checks_mandatory) {
988 DeltaState state;
989
990 // Using kSignatureNone since it doesn't affect the results of our test.
991 // If we've to use other signature options, then we'd have to get the
992 // metadata size again after adding the signing operation to the manifest.
Allie Woodfdf00512015-03-02 13:34:55 -0800993 GenerateDeltaFile(true, true, false, -1, signature_test, &state,
994 DeltaPerformer::kFullPayloadMinorVersion);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800995
996 ScopedPathUnlinker a_img_unlinker(state.a_img);
997 ScopedPathUnlinker b_img_unlinker(state.b_img);
998 ScopedPathUnlinker delta_unlinker(state.delta_path);
999 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
1000 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
1001
1002 // Loads the payload and parses the manifest.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001003 chromeos::Blob payload;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001004 EXPECT_TRUE(utils::ReadFile(state.delta_path, &payload));
1005 LOG(INFO) << "Payload size: " << payload.size();
1006
1007 InstallPlan install_plan;
1008 install_plan.hash_checks_mandatory = hash_checks_mandatory;
1009 install_plan.metadata_size = state.metadata_size;
1010
1011 DeltaPerformer::MetadataParseResult expected_result, actual_result;
David Zeuthena99981f2013-04-29 13:42:47 -07001012 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001013
1014 // Fill up the metadata signature in install plan according to the test.
1015 switch (metadata_signature_test) {
1016 case kEmptyMetadataSignature:
1017 install_plan.metadata_signature.clear();
1018 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001019 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001020 break;
1021
1022 case kInvalidMetadataSignature:
1023 install_plan.metadata_signature = kBogusMetadataSignature1;
1024 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001025 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001026 break;
1027
1028 case kValidMetadataSignature:
1029 default:
1030 // Set the install plan's metadata size to be the same as the one
1031 // in the manifest so that we pass the metadata size checks. Only
1032 // then we can get to manifest signature checks.
1033 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -07001034 payload.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001035 state.metadata_size,
1036 kUnittestPrivateKeyPath,
1037 &install_plan.metadata_signature));
1038 EXPECT_FALSE(install_plan.metadata_signature.empty());
1039 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001040 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001041 break;
1042 }
1043
1044 // Ignore the expected result/error if hash checks are not mandatory.
1045 if (!hash_checks_mandatory) {
1046 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001047 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001048 }
1049
1050 // Create the delta performer object.
Alex Deymo8427b4a2014-11-05 14:00:32 -08001051 MockPrefs prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001052 DeltaPerformer delta_performer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001053 &state.fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001054 &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001055
1056 // Use the public key corresponding to the private key used above to
1057 // sign the metadata.
1058 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
1059 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
1060
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001061 // Init actual_error with an invalid value so that we make sure
1062 // ParsePayloadMetadata properly populates it in all cases.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001063 actual_error = ErrorCode::kUmaReportedMax;
Gilad Arnolddaa27402014-01-23 11:56:17 -08001064 actual_result = delta_performer.ParsePayloadMetadata(payload, &actual_error);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001065
1066 EXPECT_EQ(expected_result, actual_result);
1067 EXPECT_EQ(expected_error, actual_error);
1068
1069 // Check that the parsed metadata size is what's expected. This test
1070 // implicitly confirms that the metadata signature is valid, if required.
Gilad Arnoldfe133932014-01-14 12:25:50 -08001071 EXPECT_EQ(state.metadata_size, delta_performer.GetMetadataSize());
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001072}
1073
1074void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
1075 bool hash_checks_mandatory) {
1076 DeltaState state;
Allie Woodfdf00512015-03-02 13:34:55 -08001077 uint64_t minor_version = DeltaPerformer::kFullPayloadMinorVersion;
1078 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state,
1079 minor_version);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001080 ScopedPathUnlinker a_img_unlinker(state.a_img);
1081 ScopedPathUnlinker b_img_unlinker(state.b_img);
1082 ScopedPathUnlinker delta_unlinker(state.delta_path);
1083 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
1084 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Alex Deymo52146ce2014-05-29 11:09:45 -07001085 DeltaPerformer *performer = nullptr;
Allie Woodfdf00512015-03-02 13:34:55 -08001086 ApplyDeltaFile(true, true, false, kSignatureGenerated, &state,
1087 hash_checks_mandatory, op_hash_test, &performer,
1088 minor_version);
Alex Deymo52146ce2014-05-29 11:09:45 -07001089 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001090}
1091
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001092TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
Allie Wood56873452015-03-27 17:48:40 -07001093 uint64_t test[] = {1, 1, 4, 2, 0, 1};
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001094 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
1095 const uint64_t block_size = 4096;
Allie Wood56873452015-03-27 17:48:40 -07001096 const uint64_t file_length = 4 * block_size - 13;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001097
1098 google::protobuf::RepeatedPtrField<Extent> extents;
1099 for (size_t i = 0; i < arraysize(test); i += 2) {
1100 Extent* extent = extents.Add();
1101 extent->set_start_block(test[i]);
1102 extent->set_num_blocks(test[i + 1]);
1103 }
1104
Allie Wood56873452015-03-27 17:48:40 -07001105 string expected_output = "4096:4096,16384:8192,0:4083";
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001106 string actual_output;
1107 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
1108 block_size,
1109 file_length,
1110 &actual_output));
1111 EXPECT_EQ(expected_output, actual_output);
1112}
Darin Petkov68c10d12010-10-14 09:24:37 -07001113
Don Garrettb8dd1d92013-11-22 17:40:02 -08001114TEST(DeltaPerformerTest, ValidateManifestFullGoodTest) {
1115 // The Manifest we are validating.
1116 DeltaArchiveManifest manifest;
1117 manifest.mutable_new_kernel_info();
1118 manifest.mutable_new_rootfs_info();
1119 manifest.set_minor_version(DeltaPerformer::kFullPayloadMinorVersion);
1120
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001121 DeltaPerformerTest::RunManifestValidation(manifest, true,
1122 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001123}
1124
1125TEST(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
1126 // The Manifest we are validating.
1127 DeltaArchiveManifest manifest;
1128 manifest.mutable_old_kernel_info();
1129 manifest.mutable_old_rootfs_info();
1130 manifest.mutable_new_kernel_info();
1131 manifest.mutable_new_rootfs_info();
1132 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1133
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001134 DeltaPerformerTest::RunManifestValidation(manifest, false,
1135 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001136}
1137
1138TEST(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
1139 // The Manifest we are validating.
1140 DeltaArchiveManifest manifest;
1141
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001142 DeltaPerformerTest::RunManifestValidation(manifest, true,
1143 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001144}
1145
1146TEST(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
1147 // The Manifest we are validating.
1148 DeltaArchiveManifest manifest;
1149
1150 DeltaPerformerTest::RunManifestValidation(
1151 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001152 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001153}
1154
1155TEST(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
1156 // The Manifest we are validating.
1157 DeltaArchiveManifest manifest;
1158 manifest.mutable_old_kernel_info();
1159 manifest.mutable_new_kernel_info();
1160 manifest.mutable_new_rootfs_info();
1161 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1162
1163 DeltaPerformerTest::RunManifestValidation(
1164 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001165 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001166}
1167
1168TEST(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
1169 // The Manifest we are validating.
1170 DeltaArchiveManifest manifest;
1171 manifest.mutable_old_rootfs_info();
1172 manifest.mutable_new_kernel_info();
1173 manifest.mutable_new_rootfs_info();
1174 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1175
1176 DeltaPerformerTest::RunManifestValidation(
1177 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001178 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001179}
1180
1181TEST(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
1182 // The Manifest we are validating.
1183 DeltaArchiveManifest manifest;
1184
1185 // Generate a bad version number.
1186 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
1187 10000);
1188
1189 DeltaPerformerTest::RunManifestValidation(
1190 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001191 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001192}
1193
Darin Petkov68c10d12010-10-14 09:24:37 -07001194TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001195 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001196 false, kInPlaceMinorPayloadVersion);
Darin Petkov8e447e02013-04-16 16:23:50 +02001197}
1198
Don Garrett2ae37872013-10-25 13:33:20 -07001199TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
1200 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
Allie Woodfdf00512015-03-02 13:34:55 -08001201 false, kInPlaceMinorPayloadVersion);
Don Garrett2ae37872013-10-25 13:33:20 -07001202}
1203
1204TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
1205 DeltaState state;
1206 GenerateDeltaFile(false, false, false, -1,
Allie Woodfdf00512015-03-02 13:34:55 -08001207 kSignatureGeneratedPlaceholderMismatch, &state,
1208 kInPlaceMinorPayloadVersion);
Don Garrett2ae37872013-10-25 13:33:20 -07001209}
1210
Darin Petkov8e447e02013-04-16 16:23:50 +02001211TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001212 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001213 false, kInPlaceMinorPayloadVersion);
Darin Petkov68c10d12010-10-14 09:24:37 -07001214}
1215
1216TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001217 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001218 false, kInPlaceMinorPayloadVersion);
Darin Petkov7a22d792010-11-08 14:10:00 -08001219}
1220
1221TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001222 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001223 true, DeltaPerformer::kFullPayloadMinorVersion);
Darin Petkov9fa7ec52010-10-18 11:45:23 -07001224}
1225
1226TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001227 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001228 false, kInPlaceMinorPayloadVersion);
Darin Petkov9574f7e2011-01-13 10:48:12 -08001229}
1230
Darin Petkovcbfb0172011-01-14 15:24:45 -08001231TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001232 DoSmallImageTest(false, false, false, -1, kSignatureNone,
Allie Woodfdf00512015-03-02 13:34:55 -08001233 false, kInPlaceMinorPayloadVersion);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001234}
1235
1236TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001237 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
Allie Woodfdf00512015-03-02 13:34:55 -08001238 true, kInPlaceMinorPayloadVersion);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001239}
1240
1241TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001242 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
Allie Woodfdf00512015-03-02 13:34:55 -08001243 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -07001244}
1245
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001246TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001247 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
Allie Woodfdf00512015-03-02 13:34:55 -08001248 false, kInPlaceMinorPayloadVersion);
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001249}
1250
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001251TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001252 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
Allie Woodfdf00512015-03-02 13:34:55 -08001253 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001254}
1255
1256TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001257 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
Allie Woodfdf00512015-03-02 13:34:55 -08001258 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001259}
1260
Allie Wood9f6f0a52015-03-30 11:25:47 -07001261TEST(DeltaPerformerTest, RunAsRootSmallImageSourceOpsTest) {
1262 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
1263 false, kSourceMinorPayloadVersion);
1264}
1265
Darin Petkov934bb412010-11-18 11:21:35 -08001266TEST(DeltaPerformerTest, BadDeltaMagicTest) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001267 MockPrefs prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001268 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001269 FakeSystemState fake_system_state;
1270 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -08001271 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1272 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -08001273 EXPECT_TRUE(performer.Write("junk", 4));
1274 EXPECT_TRUE(performer.Write("morejunk", 8));
1275 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -08001276 EXPECT_LT(performer.Close(), 0);
1277}
1278
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001279TEST(DeltaPerformerTest, WriteUpdatesPayloadState) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001280 MockPrefs prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001281 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001282 FakeSystemState fake_system_state;
1283 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001284 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1285 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
1286
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001287 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001288 DownloadProgress(4)).Times(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001289 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001290 DownloadProgress(8)).Times(2);
1291
1292 EXPECT_TRUE(performer.Write("junk", 4));
1293 EXPECT_TRUE(performer.Write("morejunk", 8));
1294 EXPECT_FALSE(performer.Write("morejunk", 8));
1295 EXPECT_LT(performer.Close(), 0);
1296}
1297
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001298TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
1299 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001300}
1301
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001302TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
1303 DoMetadataSizeTest(0, 123456, false);
1304}
1305
1306TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
1307 DoMetadataSizeTest(13000, 140000, true);
1308}
1309
1310TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
1311 DoMetadataSizeTest(40000, 50000, false);
1312}
1313
1314TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
1315 DoMetadataSizeTest(85376, 85376, true);
1316}
1317
1318TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
1319 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, true);
1320}
1321
1322TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
1323 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, false);
1324}
1325
1326TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
1327 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated, true);
1328}
1329
1330TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
1331 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated,
1332 false);
1333}
1334
1335TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
1336 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureNone, true);
1337}
1338
1339TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
1340 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, true);
1341}
1342
1343TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
1344 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, false);
1345}
1346
1347TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
1348 DoOperationHashMismatchTest(kInvalidOperationData, true);
1349}
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001350
David Zeuthene7f89172013-10-31 10:21:04 -07001351TEST(DeltaPerformerTest, UsePublicKeyFromResponse) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001352 MockPrefs prefs;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001353 FakeSystemState fake_system_state;
David Zeuthene7f89172013-10-31 10:21:04 -07001354 InstallPlan install_plan;
1355 base::FilePath key_path;
1356
1357 // The result of the GetPublicKeyResponse() method is based on three things
1358 //
1359 // 1. Whether it's an official build; and
1360 // 2. Whether the Public RSA key to be used is in the root filesystem; and
Alex Vakulenko072359c2014-07-18 11:41:07 -07001361 // 3. Whether the response has a public key
David Zeuthene7f89172013-10-31 10:21:04 -07001362 //
1363 // We test all eight combinations to ensure that we only use the
1364 // public key in the response if
1365 //
1366 // a. it's not an official build; and
1367 // b. there is no key in the root filesystem.
1368
1369 DeltaPerformer *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001370 &fake_system_state,
David Zeuthene7f89172013-10-31 10:21:04 -07001371 &install_plan);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001372 FakeHardware* fake_hardware = fake_system_state.fake_hardware();
David Zeuthene7f89172013-10-31 10:21:04 -07001373
1374 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -08001375 EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
David Zeuthene7f89172013-10-31 10:21:04 -07001376 &temp_dir));
1377 string non_existing_file = temp_dir + "/non-existing";
1378 string existing_file = temp_dir + "/existing";
Alex Vakulenko75039d72014-03-25 12:36:28 -07001379 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
David Zeuthene7f89172013-10-31 10:21:04 -07001380
1381 // Non-official build, non-existing public-key, key in response -> true
Don Garrett6646b442013-11-13 15:29:11 -08001382 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001383 performer->public_key_path_ = non_existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001384 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001385 EXPECT_TRUE(performer->GetPublicKeyFromResponse(&key_path));
1386 EXPECT_FALSE(key_path.empty());
1387 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
1388 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001389 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001390 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1391
1392 // Non-official build, existing public-key, key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001393 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001394 performer->public_key_path_ = existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001395 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001396 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1397 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001398 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001399 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1400
1401 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001402 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001403 performer->public_key_path_ = non_existing_file;
1404 install_plan.public_key_rsa = "";
1405 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1406 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001407 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001408 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1409
1410 // Non-official build, existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001411 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001412 performer->public_key_path_ = existing_file;
1413 install_plan.public_key_rsa = "";
1414 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1415 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001416 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001417 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1418
1419 // Non-official build, non-existing public-key, key in response
1420 // but invalid base64 -> false
Don Garrett6646b442013-11-13 15:29:11 -08001421 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001422 performer->public_key_path_ = non_existing_file;
1423 install_plan.public_key_rsa = "not-valid-base64";
1424 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1425
1426 delete performer;
Alex Deymo10875d92014-11-10 21:52:57 -08001427 EXPECT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
David Zeuthene7f89172013-10-31 10:21:04 -07001428}
1429
Allie Wood78750a42015-02-11 15:42:11 -08001430TEST(DeltaPerformerTest, MinorVersionsMatch) {
1431 // Test that the minor version in update_engine.conf that is installed to
1432 // the image matches the supported delta minor version in the update engine.
1433 uint32_t minor_version;
Alex Deymob42b98d2015-07-06 17:42:38 -07001434 chromeos::KeyValueStore store;
1435 EXPECT_TRUE(store.Load(base::FilePath("update_engine.conf")));
1436 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
1437 EXPECT_EQ(DeltaPerformer::kSupportedMinorPayloadVersion, minor_version);
Allie Wood78750a42015-02-11 15:42:11 -08001438}
1439
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001440} // namespace chromeos_update_engine