blob: 44ecb6434b52ff3d3d97a31720e43e0758c11e9e [file] [log] [blame]
Mike Frysinger8155d082012-04-06 15:23:18 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07005#include <inttypes.h>
Alex Deymo161c4a12014-05-16 15:56:21 -07006#include <sys/mount.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07007
8#include <algorithm>
9#include <string>
10#include <vector>
11
Ben Chan06c76a42014-09-05 08:21:06 -070012#include <base/files/file_util.h>
Chris Masoned903c3b2011-05-12 15:35:46 -070013#include <base/memory/scoped_ptr.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070014#include <base/strings/string_util.h>
15#include <base/strings/stringprintf.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070016#include <google/protobuf/repeated_field.h>
17#include <gtest/gtest.h>
18
Jay Srinivasand29695d2013-04-08 15:08:05 -070019#include "update_engine/constants.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070020#include "update_engine/delta_performer.h"
Andrew de los Reyes353777c2010-10-08 10:34:30 -070021#include "update_engine/extent_ranges.h"
David Zeuthene7f89172013-10-31 10:21:04 -070022#include "update_engine/fake_hardware.h"
Gilad Arnold5bb4c902014-04-10 12:32:13 -070023#include "update_engine/fake_system_state.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070024#include "update_engine/payload_constants.h"
25#include "update_engine/payload_generator/delta_diff_generator.h"
Alex Deymo923d8fa2014-07-15 17:58:51 -070026#include "update_engine/payload_generator/payload_signer.h"
27#include "update_engine/payload_verifier.h"
Darin Petkov73058b42010-10-06 16:32:19 -070028#include "update_engine/prefs_mock.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070029#include "update_engine/test_utils.h"
30#include "update_engine/update_metadata.pb.h"
31#include "update_engine/utils.h"
32
33namespace chromeos_update_engine {
34
35using std::min;
36using std::string;
37using std::vector;
Darin Petkov73058b42010-10-06 16:32:19 -070038using testing::Return;
Alex Deymo161c4a12014-05-16 15:56:21 -070039using testing::_;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070040
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070041extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070042extern const char* kUnittestPublicKeyPath;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070043extern const char* kUnittestPrivateKey2Path;
44extern const char* kUnittestPublicKey2Path;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070045
Jay Srinivasan738fdf32012-12-07 17:40:54 -080046static const size_t kBlockSize = 4096;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -070047static const char* kBogusMetadataSignature1 =
48 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
49 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
50 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
51 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
52 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
53 "pLRtClp97kN2+tXGNBQqkA==";
Jay Srinivasan738fdf32012-12-07 17:40:54 -080054
Alex Vakulenkod2779df2014-06-16 13:19:00 -070055static const int kDefaultKernelSize = 4096; // Something small for a test
Jay Srinivasan738fdf32012-12-07 17:40:54 -080056static const char* kNewDataString = "This is new data.";
57
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070058namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080059struct DeltaState {
60 string a_img;
61 string b_img;
62 int image_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070063
Jay Srinivasan738fdf32012-12-07 17:40:54 -080064 string delta_path;
65 uint64_t metadata_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070066
Jay Srinivasan738fdf32012-12-07 17:40:54 -080067 string old_kernel;
68 vector<char> old_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070069
Jay Srinivasan738fdf32012-12-07 17:40:54 -080070 string new_kernel;
71 vector<char> new_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070072
Jay Srinivasan738fdf32012-12-07 17:40:54 -080073 // The in-memory copy of delta file.
74 vector<char> delta;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080075
76 // The mock system state object with which we initialize the
77 // delta performer.
Gilad Arnold5bb4c902014-04-10 12:32:13 -070078 FakeSystemState fake_system_state;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080079};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070080
Jay Srinivasan738fdf32012-12-07 17:40:54 -080081enum SignatureTest {
82 kSignatureNone, // No payload signing.
83 kSignatureGenerator, // Sign the payload at generation time.
84 kSignatureGenerated, // Sign the payload after it's generated.
Don Garrett2ae37872013-10-25 13:33:20 -070085 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
Alex Vakulenkod2779df2014-06-16 13:19:00 -070086 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
Jay Srinivasan738fdf32012-12-07 17:40:54 -080087 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
88 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
89 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
90 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
91};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070092
Jay Srinivasan738fdf32012-12-07 17:40:54 -080093// Different options that determine what we should fill into the
94// install_plan.metadata_signature to simulate the contents received in the
95// Omaha response.
96enum MetadataSignatureTest {
97 kEmptyMetadataSignature,
98 kInvalidMetadataSignature,
99 kValidMetadataSignature,
100};
101
102enum OperationHashTest {
103 kInvalidOperationData,
104 kValidOperationData,
105};
106
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700107} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800108
109static void CompareFilesByBlock(const string& a_file, const string& b_file) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700110 vector<char> a_data, b_data;
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700111 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
112 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700113
114 EXPECT_EQ(a_data.size(), b_data.size());
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700115 EXPECT_EQ(0, a_data.size() % kBlockSize);
116 for (size_t i = 0; i < a_data.size(); i += kBlockSize) {
117 EXPECT_EQ(0, i % kBlockSize);
118 vector<char> a_sub(&a_data[i], &a_data[i + kBlockSize]);
119 vector<char> b_sub(&b_data[i], &b_data[i + kBlockSize]);
120 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
121 }
122}
123
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800124static bool WriteSparseFile(const string& path, off_t size) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700125 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
126 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
127 ScopedFdCloser fd_closer(&fd);
128 off_t rc = lseek(fd, size + 1, SEEK_SET);
129 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
130 int return_code = ftruncate(fd, size);
131 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
132 return true;
133}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700134
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800135static size_t GetSignatureSize(const string& private_key_path) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800136 const vector<char> data(1, 'x');
137 vector<char> hash;
138 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(data, &hash));
139 vector<char> signature;
140 EXPECT_TRUE(PayloadSigner::SignHash(hash,
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800141 private_key_path,
Darin Petkovcbfb0172011-01-14 15:24:45 -0800142 &signature));
143 return signature.size();
144}
145
Don Garrett2ae37872013-10-25 13:33:20 -0700146static bool InsertSignaturePlaceholder(int signature_size,
147 const string& payload_path,
148 uint64_t* out_metadata_size) {
Ben Chanf9cb98c2014-09-21 18:31:30 -0700149 vector<vector<char>> signatures;
Don Garrett2ae37872013-10-25 13:33:20 -0700150 signatures.push_back(vector<char>(signature_size, 0));
151
152 return PayloadSigner::AddSignatureToPayload(
153 payload_path,
154 signatures,
155 payload_path,
156 out_metadata_size);
157}
158
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800159static void SignGeneratedPayload(const string& payload_path,
160 uint64_t* out_metadata_size) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800161 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800162 vector<char> hash;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700163 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
164 payload_path,
165 vector<int>(1, signature_size),
166 &hash));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800167 vector<char> signature;
168 ASSERT_TRUE(PayloadSigner::SignHash(hash,
169 kUnittestPrivateKeyPath,
170 &signature));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700171 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
172 payload_path,
Ben Chanf9cb98c2014-09-21 18:31:30 -0700173 vector<vector<char>>(1, signature),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800174 payload_path,
175 out_metadata_size));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700176 EXPECT_TRUE(PayloadVerifier::VerifySignedPayload(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700177 payload_path,
178 kUnittestPublicKeyPath,
179 kSignatureMessageOriginalVersion));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800180}
181
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800182static void SignGeneratedShellPayload(SignatureTest signature_test,
183 const string& payload_path) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800184 string private_key_path = kUnittestPrivateKeyPath;
185 if (signature_test == kSignatureGeneratedShellBadKey) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800186 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800187 &private_key_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700188 nullptr));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800189 } else {
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700190 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
191 signature_test == kSignatureGeneratedShellRotateCl1 ||
192 signature_test == kSignatureGeneratedShellRotateCl2);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800193 }
194 ScopedPathUnlinker key_unlinker(private_key_path);
195 key_unlinker.set_should_remove(signature_test ==
196 kSignatureGeneratedShellBadKey);
197 // Generates a new private key that will not match the public key.
198 if (signature_test == kSignatureGeneratedShellBadKey) {
199 LOG(INFO) << "Generating a mismatched private key.";
Alex Deymo719bfff2014-07-11 12:12:32 -0700200 ASSERT_EQ(0, System(base::StringPrintf(
201 "%s genrsa -out %s 2048",
202 utils::GetPathOnBoard("openssl").c_str(), private_key_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800203 }
204 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800205 string hash_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700206 ASSERT_TRUE(utils::MakeTempFile("hash.XXXXXX", &hash_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800207 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700208 string signature_size_string;
209 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
210 signature_test == kSignatureGeneratedShellRotateCl2)
Alex Vakulenko75039d72014-03-25 12:36:28 -0700211 signature_size_string = base::StringPrintf("%d:%d",
212 signature_size, signature_size);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700213 else
Alex Vakulenko75039d72014-03-25 12:36:28 -0700214 signature_size_string = base::StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800215 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700216 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700217 "./delta_generator -in_file=%s -signature_size=%s "
218 "-out_hash_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800219 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700220 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800221 hash_file.c_str())));
222
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700223 // Pad the hash
224 vector<char> hash;
225 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700226 ASSERT_TRUE(PayloadVerifier::PadRSA2048SHA256Hash(&hash));
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700227 ASSERT_TRUE(WriteFileVector(hash_file, hash));
228
Darin Petkovcbfb0172011-01-14 15:24:45 -0800229 string sig_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700230 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800231 ScopedPathUnlinker sig_unlinker(sig_file);
232 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700233 System(base::StringPrintf(
Alex Deymo719bfff2014-07-11 12:12:32 -0700234 "%s rsautl -raw -sign -inkey %s -in %s -out %s",
235 utils::GetPathOnBoard("openssl").c_str(),
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800236 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800237 hash_file.c_str(),
238 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700239 string sig_file2;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700240 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file2, nullptr));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700241 ScopedPathUnlinker sig2_unlinker(sig_file2);
242 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
243 signature_test == kSignatureGeneratedShellRotateCl2) {
244 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700245 System(base::StringPrintf(
Alex Deymo719bfff2014-07-11 12:12:32 -0700246 "%s rsautl -raw -sign -inkey %s -in %s -out %s",
247 utils::GetPathOnBoard("openssl").c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700248 kUnittestPrivateKey2Path,
249 hash_file.c_str(),
250 sig_file2.c_str())));
251 // Append second sig file to first path
252 sig_file += ":" + sig_file2;
253 }
254
Darin Petkovcbfb0172011-01-14 15:24:45 -0800255 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700256 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700257 "./delta_generator -in_file=%s -signature_file=%s "
258 "-out_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800259 payload_path.c_str(),
260 sig_file.c_str(),
261 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800262 int verify_result =
Alex Vakulenko75039d72014-03-25 12:36:28 -0700263 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700264 "./delta_generator -in_file=%s -public_key=%s -public_key_version=%d",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700265 payload_path.c_str(),
266 signature_test == kSignatureGeneratedShellRotateCl2 ?
267 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
268 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800269 if (signature_test == kSignatureGeneratedShellBadKey) {
270 ASSERT_NE(0, verify_result);
271 } else {
272 ASSERT_EQ(0, verify_result);
273 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800274}
275
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800276static void GenerateDeltaFile(bool full_kernel,
277 bool full_rootfs,
278 bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200279 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800280 SignatureTest signature_test,
281 DeltaState *state) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700282 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
283 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
284 CreateExtImageAtPath(state->a_img, nullptr);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700285
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800286 state->image_size = static_cast<int>(utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700287
288 // Extend the "partitions" holding the file system a bit.
289 EXPECT_EQ(0, System(base::StringPrintf(
290 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800291 state->a_img.c_str(),
292 state->image_size + 1024 * 1024 - 1)));
293 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700294
Don Garrett0dd39852013-04-03 16:55:42 -0700295 // Create ImageInfo A & B
296 ImageInfo old_image_info;
297 ImageInfo new_image_info;
298
299 if (!full_rootfs) {
300 old_image_info.set_channel("src-channel");
301 old_image_info.set_board("src-board");
302 old_image_info.set_version("src-version");
303 old_image_info.set_key("src-key");
304 old_image_info.set_build_channel("src-build-channel");
305 old_image_info.set_build_version("src-build-version");
306 }
307
308 new_image_info.set_channel("test-channel");
309 new_image_info.set_board("test-board");
310 new_image_info.set_version("test-version");
311 new_image_info.set_key("test-key");
312 new_image_info.set_build_channel("test-build-channel");
313 new_image_info.set_build_version("test-build-version");
314
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700315 // Make some changes to the A image.
316 {
317 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800318 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700319
Darin Petkov8e447e02013-04-16 16:23:50 +0200320 vector<char> hardtocompress;
321 while (hardtocompress.size() < 3 * kBlockSize) {
322 hardtocompress.insert(hardtocompress.end(),
323 kRandomString,
324 kRandomString + sizeof(kRandomString) - 1);
325 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700326 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700327 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700328 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200329 hardtocompress.size()));
330
Darin Petkov8a075a72013-04-25 14:46:09 +0200331 vector<char> zeros(16 * 1024, 0);
332 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700333 base::WriteFile(base::FilePath(base::StringPrintf(
334 "%s/move-to-sparse", a_mnt.c_str())),
335 zeros.data(), zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200336
337 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700338 WriteSparseFile(base::StringPrintf("%s/move-from-sparse",
339 a_mnt.c_str()), 16 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200340
Alex Vakulenko75039d72014-03-25 12:36:28 -0700341 EXPECT_EQ(0,
342 system(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
343 " bs=1 seek=4096 count=1",
Darin Petkov8a075a72013-04-25 14:46:09 +0200344 a_mnt.c_str()).c_str()));
345
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700346 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
347 // patch fails to zero out the final block.
348 vector<char> ones(1024 * 1024, 0xff);
Alex Vakulenko75039d72014-03-25 12:36:28 -0700349 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/ones",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700350 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700351 ones.data(),
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700352 ones.size()));
353 }
354
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700355 if (noop) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700356 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img),
357 base::FilePath(state->b_img)));
Don Garrett0dd39852013-04-03 16:55:42 -0700358 old_image_info = new_image_info;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700359 } else {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700360 CreateExtImageAtPath(state->b_img, nullptr);
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700361 EXPECT_EQ(0, System(base::StringPrintf(
362 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800363 state->b_img.c_str(),
364 state->image_size + 1024 * 1024 - 1)));
365 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700366
367 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700368 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800369 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700370
Alex Vakulenko75039d72014-03-25 12:36:28 -0700371 EXPECT_EQ(0, system(base::StringPrintf("cp %s/hello %s/hello2",
372 b_mnt.c_str(),
373 b_mnt.c_str()).c_str()));
374 EXPECT_EQ(0, system(base::StringPrintf("rm %s/hello",
375 b_mnt.c_str()).c_str()));
376 EXPECT_EQ(0, system(base::StringPrintf("mv %s/hello2 %s/hello",
377 b_mnt.c_str(),
378 b_mnt.c_str()).c_str()));
379 EXPECT_EQ(0, system(base::StringPrintf("echo foo > %s/foo",
380 b_mnt.c_str()).c_str()));
381 EXPECT_EQ(0, system(base::StringPrintf("touch %s/emptyfile",
382 b_mnt.c_str()).c_str()));
383 EXPECT_TRUE(WriteSparseFile(base::StringPrintf("%s/fullsparse",
384 b_mnt.c_str()),
385 1024 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200386
387 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700388 WriteSparseFile(base::StringPrintf("%s/move-to-sparse", b_mnt.c_str()),
Darin Petkov8a075a72013-04-25 14:46:09 +0200389 16 * 1024));
390
391 vector<char> zeros(16 * 1024, 0);
392 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700393 base::WriteFile(base::FilePath(base::StringPrintf(
394 "%s/move-from-sparse", b_mnt.c_str())),
395 zeros.data(), zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200396
Alex Vakulenko75039d72014-03-25 12:36:28 -0700397 EXPECT_EQ(0, system(base::StringPrintf("dd if=/dev/zero "
398 "of=%s/move-semi-sparse "
399 "bs=1 seek=4096 count=1",
400 b_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200401
Alex Vakulenko75039d72014-03-25 12:36:28 -0700402 EXPECT_EQ(0, system(base::StringPrintf("dd if=/dev/zero "
403 "of=%s/partsparse bs=1 "
404 "seek=4096 count=1",
405 b_mnt.c_str()).c_str()));
406 EXPECT_EQ(0, system(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
407 "mv %s/tmp %s/srchardlink1",
408 b_mnt.c_str(),
409 b_mnt.c_str(),
410 b_mnt.c_str(),
411 b_mnt.c_str()).c_str()));
412 EXPECT_EQ(0, system(base::StringPrintf("rm %s/boguslink && "
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800413 "echo foobar > %s/boguslink",
414 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Darin Petkov8e447e02013-04-16 16:23:50 +0200415
416 vector<char> hardtocompress;
417 while (hardtocompress.size() < 3 * kBlockSize) {
418 hardtocompress.insert(hardtocompress.end(),
419 kRandomString,
420 kRandomString + sizeof(kRandomString));
421 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700422 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700423 b_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700424 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200425 hardtocompress.size()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700426 }
427
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700428 string old_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800429 EXPECT_TRUE(utils::MakeTempFile("old_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800430 &state->old_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700431 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700432
433 string new_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800434 EXPECT_TRUE(utils::MakeTempFile("new_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800435 &state->new_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700436 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700437
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800438 state->old_kernel_data.resize(kDefaultKernelSize);
439 state->new_kernel_data.resize(state->old_kernel_data.size());
440 FillWithData(&state->old_kernel_data);
441 FillWithData(&state->new_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700442
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700443 // change the new kernel data
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700444 strcpy(&state->new_kernel_data[0], kNewDataString); // NOLINT(runtime/printf)
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700445
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700446 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800447 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700448 }
449
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700450 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800451 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700452 state->old_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800453 state->old_kernel_data.size()));
454 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700455 state->new_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800456 state->new_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700457
Gilad Arnolda6742b32014-01-11 00:18:34 -0800458 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800459 &state->delta_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700460 nullptr));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800461 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700462 {
463 string a_mnt, b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800464 ScopedLoopMounter a_mounter(state->a_img, &a_mnt, MS_RDONLY);
465 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, MS_RDONLY);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800466 const string private_key =
467 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700468 EXPECT_TRUE(
Darin Petkov68c10d12010-10-14 09:24:37 -0700469 DeltaDiffGenerator::GenerateDeltaUpdateFile(
Darin Petkov7a22d792010-11-08 14:10:00 -0800470 full_rootfs ? "" : a_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800471 full_rootfs ? "" : state->a_img,
Darin Petkov68c10d12010-10-14 09:24:37 -0700472 b_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800473 state->b_img,
474 full_kernel ? "" : state->old_kernel,
475 state->new_kernel,
476 state->delta_path,
477 private_key,
Darin Petkov8e447e02013-04-16 16:23:50 +0200478 chunk_size,
Chris Sosad5ae1562013-04-23 13:20:18 -0700479 kRootFSPartitionSize,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700480 full_rootfs ? nullptr : &old_image_info,
Don Garrett0dd39852013-04-03 16:55:42 -0700481 &new_image_info,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800482 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800483 }
484
Don Garrett2ae37872013-10-25 13:33:20 -0700485 if (signature_test == kSignatureGeneratedPlaceholder ||
486 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Don Garrett2ae37872013-10-25 13:33:20 -0700487 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
488 LOG(INFO) << "Inserting placeholder signature.";
489 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
490 &state->metadata_size));
491
492 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
493 signature_size -= 1;
494 LOG(INFO) << "Inserting mismatched placeholder signature.";
495 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
496 &state->metadata_size));
497 return;
498 }
499 }
500
501 if (signature_test == kSignatureGenerated ||
502 signature_test == kSignatureGeneratedPlaceholder ||
503 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800504 // Generate the signed payload and update the metadata size in state to
505 // reflect the new size after adding the signature operation to the
506 // manifest.
Don Garrett2ae37872013-10-25 13:33:20 -0700507 LOG(INFO) << "Signing payload.";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800508 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800509 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700510 signature_test == kSignatureGeneratedShellBadKey ||
511 signature_test == kSignatureGeneratedShellRotateCl1 ||
512 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800513 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700514 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800515}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700516
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800517static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
518 SignatureTest signature_test, DeltaState* state,
519 bool hash_checks_mandatory,
520 OperationHashTest op_hash_test,
521 DeltaPerformer** performer) {
Darin Petkov36a58222010-10-07 22:00:09 -0700522 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700523 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700524 DeltaArchiveManifest manifest;
Alex Deymo923d8fa2014-07-15 17:58:51 -0700525 EXPECT_TRUE(PayloadVerifier::LoadPayload(state->delta_path,
526 &state->delta,
527 &manifest,
528 &state->metadata_size));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800529 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700530
Don Garrett0dd39852013-04-03 16:55:42 -0700531
532
Darin Petkovcbfb0172011-01-14 15:24:45 -0800533 if (signature_test == kSignatureNone) {
534 EXPECT_FALSE(manifest.has_signatures_offset());
535 EXPECT_FALSE(manifest.has_signatures_size());
536 } else {
537 EXPECT_TRUE(manifest.has_signatures_offset());
538 EXPECT_TRUE(manifest.has_signatures_size());
539 Signatures sigs_message;
540 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800541 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800542 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700543 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
544 signature_test == kSignatureGeneratedShellRotateCl2)
545 EXPECT_EQ(2, sigs_message.signatures_size());
546 else
547 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800548 const Signatures_Signature& signature = sigs_message.signatures(0);
549 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700550
Darin Petkovcbfb0172011-01-14 15:24:45 -0800551 uint64_t expected_sig_data_length = 0;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700552 vector<string> key_paths{kUnittestPrivateKeyPath};
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700553 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
554 signature_test == kSignatureGeneratedShellRotateCl2) {
555 key_paths.push_back(kUnittestPrivateKey2Path);
556 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800557 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700558 key_paths,
559 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800560 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
561 EXPECT_FALSE(signature.data().empty());
562 }
Darin Petkov36a58222010-10-07 22:00:09 -0700563
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700564 if (noop) {
565 EXPECT_EQ(1, manifest.install_operations_size());
566 EXPECT_EQ(1, manifest.kernel_install_operations_size());
567 }
568
Darin Petkovd43d6902010-10-14 11:17:50 -0700569 if (full_kernel) {
570 EXPECT_FALSE(manifest.has_old_kernel_info());
571 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800572 EXPECT_EQ(state->old_kernel_data.size(),
573 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700574 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
575 }
Darin Petkov698d0412010-10-13 10:59:44 -0700576
Don Garrett0dd39852013-04-03 16:55:42 -0700577 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
578 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
579 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
580 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
581 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
582 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
583
584 if (!full_rootfs) {
Don Garrett0dd39852013-04-03 16:55:42 -0700585 if (noop) {
586 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
587 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
588 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
589 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
590 EXPECT_EQ(manifest.old_image_info().build_channel(),
591 "test-build-channel");
592 EXPECT_EQ(manifest.old_image_info().build_version(),
593 "test-build-version");
594 } else {
595 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
596 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
597 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
598 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
599 EXPECT_EQ(manifest.old_image_info().build_channel(),
600 "src-build-channel");
601 EXPECT_EQ(manifest.old_image_info().build_version(),
602 "src-build-version");
603 }
604 }
605
606
Darin Petkov7a22d792010-11-08 14:10:00 -0800607 if (full_rootfs) {
608 EXPECT_FALSE(manifest.has_old_rootfs_info());
Don Garrett0dd39852013-04-03 16:55:42 -0700609 EXPECT_FALSE(manifest.has_old_image_info());
610 EXPECT_TRUE(manifest.has_new_image_info());
Darin Petkov7a22d792010-11-08 14:10:00 -0800611 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800612 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800613 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
614 }
615
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800616 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
617 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700618
Darin Petkov36a58222010-10-07 22:00:09 -0700619 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700620 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700621 }
622
Darin Petkov73058b42010-10-06 16:32:19 -0700623 PrefsMock prefs;
624 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800625 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700626 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
627 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700628 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
629 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700630 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
631 .WillRepeatedly(Return(true));
David Zeuthen41996ad2013-09-24 15:43:24 -0700632 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
633 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700634 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700635 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800636 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800637 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
638 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700639 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
640 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800641 }
Darin Petkov73058b42010-10-06 16:32:19 -0700642
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700643 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700644 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800645 install_plan.hash_checks_mandatory = hash_checks_mandatory;
646 install_plan.metadata_size = state->metadata_size;
Don Garrettb8dd1d92013-11-22 17:40:02 -0800647 install_plan.is_full_update = full_kernel && full_rootfs;
648
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800649 LOG(INFO) << "Setting payload metadata size in Omaha = "
650 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700651 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700652 state->delta.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800653 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700654 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700655 &install_plan.metadata_signature));
656 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700657
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800658 *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700659 &state->fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800660 &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700661 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800662 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700663
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800664 EXPECT_EQ(state->image_size,
665 OmahaHashCalculator::RawHashOfFile(state->a_img,
666 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700667 &install_plan.rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800668 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->old_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700669 &install_plan.kernel_hash));
670
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800671 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
672 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
673
David Zeuthena99981f2013-04-29 13:42:47 -0700674 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800675 bool continue_writing;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700676 switch (op_hash_test) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800677 case kInvalidOperationData: {
678 // Muck with some random offset post the metadata size so that
679 // some operation hash will result in a mismatch.
680 int some_offset = state->metadata_size + 300;
681 LOG(INFO) << "Tampered value at offset: " << some_offset;
682 state->delta[some_offset]++;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700683 expected_error = ErrorCode::kDownloadOperationHashMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800684 continue_writing = false;
685 break;
686 }
687
688 case kValidOperationData:
689 default:
690 // no change.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700691 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800692 continue_writing = true;
693 break;
694 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700695
696 // Write at some number of bytes per operation. Arbitrarily chose 5.
697 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800698 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
699 size_t count = min(state->delta.size() - i, kBytesPerWrite);
700 bool write_succeeded = ((*performer)->Write(&state->delta[i],
701 count,
702 &actual_error));
703 // Normally write_succeeded should be true every time and
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700704 // actual_error should be ErrorCode::kSuccess. If so, continue the loop.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800705 // But if we seeded an operation hash error above, then write_succeeded
706 // will be false. The failure may happen at any operation n. So, all
707 // Writes until n-1 should succeed and the nth operation will fail with
708 // actual_error. In this case, we should bail out of the loop because
709 // we cannot proceed applying the delta.
710 if (!write_succeeded) {
711 LOG(INFO) << "Write failed. Checking if it failed with expected error";
712 EXPECT_EQ(expected_error, actual_error);
713 if (!continue_writing) {
714 LOG(INFO) << "Cannot continue writing. Bailing out.";
715 break;
716 }
717 }
718
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700719 EXPECT_EQ(ErrorCode::kSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700720 }
721
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800722 // If we had continued all the way through, Close should succeed.
723 // Otherwise, it should fail. Check appropriately.
724 bool close_result = (*performer)->Close();
725 if (continue_writing)
726 EXPECT_EQ(0, close_result);
727 else
728 EXPECT_LE(0, close_result);
729}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700730
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800731void VerifyPayloadResult(DeltaPerformer* performer,
732 DeltaState* state,
David Zeuthena99981f2013-04-29 13:42:47 -0700733 ErrorCode expected_result) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800734 if (!performer) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700735 EXPECT_TRUE(!"Skipping payload verification since performer is null.");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800736 return;
737 }
738
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700739 int expected_times = (expected_result == ErrorCode::kSuccess) ? 1 : 0;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700740 EXPECT_CALL(*(state->fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800741 DownloadComplete()).Times(expected_times);
742
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800743 LOG(INFO) << "Verifying payload for expected result "
744 << expected_result;
745 EXPECT_EQ(expected_result, performer->VerifyPayload(
746 OmahaHashCalculator::OmahaHashOfData(state->delta),
747 state->delta.size()));
748 LOG(INFO) << "Verified payload.";
749
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700750 if (expected_result != ErrorCode::kSuccess) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800751 // no need to verify new partition if VerifyPayload failed.
752 return;
753 }
754
755 CompareFilesByBlock(state->old_kernel, state->new_kernel);
756 CompareFilesByBlock(state->a_img, state->b_img);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700757
758 vector<char> updated_kernel_partition;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800759 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
Alex Vakulenko75039d72014-03-25 12:36:28 -0700760 EXPECT_EQ(0, strncmp(updated_kernel_partition.data(), kNewDataString,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800761 strlen(kNewDataString)));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700762
763 uint64_t new_kernel_size;
764 vector<char> new_kernel_hash;
765 uint64_t new_rootfs_size;
766 vector<char> new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800767 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Don Garrett0dd39852013-04-03 16:55:42 -0700768 &new_kernel_hash,
769 &new_rootfs_size,
770 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800771 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700772 vector<char> expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800773 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700774 &expected_new_kernel_hash));
775 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800776 EXPECT_EQ(state->image_size, new_rootfs_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700777 vector<char> expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800778 EXPECT_EQ(state->image_size,
779 OmahaHashCalculator::RawHashOfFile(state->b_img,
780 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700781 &expected_new_rootfs_hash));
782 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
783}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800784
785void VerifyPayload(DeltaPerformer* performer,
786 DeltaState* state,
787 SignatureTest signature_test) {
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700788 ErrorCode expected_result = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800789 switch (signature_test) {
790 case kSignatureNone:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700791 expected_result = ErrorCode::kSignedDeltaPayloadExpectedError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800792 break;
793 case kSignatureGeneratedShellBadKey:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700794 expected_result = ErrorCode::kDownloadPayloadPubKeyVerificationError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800795 break;
796 default: break; // appease gcc
797 }
798
799 VerifyPayloadResult(performer, state, expected_result);
800}
801
802void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200803 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800804 SignatureTest signature_test,
805 bool hash_checks_mandatory) {
806 DeltaState state;
Alex Deymo52146ce2014-05-29 11:09:45 -0700807 DeltaPerformer *performer = nullptr;
Darin Petkov8e447e02013-04-16 16:23:50 +0200808 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
809 signature_test, &state);
Don Garrett0dd39852013-04-03 16:55:42 -0700810
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800811 ScopedPathUnlinker a_img_unlinker(state.a_img);
812 ScopedPathUnlinker b_img_unlinker(state.b_img);
813 ScopedPathUnlinker delta_unlinker(state.delta_path);
814 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
815 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
816 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
817 &state, hash_checks_mandatory, kValidOperationData,
818 &performer);
819 VerifyPayload(performer, &state, signature_test);
Alex Deymo52146ce2014-05-29 11:09:45 -0700820 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800821}
822
823// Calls delta performer's Write method by pretending to pass in bytes from a
824// delta file whose metadata size is actual_metadata_size and tests if all
825// checks are correctly performed if the install plan contains
826// expected_metadata_size and that the result of the parsing are as per
827// hash_checks_mandatory flag.
828void DoMetadataSizeTest(uint64_t expected_metadata_size,
829 uint64_t actual_metadata_size,
830 bool hash_checks_mandatory) {
831 PrefsMock prefs;
832 InstallPlan install_plan;
833 install_plan.hash_checks_mandatory = hash_checks_mandatory;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700834 FakeSystemState fake_system_state;
835 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800836 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
837 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
838
839 // Set a valid magic string and version number 1.
840 EXPECT_TRUE(performer.Write("CrAU", 4));
841 uint64_t version = htobe64(1);
842 EXPECT_TRUE(performer.Write(&version, 8));
843
844 install_plan.metadata_size = expected_metadata_size;
David Zeuthena99981f2013-04-29 13:42:47 -0700845 ErrorCode error_code;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800846 // When filling in size in manifest, exclude the size of the 20-byte header.
847 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
848 bool result = performer.Write(&size_in_manifest, 8, &error_code);
849 if (expected_metadata_size == actual_metadata_size ||
850 !hash_checks_mandatory) {
851 EXPECT_TRUE(result);
852 } else {
853 EXPECT_FALSE(result);
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700854 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800855 }
856
857 EXPECT_LT(performer.Close(), 0);
858}
859
860// Generates a valid delta file but tests the delta performer by suppling
861// different metadata signatures as per omaha_metadata_signature flag and
862// sees if the result of the parsing are as per hash_checks_mandatory flag.
863void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
864 SignatureTest signature_test,
865 bool hash_checks_mandatory) {
866 DeltaState state;
867
868 // Using kSignatureNone since it doesn't affect the results of our test.
869 // If we've to use other signature options, then we'd have to get the
870 // metadata size again after adding the signing operation to the manifest.
Darin Petkov8e447e02013-04-16 16:23:50 +0200871 GenerateDeltaFile(true, true, false, -1, signature_test, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800872
873 ScopedPathUnlinker a_img_unlinker(state.a_img);
874 ScopedPathUnlinker b_img_unlinker(state.b_img);
875 ScopedPathUnlinker delta_unlinker(state.delta_path);
876 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
877 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
878
879 // Loads the payload and parses the manifest.
880 vector<char> payload;
881 EXPECT_TRUE(utils::ReadFile(state.delta_path, &payload));
882 LOG(INFO) << "Payload size: " << payload.size();
883
884 InstallPlan install_plan;
885 install_plan.hash_checks_mandatory = hash_checks_mandatory;
886 install_plan.metadata_size = state.metadata_size;
887
888 DeltaPerformer::MetadataParseResult expected_result, actual_result;
David Zeuthena99981f2013-04-29 13:42:47 -0700889 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800890
891 // Fill up the metadata signature in install plan according to the test.
892 switch (metadata_signature_test) {
893 case kEmptyMetadataSignature:
894 install_plan.metadata_signature.clear();
895 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700896 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800897 break;
898
899 case kInvalidMetadataSignature:
900 install_plan.metadata_signature = kBogusMetadataSignature1;
901 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700902 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800903 break;
904
905 case kValidMetadataSignature:
906 default:
907 // Set the install plan's metadata size to be the same as the one
908 // in the manifest so that we pass the metadata size checks. Only
909 // then we can get to manifest signature checks.
910 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700911 payload.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800912 state.metadata_size,
913 kUnittestPrivateKeyPath,
914 &install_plan.metadata_signature));
915 EXPECT_FALSE(install_plan.metadata_signature.empty());
916 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700917 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800918 break;
919 }
920
921 // Ignore the expected result/error if hash checks are not mandatory.
922 if (!hash_checks_mandatory) {
923 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700924 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800925 }
926
927 // Create the delta performer object.
928 PrefsMock prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800929 DeltaPerformer delta_performer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700930 &state.fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800931 &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800932
933 // Use the public key corresponding to the private key used above to
934 // sign the metadata.
935 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
936 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
937
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800938 // Init actual_error with an invalid value so that we make sure
939 // ParsePayloadMetadata properly populates it in all cases.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700940 actual_error = ErrorCode::kUmaReportedMax;
Gilad Arnolddaa27402014-01-23 11:56:17 -0800941 actual_result = delta_performer.ParsePayloadMetadata(payload, &actual_error);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800942
943 EXPECT_EQ(expected_result, actual_result);
944 EXPECT_EQ(expected_error, actual_error);
945
946 // Check that the parsed metadata size is what's expected. This test
947 // implicitly confirms that the metadata signature is valid, if required.
Gilad Arnoldfe133932014-01-14 12:25:50 -0800948 EXPECT_EQ(state.metadata_size, delta_performer.GetMetadataSize());
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800949}
950
951void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
952 bool hash_checks_mandatory) {
953 DeltaState state;
Darin Petkov8e447e02013-04-16 16:23:50 +0200954 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800955 ScopedPathUnlinker a_img_unlinker(state.a_img);
956 ScopedPathUnlinker b_img_unlinker(state.b_img);
957 ScopedPathUnlinker delta_unlinker(state.delta_path);
958 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
959 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Alex Deymo52146ce2014-05-29 11:09:45 -0700960 DeltaPerformer *performer = nullptr;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800961 ApplyDeltaFile(true, true, false, kSignatureGenerated,
962 &state, hash_checks_mandatory, op_hash_test, &performer);
Alex Deymo52146ce2014-05-29 11:09:45 -0700963 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800964}
965
Don Garrettb8dd1d92013-11-22 17:40:02 -0800966
967class DeltaPerformerTest : public ::testing::Test {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800968 public:
969 // Test helper placed where it can easily be friended from DeltaPerformer.
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700970 static void RunManifestValidation(const DeltaArchiveManifest& manifest,
Don Garrettb8dd1d92013-11-22 17:40:02 -0800971 bool full_payload,
972 ErrorCode expected) {
973 PrefsMock prefs;
974 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700975 FakeSystemState fake_system_state;
976 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800977
978 // The install plan is for Full or Delta.
979 install_plan.is_full_update = full_payload;
980
981 // The Manifest we are validating.
982 performer.manifest_.CopyFrom(manifest);
983
984 EXPECT_EQ(expected, performer.ValidateManifest());
985 }
986};
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800987
988TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
989 uint64_t test[] = {1, 1, 4, 2, kSparseHole, 1, 0, 1};
990 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
991 const uint64_t block_size = 4096;
992 const uint64_t file_length = 5 * block_size - 13;
993
994 google::protobuf::RepeatedPtrField<Extent> extents;
995 for (size_t i = 0; i < arraysize(test); i += 2) {
996 Extent* extent = extents.Add();
997 extent->set_start_block(test[i]);
998 extent->set_num_blocks(test[i + 1]);
999 }
1000
1001 string expected_output = "4096:4096,16384:8192,-1:4096,0:4083";
1002 string actual_output;
1003 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
1004 block_size,
1005 file_length,
1006 &actual_output));
1007 EXPECT_EQ(expected_output, actual_output);
1008}
Darin Petkov68c10d12010-10-14 09:24:37 -07001009
Don Garrettb8dd1d92013-11-22 17:40:02 -08001010TEST(DeltaPerformerTest, ValidateManifestFullGoodTest) {
1011 // The Manifest we are validating.
1012 DeltaArchiveManifest manifest;
1013 manifest.mutable_new_kernel_info();
1014 manifest.mutable_new_rootfs_info();
1015 manifest.set_minor_version(DeltaPerformer::kFullPayloadMinorVersion);
1016
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001017 DeltaPerformerTest::RunManifestValidation(manifest, true,
1018 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001019}
1020
1021TEST(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
1022 // The Manifest we are validating.
1023 DeltaArchiveManifest manifest;
1024 manifest.mutable_old_kernel_info();
1025 manifest.mutable_old_rootfs_info();
1026 manifest.mutable_new_kernel_info();
1027 manifest.mutable_new_rootfs_info();
1028 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1029
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001030 DeltaPerformerTest::RunManifestValidation(manifest, false,
1031 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001032}
1033
1034TEST(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
1035 // The Manifest we are validating.
1036 DeltaArchiveManifest manifest;
1037
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001038 DeltaPerformerTest::RunManifestValidation(manifest, true,
1039 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001040}
1041
1042TEST(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
1043 // The Manifest we are validating.
1044 DeltaArchiveManifest manifest;
1045
1046 DeltaPerformerTest::RunManifestValidation(
1047 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001048 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001049}
1050
1051TEST(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
1052 // The Manifest we are validating.
1053 DeltaArchiveManifest manifest;
1054 manifest.mutable_old_kernel_info();
1055 manifest.mutable_new_kernel_info();
1056 manifest.mutable_new_rootfs_info();
1057 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1058
1059 DeltaPerformerTest::RunManifestValidation(
1060 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001061 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001062}
1063
1064TEST(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
1065 // The Manifest we are validating.
1066 DeltaArchiveManifest manifest;
1067 manifest.mutable_old_rootfs_info();
1068 manifest.mutable_new_kernel_info();
1069 manifest.mutable_new_rootfs_info();
1070 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1071
1072 DeltaPerformerTest::RunManifestValidation(
1073 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001074 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001075}
1076
1077TEST(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
1078 // The Manifest we are validating.
1079 DeltaArchiveManifest manifest;
1080
1081 // Generate a bad version number.
1082 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
1083 10000);
1084
1085 DeltaPerformerTest::RunManifestValidation(
1086 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001087 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001088}
1089
Darin Petkov68c10d12010-10-14 09:24:37 -07001090TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001091 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001092 false);
Darin Petkov8e447e02013-04-16 16:23:50 +02001093}
1094
Don Garrett2ae37872013-10-25 13:33:20 -07001095TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
1096 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
1097 false);
1098}
1099
1100TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
1101 DeltaState state;
1102 GenerateDeltaFile(false, false, false, -1,
1103 kSignatureGeneratedPlaceholderMismatch, &state);
1104}
1105
Darin Petkov8e447e02013-04-16 16:23:50 +02001106TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001107 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001108 false);
Darin Petkov68c10d12010-10-14 09:24:37 -07001109}
1110
1111TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001112 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001113 false);
Darin Petkov7a22d792010-11-08 14:10:00 -08001114}
1115
1116TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001117 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001118 true);
Darin Petkov9fa7ec52010-10-18 11:45:23 -07001119}
1120
1121TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001122 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001123 false);
Darin Petkov9574f7e2011-01-13 10:48:12 -08001124}
1125
Darin Petkovcbfb0172011-01-14 15:24:45 -08001126TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001127 DoSmallImageTest(false, false, false, -1, kSignatureNone,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001128 false);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001129}
1130
1131TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001132 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001133 true);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001134}
1135
1136TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001137 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001138 false);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -07001139}
1140
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001141TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001142 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001143 false);
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001144}
1145
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001146TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001147 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001148 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001149}
1150
1151TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001152 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001153 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001154}
1155
Darin Petkov934bb412010-11-18 11:21:35 -08001156TEST(DeltaPerformerTest, BadDeltaMagicTest) {
1157 PrefsMock prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001158 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001159 FakeSystemState fake_system_state;
1160 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -08001161 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1162 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -08001163 EXPECT_TRUE(performer.Write("junk", 4));
1164 EXPECT_TRUE(performer.Write("morejunk", 8));
1165 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -08001166 EXPECT_LT(performer.Close(), 0);
1167}
1168
Andrew de los Reyes353777c2010-10-08 10:34:30 -07001169TEST(DeltaPerformerTest, IsIdempotentOperationTest) {
1170 DeltaArchiveManifest_InstallOperation op;
1171 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1172 *(op.add_dst_extents()) = ExtentForRange(0, 5);
1173 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1174 *(op.add_src_extents()) = ExtentForRange(4, 1);
1175 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1176 op.clear_src_extents();
1177 *(op.add_src_extents()) = ExtentForRange(5, 3);
1178 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1179 *(op.add_dst_extents()) = ExtentForRange(20, 6);
1180 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1181 *(op.add_src_extents()) = ExtentForRange(19, 2);
1182 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1183}
1184
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001185TEST(DeltaPerformerTest, WriteUpdatesPayloadState) {
1186 PrefsMock prefs;
1187 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001188 FakeSystemState fake_system_state;
1189 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001190 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1191 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
1192
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001193 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001194 DownloadProgress(4)).Times(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001195 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001196 DownloadProgress(8)).Times(2);
1197
1198 EXPECT_TRUE(performer.Write("junk", 4));
1199 EXPECT_TRUE(performer.Write("morejunk", 8));
1200 EXPECT_FALSE(performer.Write("morejunk", 8));
1201 EXPECT_LT(performer.Close(), 0);
1202}
1203
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001204TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
1205 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001206}
1207
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001208TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
1209 DoMetadataSizeTest(0, 123456, false);
1210}
1211
1212TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
1213 DoMetadataSizeTest(13000, 140000, true);
1214}
1215
1216TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
1217 DoMetadataSizeTest(40000, 50000, false);
1218}
1219
1220TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
1221 DoMetadataSizeTest(85376, 85376, true);
1222}
1223
1224TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
1225 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, true);
1226}
1227
1228TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
1229 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, false);
1230}
1231
1232TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
1233 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated, true);
1234}
1235
1236TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
1237 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated,
1238 false);
1239}
1240
1241TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
1242 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureNone, true);
1243}
1244
1245TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
1246 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, true);
1247}
1248
1249TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
1250 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, false);
1251}
1252
1253TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
1254 DoOperationHashMismatchTest(kInvalidOperationData, true);
1255}
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001256
David Zeuthene7f89172013-10-31 10:21:04 -07001257TEST(DeltaPerformerTest, UsePublicKeyFromResponse) {
1258 PrefsMock prefs;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001259 FakeSystemState fake_system_state;
David Zeuthene7f89172013-10-31 10:21:04 -07001260 InstallPlan install_plan;
1261 base::FilePath key_path;
1262
1263 // The result of the GetPublicKeyResponse() method is based on three things
1264 //
1265 // 1. Whether it's an official build; and
1266 // 2. Whether the Public RSA key to be used is in the root filesystem; and
Alex Vakulenko072359c2014-07-18 11:41:07 -07001267 // 3. Whether the response has a public key
David Zeuthene7f89172013-10-31 10:21:04 -07001268 //
1269 // We test all eight combinations to ensure that we only use the
1270 // public key in the response if
1271 //
1272 // a. it's not an official build; and
1273 // b. there is no key in the root filesystem.
1274
1275 DeltaPerformer *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001276 &fake_system_state,
David Zeuthene7f89172013-10-31 10:21:04 -07001277 &install_plan);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001278 FakeHardware* fake_hardware = fake_system_state.fake_hardware();
David Zeuthene7f89172013-10-31 10:21:04 -07001279
1280 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -08001281 EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
David Zeuthene7f89172013-10-31 10:21:04 -07001282 &temp_dir));
1283 string non_existing_file = temp_dir + "/non-existing";
1284 string existing_file = temp_dir + "/existing";
Alex Vakulenko75039d72014-03-25 12:36:28 -07001285 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
David Zeuthene7f89172013-10-31 10:21:04 -07001286
1287 // Non-official build, non-existing public-key, key in response -> true
Don Garrett6646b442013-11-13 15:29:11 -08001288 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001289 performer->public_key_path_ = non_existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001290 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001291 EXPECT_TRUE(performer->GetPublicKeyFromResponse(&key_path));
1292 EXPECT_FALSE(key_path.empty());
1293 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
1294 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001295 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001296 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1297
1298 // Non-official build, existing public-key, key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001299 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001300 performer->public_key_path_ = existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001301 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001302 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1303 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001304 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001305 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1306
1307 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001308 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001309 performer->public_key_path_ = non_existing_file;
1310 install_plan.public_key_rsa = "";
1311 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1312 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001313 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001314 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1315
1316 // Non-official build, existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001317 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001318 performer->public_key_path_ = existing_file;
1319 install_plan.public_key_rsa = "";
1320 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1321 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001322 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001323 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1324
1325 // Non-official build, non-existing public-key, key in response
1326 // but invalid base64 -> false
Don Garrett6646b442013-11-13 15:29:11 -08001327 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001328 performer->public_key_path_ = non_existing_file;
1329 install_plan.public_key_rsa = "not-valid-base64";
1330 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1331
1332 delete performer;
1333 EXPECT_TRUE(utils::RecursiveUnlinkDir(temp_dir));
1334}
1335
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001336} // namespace chromeos_update_engine