blob: 0a19aa2793988a0c79e0ad106770a31282bac37c [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
5#include <sys/mount.h>
6#include <inttypes.h>
7
8#include <algorithm>
9#include <string>
10#include <vector>
11
Darin Petkov9fa7ec52010-10-18 11:45:23 -070012#include <base/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_diff_generator.h"
21#include "update_engine/delta_performer.h"
Andrew de los Reyes353777c2010-10-08 10:34:30 -070022#include "update_engine/extent_ranges.h"
David Zeuthene7f89172013-10-31 10:21:04 -070023#include "update_engine/fake_hardware.h"
Gilad Arnold5bb4c902014-04-10 12:32:13 -070024#include "update_engine/fake_system_state.h"
Darin Petkov7a22d792010-11-08 14:10:00 -080025#include "update_engine/full_update_generator.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070026#include "update_engine/graph_types.h"
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070027#include "update_engine/payload_signer.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::_;
39using testing::Return;
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;
47static const char* kBogusMetadataSignature1 = "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBvJ5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQrYH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMSBmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIRfjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoVpLRtClp97kN2+tXGNBQqkA==";
48
49static const int kDefaultKernelSize = 4096; // Something small for a test
50static const char* kNewDataString = "This is new data.";
51
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070052namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080053struct DeltaState {
54 string a_img;
55 string b_img;
56 int image_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070057
Jay Srinivasan738fdf32012-12-07 17:40:54 -080058 string delta_path;
59 uint64_t metadata_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070060
Jay Srinivasan738fdf32012-12-07 17:40:54 -080061 string old_kernel;
62 vector<char> old_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070063
Jay Srinivasan738fdf32012-12-07 17:40:54 -080064 string new_kernel;
65 vector<char> new_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070066
Jay Srinivasan738fdf32012-12-07 17:40:54 -080067 // The in-memory copy of delta file.
68 vector<char> delta;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080069
70 // The mock system state object with which we initialize the
71 // delta performer.
Gilad Arnold5bb4c902014-04-10 12:32:13 -070072 FakeSystemState fake_system_state;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080073};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070074
Jay Srinivasan738fdf32012-12-07 17:40:54 -080075enum SignatureTest {
76 kSignatureNone, // No payload signing.
77 kSignatureGenerator, // Sign the payload at generation time.
78 kSignatureGenerated, // Sign the payload after it's generated.
Don Garrett2ae37872013-10-25 13:33:20 -070079 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
80 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
Jay Srinivasan738fdf32012-12-07 17:40:54 -080081 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
82 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
83 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
84 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
85};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070086
Jay Srinivasan738fdf32012-12-07 17:40:54 -080087// Different options that determine what we should fill into the
88// install_plan.metadata_signature to simulate the contents received in the
89// Omaha response.
90enum MetadataSignatureTest {
91 kEmptyMetadataSignature,
92 kInvalidMetadataSignature,
93 kValidMetadataSignature,
94};
95
96enum OperationHashTest {
97 kInvalidOperationData,
98 kValidOperationData,
99};
100
101} // namespace {}
102
103static void CompareFilesByBlock(const string& a_file, const string& b_file) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700104 vector<char> a_data, b_data;
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700105 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
106 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700107
108 EXPECT_EQ(a_data.size(), b_data.size());
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700109 EXPECT_EQ(0, a_data.size() % kBlockSize);
110 for (size_t i = 0; i < a_data.size(); i += kBlockSize) {
111 EXPECT_EQ(0, i % kBlockSize);
112 vector<char> a_sub(&a_data[i], &a_data[i + kBlockSize]);
113 vector<char> b_sub(&b_data[i], &b_data[i + kBlockSize]);
114 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
115 }
116}
117
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800118static bool WriteSparseFile(const string& path, off_t size) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700119 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
120 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
121 ScopedFdCloser fd_closer(&fd);
122 off_t rc = lseek(fd, size + 1, SEEK_SET);
123 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
124 int return_code = ftruncate(fd, size);
125 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
126 return true;
127}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700128
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800129static size_t GetSignatureSize(const string& private_key_path) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800130 const vector<char> data(1, 'x');
131 vector<char> hash;
132 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(data, &hash));
133 vector<char> signature;
134 EXPECT_TRUE(PayloadSigner::SignHash(hash,
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800135 private_key_path,
Darin Petkovcbfb0172011-01-14 15:24:45 -0800136 &signature));
137 return signature.size();
138}
139
Don Garrett2ae37872013-10-25 13:33:20 -0700140static bool InsertSignaturePlaceholder(int signature_size,
141 const string& payload_path,
142 uint64_t* out_metadata_size) {
143 vector<vector<char> > signatures;
144 signatures.push_back(vector<char>(signature_size, 0));
145
146 return PayloadSigner::AddSignatureToPayload(
147 payload_path,
148 signatures,
149 payload_path,
150 out_metadata_size);
151}
152
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800153static void SignGeneratedPayload(const string& payload_path,
154 uint64_t* out_metadata_size) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800155 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800156 vector<char> hash;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700157 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
158 payload_path,
159 vector<int>(1, signature_size),
160 &hash));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800161 vector<char> signature;
162 ASSERT_TRUE(PayloadSigner::SignHash(hash,
163 kUnittestPrivateKeyPath,
164 &signature));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700165 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
166 payload_path,
167 vector<vector<char> >(1, signature),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800168 payload_path,
169 out_metadata_size));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700170 EXPECT_TRUE(PayloadSigner::VerifySignedPayload(
171 payload_path,
172 kUnittestPublicKeyPath,
173 kSignatureMessageOriginalVersion));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800174}
175
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800176static void SignGeneratedShellPayload(SignatureTest signature_test,
177 const string& payload_path) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800178 string private_key_path = kUnittestPrivateKeyPath;
179 if (signature_test == kSignatureGeneratedShellBadKey) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800180 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800181 &private_key_path,
182 NULL));
183 } else {
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700184 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
185 signature_test == kSignatureGeneratedShellRotateCl1 ||
186 signature_test == kSignatureGeneratedShellRotateCl2);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800187 }
188 ScopedPathUnlinker key_unlinker(private_key_path);
189 key_unlinker.set_should_remove(signature_test ==
190 kSignatureGeneratedShellBadKey);
191 // Generates a new private key that will not match the public key.
192 if (signature_test == kSignatureGeneratedShellBadKey) {
193 LOG(INFO) << "Generating a mismatched private key.";
194 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700195 System(base::StringPrintf("openssl genrsa -out %s 2048",
196 private_key_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800197 }
198 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800199 string hash_file;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800200 ASSERT_TRUE(utils::MakeTempFile("hash.XXXXXX", &hash_file, NULL));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800201 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700202 string signature_size_string;
203 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
204 signature_test == kSignatureGeneratedShellRotateCl2)
Alex Vakulenko75039d72014-03-25 12:36:28 -0700205 signature_size_string = base::StringPrintf("%d:%d",
206 signature_size, signature_size);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700207 else
Alex Vakulenko75039d72014-03-25 12:36:28 -0700208 signature_size_string = base::StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800209 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700210 System(base::StringPrintf(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700211 "./delta_generator -in_file %s -signature_size %s "
Darin Petkovcbfb0172011-01-14 15:24:45 -0800212 "-out_hash_file %s",
213 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700214 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800215 hash_file.c_str())));
216
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700217 // Pad the hash
218 vector<char> hash;
219 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
220 ASSERT_TRUE(PayloadSigner::PadRSA2048SHA256Hash(&hash));
221 ASSERT_TRUE(WriteFileVector(hash_file, hash));
222
Darin Petkovcbfb0172011-01-14 15:24:45 -0800223 string sig_file;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800224 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file, NULL));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800225 ScopedPathUnlinker sig_unlinker(sig_file);
226 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700227 System(base::StringPrintf(
Mike Frysinger2149be42012-03-12 19:23:47 -0400228 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800229 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800230 hash_file.c_str(),
231 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700232 string sig_file2;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800233 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file2, NULL));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700234 ScopedPathUnlinker sig2_unlinker(sig_file2);
235 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
236 signature_test == kSignatureGeneratedShellRotateCl2) {
237 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700238 System(base::StringPrintf(
Mike Frysinger2149be42012-03-12 19:23:47 -0400239 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700240 kUnittestPrivateKey2Path,
241 hash_file.c_str(),
242 sig_file2.c_str())));
243 // Append second sig file to first path
244 sig_file += ":" + sig_file2;
245 }
246
Darin Petkovcbfb0172011-01-14 15:24:45 -0800247 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700248 System(base::StringPrintf(
Darin Petkovcbfb0172011-01-14 15:24:45 -0800249 "./delta_generator -in_file %s -signature_file %s "
250 "-out_file %s",
251 payload_path.c_str(),
252 sig_file.c_str(),
253 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800254 int verify_result =
Alex Vakulenko75039d72014-03-25 12:36:28 -0700255 System(base::StringPrintf(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700256 "./delta_generator -in_file %s -public_key %s -public_key_version %d",
257 payload_path.c_str(),
258 signature_test == kSignatureGeneratedShellRotateCl2 ?
259 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
260 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800261 if (signature_test == kSignatureGeneratedShellBadKey) {
262 ASSERT_NE(0, verify_result);
263 } else {
264 ASSERT_EQ(0, verify_result);
265 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800266}
267
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800268static void GenerateDeltaFile(bool full_kernel,
269 bool full_rootfs,
270 bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200271 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800272 SignatureTest signature_test,
273 DeltaState *state) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800274 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, NULL));
275 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, NULL));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800276 CreateExtImageAtPath(state->a_img, NULL);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700277
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800278 state->image_size = static_cast<int>(utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700279
280 // Extend the "partitions" holding the file system a bit.
281 EXPECT_EQ(0, System(base::StringPrintf(
282 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800283 state->a_img.c_str(),
284 state->image_size + 1024 * 1024 - 1)));
285 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700286
Don Garrett0dd39852013-04-03 16:55:42 -0700287 // Create ImageInfo A & B
288 ImageInfo old_image_info;
289 ImageInfo new_image_info;
290
291 if (!full_rootfs) {
292 old_image_info.set_channel("src-channel");
293 old_image_info.set_board("src-board");
294 old_image_info.set_version("src-version");
295 old_image_info.set_key("src-key");
296 old_image_info.set_build_channel("src-build-channel");
297 old_image_info.set_build_version("src-build-version");
298 }
299
300 new_image_info.set_channel("test-channel");
301 new_image_info.set_board("test-board");
302 new_image_info.set_version("test-version");
303 new_image_info.set_key("test-key");
304 new_image_info.set_build_channel("test-build-channel");
305 new_image_info.set_build_version("test-build-version");
306
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700307 // Make some changes to the A image.
308 {
309 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800310 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700311
Darin Petkov8e447e02013-04-16 16:23:50 +0200312 vector<char> hardtocompress;
313 while (hardtocompress.size() < 3 * kBlockSize) {
314 hardtocompress.insert(hardtocompress.end(),
315 kRandomString,
316 kRandomString + sizeof(kRandomString) - 1);
317 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700318 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700319 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700320 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200321 hardtocompress.size()));
322
Darin Petkov8a075a72013-04-25 14:46:09 +0200323 vector<char> zeros(16 * 1024, 0);
324 EXPECT_EQ(zeros.size(),
325 file_util::WriteFile(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700326 base::FilePath(base::StringPrintf("%s/move-to-sparse",
327 a_mnt.c_str())),
328 zeros.data(), zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200329
330 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700331 WriteSparseFile(base::StringPrintf("%s/move-from-sparse",
332 a_mnt.c_str()), 16 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200333
Alex Vakulenko75039d72014-03-25 12:36:28 -0700334 EXPECT_EQ(0,
335 system(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
336 " bs=1 seek=4096 count=1",
Darin Petkov8a075a72013-04-25 14:46:09 +0200337 a_mnt.c_str()).c_str()));
338
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700339 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
340 // patch fails to zero out the final block.
341 vector<char> ones(1024 * 1024, 0xff);
Alex Vakulenko75039d72014-03-25 12:36:28 -0700342 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/ones",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700343 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700344 ones.data(),
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700345 ones.size()));
346 }
347
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700348 if (noop) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700349 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img),
350 base::FilePath(state->b_img)));
Don Garrett0dd39852013-04-03 16:55:42 -0700351 old_image_info = new_image_info;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700352 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800353 CreateExtImageAtPath(state->b_img, NULL);
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700354 EXPECT_EQ(0, System(base::StringPrintf(
355 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800356 state->b_img.c_str(),
357 state->image_size + 1024 * 1024 - 1)));
358 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700359
360 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700361 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800362 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700363
Alex Vakulenko75039d72014-03-25 12:36:28 -0700364 EXPECT_EQ(0, system(base::StringPrintf("cp %s/hello %s/hello2",
365 b_mnt.c_str(),
366 b_mnt.c_str()).c_str()));
367 EXPECT_EQ(0, system(base::StringPrintf("rm %s/hello",
368 b_mnt.c_str()).c_str()));
369 EXPECT_EQ(0, system(base::StringPrintf("mv %s/hello2 %s/hello",
370 b_mnt.c_str(),
371 b_mnt.c_str()).c_str()));
372 EXPECT_EQ(0, system(base::StringPrintf("echo foo > %s/foo",
373 b_mnt.c_str()).c_str()));
374 EXPECT_EQ(0, system(base::StringPrintf("touch %s/emptyfile",
375 b_mnt.c_str()).c_str()));
376 EXPECT_TRUE(WriteSparseFile(base::StringPrintf("%s/fullsparse",
377 b_mnt.c_str()),
378 1024 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200379
380 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700381 WriteSparseFile(base::StringPrintf("%s/move-to-sparse", b_mnt.c_str()),
Darin Petkov8a075a72013-04-25 14:46:09 +0200382 16 * 1024));
383
384 vector<char> zeros(16 * 1024, 0);
385 EXPECT_EQ(zeros.size(),
386 file_util::WriteFile(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700387 base::FilePath(base::StringPrintf("%s/move-from-sparse",
388 b_mnt.c_str())),
389 zeros.data(), zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200390
Alex Vakulenko75039d72014-03-25 12:36:28 -0700391 EXPECT_EQ(0, system(base::StringPrintf("dd if=/dev/zero "
392 "of=%s/move-semi-sparse "
393 "bs=1 seek=4096 count=1",
394 b_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200395
Alex Vakulenko75039d72014-03-25 12:36:28 -0700396 EXPECT_EQ(0, system(base::StringPrintf("dd if=/dev/zero "
397 "of=%s/partsparse bs=1 "
398 "seek=4096 count=1",
399 b_mnt.c_str()).c_str()));
400 EXPECT_EQ(0, system(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
401 "mv %s/tmp %s/srchardlink1",
402 b_mnt.c_str(),
403 b_mnt.c_str(),
404 b_mnt.c_str(),
405 b_mnt.c_str()).c_str()));
406 EXPECT_EQ(0, system(base::StringPrintf("rm %s/boguslink && "
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800407 "echo foobar > %s/boguslink",
408 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Darin Petkov8e447e02013-04-16 16:23:50 +0200409
410 vector<char> hardtocompress;
411 while (hardtocompress.size() < 3 * kBlockSize) {
412 hardtocompress.insert(hardtocompress.end(),
413 kRandomString,
414 kRandomString + sizeof(kRandomString));
415 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700416 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700417 b_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700418 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200419 hardtocompress.size()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700420 }
421
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700422 string old_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800423 EXPECT_TRUE(utils::MakeTempFile("old_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800424 &state->old_kernel,
425 NULL));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700426
427 string new_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800428 EXPECT_TRUE(utils::MakeTempFile("new_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800429 &state->new_kernel,
430 NULL));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700431
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800432 state->old_kernel_data.resize(kDefaultKernelSize);
433 state->new_kernel_data.resize(state->old_kernel_data.size());
434 FillWithData(&state->old_kernel_data);
435 FillWithData(&state->new_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700436
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700437 // change the new kernel data
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800438 strcpy(&state->new_kernel_data[0], kNewDataString);
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700439
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700440 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800441 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700442 }
443
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700444 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800445 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700446 state->old_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800447 state->old_kernel_data.size()));
448 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700449 state->new_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800450 state->new_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700451
Gilad Arnolda6742b32014-01-11 00:18:34 -0800452 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800453 &state->delta_path,
454 NULL));
455 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700456 {
457 string a_mnt, b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800458 ScopedLoopMounter a_mounter(state->a_img, &a_mnt, MS_RDONLY);
459 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, MS_RDONLY);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800460 const string private_key =
461 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700462 EXPECT_TRUE(
Darin Petkov68c10d12010-10-14 09:24:37 -0700463 DeltaDiffGenerator::GenerateDeltaUpdateFile(
Darin Petkov7a22d792010-11-08 14:10:00 -0800464 full_rootfs ? "" : a_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800465 full_rootfs ? "" : state->a_img,
Darin Petkov68c10d12010-10-14 09:24:37 -0700466 b_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800467 state->b_img,
468 full_kernel ? "" : state->old_kernel,
469 state->new_kernel,
470 state->delta_path,
471 private_key,
Darin Petkov8e447e02013-04-16 16:23:50 +0200472 chunk_size,
Chris Sosad5ae1562013-04-23 13:20:18 -0700473 kRootFSPartitionSize,
Don Garrett0dd39852013-04-03 16:55:42 -0700474 full_rootfs ? NULL : &old_image_info,
475 &new_image_info,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800476 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800477 }
478
Don Garrett2ae37872013-10-25 13:33:20 -0700479 if (signature_test == kSignatureGeneratedPlaceholder ||
480 signature_test == kSignatureGeneratedPlaceholderMismatch) {
481
482 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
483 LOG(INFO) << "Inserting placeholder signature.";
484 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
485 &state->metadata_size));
486
487 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
488 signature_size -= 1;
489 LOG(INFO) << "Inserting mismatched placeholder signature.";
490 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
491 &state->metadata_size));
492 return;
493 }
494 }
495
496 if (signature_test == kSignatureGenerated ||
497 signature_test == kSignatureGeneratedPlaceholder ||
498 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800499 // Generate the signed payload and update the metadata size in state to
500 // reflect the new size after adding the signature operation to the
501 // manifest.
Don Garrett2ae37872013-10-25 13:33:20 -0700502 LOG(INFO) << "Signing payload.";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800503 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800504 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700505 signature_test == kSignatureGeneratedShellBadKey ||
506 signature_test == kSignatureGeneratedShellRotateCl1 ||
507 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800508 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700509 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800510}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700511
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800512static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
513 SignatureTest signature_test, DeltaState* state,
514 bool hash_checks_mandatory,
515 OperationHashTest op_hash_test,
516 DeltaPerformer** performer) {
Darin Petkov36a58222010-10-07 22:00:09 -0700517 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700518 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700519 DeltaArchiveManifest manifest;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800520 EXPECT_TRUE(PayloadSigner::LoadPayload(state->delta_path,
521 &state->delta,
522 &manifest,
523 &state->metadata_size));
524 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700525
Don Garrett0dd39852013-04-03 16:55:42 -0700526
527
Darin Petkovcbfb0172011-01-14 15:24:45 -0800528 if (signature_test == kSignatureNone) {
529 EXPECT_FALSE(manifest.has_signatures_offset());
530 EXPECT_FALSE(manifest.has_signatures_size());
531 } else {
532 EXPECT_TRUE(manifest.has_signatures_offset());
533 EXPECT_TRUE(manifest.has_signatures_size());
534 Signatures sigs_message;
535 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800536 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800537 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700538 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
539 signature_test == kSignatureGeneratedShellRotateCl2)
540 EXPECT_EQ(2, sigs_message.signatures_size());
541 else
542 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800543 const Signatures_Signature& signature = sigs_message.signatures(0);
544 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700545
Darin Petkovcbfb0172011-01-14 15:24:45 -0800546 uint64_t expected_sig_data_length = 0;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700547 vector<string> key_paths (1, kUnittestPrivateKeyPath);
548 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
549 signature_test == kSignatureGeneratedShellRotateCl2) {
550 key_paths.push_back(kUnittestPrivateKey2Path);
551 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800552 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700553 key_paths,
554 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800555 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
556 EXPECT_FALSE(signature.data().empty());
557 }
Darin Petkov36a58222010-10-07 22:00:09 -0700558
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700559 if (noop) {
560 EXPECT_EQ(1, manifest.install_operations_size());
561 EXPECT_EQ(1, manifest.kernel_install_operations_size());
562 }
563
Darin Petkovd43d6902010-10-14 11:17:50 -0700564 if (full_kernel) {
565 EXPECT_FALSE(manifest.has_old_kernel_info());
566 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800567 EXPECT_EQ(state->old_kernel_data.size(),
568 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700569 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
570 }
Darin Petkov698d0412010-10-13 10:59:44 -0700571
Don Garrett0dd39852013-04-03 16:55:42 -0700572 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
573 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
574 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
575 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
576 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
577 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
578
579 if (!full_rootfs) {
580
581 if (noop) {
582 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
583 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
584 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
585 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
586 EXPECT_EQ(manifest.old_image_info().build_channel(),
587 "test-build-channel");
588 EXPECT_EQ(manifest.old_image_info().build_version(),
589 "test-build-version");
590 } else {
591 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
592 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
593 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
594 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
595 EXPECT_EQ(manifest.old_image_info().build_channel(),
596 "src-build-channel");
597 EXPECT_EQ(manifest.old_image_info().build_version(),
598 "src-build-version");
599 }
600 }
601
602
Darin Petkov7a22d792010-11-08 14:10:00 -0800603 if (full_rootfs) {
604 EXPECT_FALSE(manifest.has_old_rootfs_info());
Don Garrett0dd39852013-04-03 16:55:42 -0700605 EXPECT_FALSE(manifest.has_old_image_info());
606 EXPECT_TRUE(manifest.has_new_image_info());
Darin Petkov7a22d792010-11-08 14:10:00 -0800607 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800608 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800609 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
610 }
611
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800612 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
613 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700614
Darin Petkov36a58222010-10-07 22:00:09 -0700615 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700616 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700617 }
618
Darin Petkov73058b42010-10-06 16:32:19 -0700619 PrefsMock prefs;
620 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800621 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700622 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
623 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700624 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
625 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700626 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
627 .WillRepeatedly(Return(true));
David Zeuthen41996ad2013-09-24 15:43:24 -0700628 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
629 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700630 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700631 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800632 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800633 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
634 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700635 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
636 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800637 }
Darin Petkov73058b42010-10-06 16:32:19 -0700638
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700639 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700640 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800641 install_plan.hash_checks_mandatory = hash_checks_mandatory;
642 install_plan.metadata_size = state->metadata_size;
Don Garrettb8dd1d92013-11-22 17:40:02 -0800643 install_plan.is_full_update = full_kernel && full_rootfs;
644
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800645 LOG(INFO) << "Setting payload metadata size in Omaha = "
646 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700647 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700648 state->delta.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800649 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700650 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700651 &install_plan.metadata_signature));
652 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700653
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800654 *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700655 &state->fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800656 &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700657 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800658 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700659
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800660 EXPECT_EQ(state->image_size,
661 OmahaHashCalculator::RawHashOfFile(state->a_img,
662 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700663 &install_plan.rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800664 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->old_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700665 &install_plan.kernel_hash));
666
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800667 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
668 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
669
David Zeuthena99981f2013-04-29 13:42:47 -0700670 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800671 bool continue_writing;
672 switch(op_hash_test) {
673 case kInvalidOperationData: {
674 // Muck with some random offset post the metadata size so that
675 // some operation hash will result in a mismatch.
676 int some_offset = state->metadata_size + 300;
677 LOG(INFO) << "Tampered value at offset: " << some_offset;
678 state->delta[some_offset]++;
David Zeuthena99981f2013-04-29 13:42:47 -0700679 expected_error = kErrorCodeDownloadOperationHashMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800680 continue_writing = false;
681 break;
682 }
683
684 case kValidOperationData:
685 default:
686 // no change.
David Zeuthena99981f2013-04-29 13:42:47 -0700687 expected_error = kErrorCodeSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800688 continue_writing = true;
689 break;
690 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700691
692 // Write at some number of bytes per operation. Arbitrarily chose 5.
693 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800694 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
695 size_t count = min(state->delta.size() - i, kBytesPerWrite);
696 bool write_succeeded = ((*performer)->Write(&state->delta[i],
697 count,
698 &actual_error));
699 // Normally write_succeeded should be true every time and
David Zeuthena99981f2013-04-29 13:42:47 -0700700 // actual_error should be kErrorCodeSuccess. If so, continue the loop.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800701 // But if we seeded an operation hash error above, then write_succeeded
702 // will be false. The failure may happen at any operation n. So, all
703 // Writes until n-1 should succeed and the nth operation will fail with
704 // actual_error. In this case, we should bail out of the loop because
705 // we cannot proceed applying the delta.
706 if (!write_succeeded) {
707 LOG(INFO) << "Write failed. Checking if it failed with expected error";
708 EXPECT_EQ(expected_error, actual_error);
709 if (!continue_writing) {
710 LOG(INFO) << "Cannot continue writing. Bailing out.";
711 break;
712 }
713 }
714
David Zeuthena99981f2013-04-29 13:42:47 -0700715 EXPECT_EQ(kErrorCodeSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700716 }
717
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800718 // If we had continued all the way through, Close should succeed.
719 // Otherwise, it should fail. Check appropriately.
720 bool close_result = (*performer)->Close();
721 if (continue_writing)
722 EXPECT_EQ(0, close_result);
723 else
724 EXPECT_LE(0, close_result);
725}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700726
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800727void VerifyPayloadResult(DeltaPerformer* performer,
728 DeltaState* state,
David Zeuthena99981f2013-04-29 13:42:47 -0700729 ErrorCode expected_result) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800730 if (!performer) {
731 EXPECT_TRUE(!"Skipping payload verification since performer is NULL.");
732 return;
733 }
734
David Zeuthena99981f2013-04-29 13:42:47 -0700735 int expected_times = (expected_result == kErrorCodeSuccess) ? 1 : 0;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700736 EXPECT_CALL(*(state->fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800737 DownloadComplete()).Times(expected_times);
738
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800739 LOG(INFO) << "Verifying payload for expected result "
740 << expected_result;
741 EXPECT_EQ(expected_result, performer->VerifyPayload(
742 OmahaHashCalculator::OmahaHashOfData(state->delta),
743 state->delta.size()));
744 LOG(INFO) << "Verified payload.";
745
David Zeuthena99981f2013-04-29 13:42:47 -0700746 if (expected_result != kErrorCodeSuccess) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800747 // no need to verify new partition if VerifyPayload failed.
748 return;
749 }
750
751 CompareFilesByBlock(state->old_kernel, state->new_kernel);
752 CompareFilesByBlock(state->a_img, state->b_img);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700753
754 vector<char> updated_kernel_partition;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800755 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
Alex Vakulenko75039d72014-03-25 12:36:28 -0700756 EXPECT_EQ(0, strncmp(updated_kernel_partition.data(), kNewDataString,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800757 strlen(kNewDataString)));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700758
759 uint64_t new_kernel_size;
760 vector<char> new_kernel_hash;
761 uint64_t new_rootfs_size;
762 vector<char> new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800763 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Don Garrett0dd39852013-04-03 16:55:42 -0700764 &new_kernel_hash,
765 &new_rootfs_size,
766 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800767 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700768 vector<char> expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800769 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700770 &expected_new_kernel_hash));
771 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800772 EXPECT_EQ(state->image_size, new_rootfs_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700773 vector<char> expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800774 EXPECT_EQ(state->image_size,
775 OmahaHashCalculator::RawHashOfFile(state->b_img,
776 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700777 &expected_new_rootfs_hash));
778 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
779}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800780
781void VerifyPayload(DeltaPerformer* performer,
782 DeltaState* state,
783 SignatureTest signature_test) {
David Zeuthena99981f2013-04-29 13:42:47 -0700784 ErrorCode expected_result = kErrorCodeSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800785 switch (signature_test) {
786 case kSignatureNone:
David Zeuthena99981f2013-04-29 13:42:47 -0700787 expected_result = kErrorCodeSignedDeltaPayloadExpectedError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800788 break;
789 case kSignatureGeneratedShellBadKey:
David Zeuthena99981f2013-04-29 13:42:47 -0700790 expected_result = kErrorCodeDownloadPayloadPubKeyVerificationError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800791 break;
792 default: break; // appease gcc
793 }
794
795 VerifyPayloadResult(performer, state, expected_result);
796}
797
798void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200799 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800800 SignatureTest signature_test,
801 bool hash_checks_mandatory) {
802 DeltaState state;
803 DeltaPerformer *performer;
Darin Petkov8e447e02013-04-16 16:23:50 +0200804 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
805 signature_test, &state);
Don Garrett0dd39852013-04-03 16:55:42 -0700806
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800807 ScopedPathUnlinker a_img_unlinker(state.a_img);
808 ScopedPathUnlinker b_img_unlinker(state.b_img);
809 ScopedPathUnlinker delta_unlinker(state.delta_path);
810 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
811 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
812 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
813 &state, hash_checks_mandatory, kValidOperationData,
814 &performer);
815 VerifyPayload(performer, &state, signature_test);
816}
817
818// Calls delta performer's Write method by pretending to pass in bytes from a
819// delta file whose metadata size is actual_metadata_size and tests if all
820// checks are correctly performed if the install plan contains
821// expected_metadata_size and that the result of the parsing are as per
822// hash_checks_mandatory flag.
823void DoMetadataSizeTest(uint64_t expected_metadata_size,
824 uint64_t actual_metadata_size,
825 bool hash_checks_mandatory) {
826 PrefsMock prefs;
827 InstallPlan install_plan;
828 install_plan.hash_checks_mandatory = hash_checks_mandatory;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700829 FakeSystemState fake_system_state;
830 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800831 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
832 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
833
834 // Set a valid magic string and version number 1.
835 EXPECT_TRUE(performer.Write("CrAU", 4));
836 uint64_t version = htobe64(1);
837 EXPECT_TRUE(performer.Write(&version, 8));
838
839 install_plan.metadata_size = expected_metadata_size;
David Zeuthena99981f2013-04-29 13:42:47 -0700840 ErrorCode error_code;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800841 // When filling in size in manifest, exclude the size of the 20-byte header.
842 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
843 bool result = performer.Write(&size_in_manifest, 8, &error_code);
844 if (expected_metadata_size == actual_metadata_size ||
845 !hash_checks_mandatory) {
846 EXPECT_TRUE(result);
847 } else {
848 EXPECT_FALSE(result);
David Zeuthena99981f2013-04-29 13:42:47 -0700849 EXPECT_EQ(kErrorCodeDownloadInvalidMetadataSize, error_code);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800850 }
851
852 EXPECT_LT(performer.Close(), 0);
853}
854
855// Generates a valid delta file but tests the delta performer by suppling
856// different metadata signatures as per omaha_metadata_signature flag and
857// sees if the result of the parsing are as per hash_checks_mandatory flag.
858void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
859 SignatureTest signature_test,
860 bool hash_checks_mandatory) {
861 DeltaState state;
862
863 // Using kSignatureNone since it doesn't affect the results of our test.
864 // If we've to use other signature options, then we'd have to get the
865 // metadata size again after adding the signing operation to the manifest.
Darin Petkov8e447e02013-04-16 16:23:50 +0200866 GenerateDeltaFile(true, true, false, -1, signature_test, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800867
868 ScopedPathUnlinker a_img_unlinker(state.a_img);
869 ScopedPathUnlinker b_img_unlinker(state.b_img);
870 ScopedPathUnlinker delta_unlinker(state.delta_path);
871 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
872 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
873
874 // Loads the payload and parses the manifest.
875 vector<char> payload;
876 EXPECT_TRUE(utils::ReadFile(state.delta_path, &payload));
877 LOG(INFO) << "Payload size: " << payload.size();
878
879 InstallPlan install_plan;
880 install_plan.hash_checks_mandatory = hash_checks_mandatory;
881 install_plan.metadata_size = state.metadata_size;
882
883 DeltaPerformer::MetadataParseResult expected_result, actual_result;
David Zeuthena99981f2013-04-29 13:42:47 -0700884 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800885
886 // Fill up the metadata signature in install plan according to the test.
887 switch (metadata_signature_test) {
888 case kEmptyMetadataSignature:
889 install_plan.metadata_signature.clear();
890 expected_result = DeltaPerformer::kMetadataParseError;
David Zeuthena99981f2013-04-29 13:42:47 -0700891 expected_error = kErrorCodeDownloadMetadataSignatureMissingError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800892 break;
893
894 case kInvalidMetadataSignature:
895 install_plan.metadata_signature = kBogusMetadataSignature1;
896 expected_result = DeltaPerformer::kMetadataParseError;
David Zeuthena99981f2013-04-29 13:42:47 -0700897 expected_error = kErrorCodeDownloadMetadataSignatureMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800898 break;
899
900 case kValidMetadataSignature:
901 default:
902 // Set the install plan's metadata size to be the same as the one
903 // in the manifest so that we pass the metadata size checks. Only
904 // then we can get to manifest signature checks.
905 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700906 payload.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800907 state.metadata_size,
908 kUnittestPrivateKeyPath,
909 &install_plan.metadata_signature));
910 EXPECT_FALSE(install_plan.metadata_signature.empty());
911 expected_result = DeltaPerformer::kMetadataParseSuccess;
David Zeuthena99981f2013-04-29 13:42:47 -0700912 expected_error = kErrorCodeSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800913 break;
914 }
915
916 // Ignore the expected result/error if hash checks are not mandatory.
917 if (!hash_checks_mandatory) {
918 expected_result = DeltaPerformer::kMetadataParseSuccess;
David Zeuthena99981f2013-04-29 13:42:47 -0700919 expected_error = kErrorCodeSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800920 }
921
922 // Create the delta performer object.
923 PrefsMock prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800924 DeltaPerformer delta_performer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700925 &state.fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800926 &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800927
928 // Use the public key corresponding to the private key used above to
929 // sign the metadata.
930 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
931 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
932
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800933 // Init actual_error with an invalid value so that we make sure
934 // ParsePayloadMetadata properly populates it in all cases.
David Zeuthena99981f2013-04-29 13:42:47 -0700935 actual_error = kErrorCodeUmaReportedMax;
Gilad Arnolddaa27402014-01-23 11:56:17 -0800936 actual_result = delta_performer.ParsePayloadMetadata(payload, &actual_error);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800937
938 EXPECT_EQ(expected_result, actual_result);
939 EXPECT_EQ(expected_error, actual_error);
940
941 // Check that the parsed metadata size is what's expected. This test
942 // implicitly confirms that the metadata signature is valid, if required.
Gilad Arnoldfe133932014-01-14 12:25:50 -0800943 EXPECT_EQ(state.metadata_size, delta_performer.GetMetadataSize());
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800944}
945
946void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
947 bool hash_checks_mandatory) {
948 DeltaState state;
Darin Petkov8e447e02013-04-16 16:23:50 +0200949 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800950 ScopedPathUnlinker a_img_unlinker(state.a_img);
951 ScopedPathUnlinker b_img_unlinker(state.b_img);
952 ScopedPathUnlinker delta_unlinker(state.delta_path);
953 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
954 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
955 DeltaPerformer *performer;
956 ApplyDeltaFile(true, true, false, kSignatureGenerated,
957 &state, hash_checks_mandatory, op_hash_test, &performer);
958}
959
Don Garrettb8dd1d92013-11-22 17:40:02 -0800960
961class DeltaPerformerTest : public ::testing::Test {
962
963 public:
964 // Test helper placed where it can easily be friended from DeltaPerformer.
965 static void RunManifestValidation(DeltaArchiveManifest& manifest,
966 bool full_payload,
967 ErrorCode expected) {
968 PrefsMock prefs;
969 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700970 FakeSystemState fake_system_state;
971 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800972
973 // The install plan is for Full or Delta.
974 install_plan.is_full_update = full_payload;
975
976 // The Manifest we are validating.
977 performer.manifest_.CopyFrom(manifest);
978
979 EXPECT_EQ(expected, performer.ValidateManifest());
980 }
981};
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800982
983TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
984 uint64_t test[] = {1, 1, 4, 2, kSparseHole, 1, 0, 1};
985 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
986 const uint64_t block_size = 4096;
987 const uint64_t file_length = 5 * block_size - 13;
988
989 google::protobuf::RepeatedPtrField<Extent> extents;
990 for (size_t i = 0; i < arraysize(test); i += 2) {
991 Extent* extent = extents.Add();
992 extent->set_start_block(test[i]);
993 extent->set_num_blocks(test[i + 1]);
994 }
995
996 string expected_output = "4096:4096,16384:8192,-1:4096,0:4083";
997 string actual_output;
998 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
999 block_size,
1000 file_length,
1001 &actual_output));
1002 EXPECT_EQ(expected_output, actual_output);
1003}
Darin Petkov68c10d12010-10-14 09:24:37 -07001004
Don Garrettb8dd1d92013-11-22 17:40:02 -08001005TEST(DeltaPerformerTest, ValidateManifestFullGoodTest) {
1006 // The Manifest we are validating.
1007 DeltaArchiveManifest manifest;
1008 manifest.mutable_new_kernel_info();
1009 manifest.mutable_new_rootfs_info();
1010 manifest.set_minor_version(DeltaPerformer::kFullPayloadMinorVersion);
1011
1012 DeltaPerformerTest::RunManifestValidation(manifest, true, kErrorCodeSuccess);
1013}
1014
1015TEST(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
1016 // The Manifest we are validating.
1017 DeltaArchiveManifest manifest;
1018 manifest.mutable_old_kernel_info();
1019 manifest.mutable_old_rootfs_info();
1020 manifest.mutable_new_kernel_info();
1021 manifest.mutable_new_rootfs_info();
1022 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1023
1024 DeltaPerformerTest::RunManifestValidation(manifest, false, kErrorCodeSuccess);
1025}
1026
1027TEST(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
1028 // The Manifest we are validating.
1029 DeltaArchiveManifest manifest;
1030
1031 DeltaPerformerTest::RunManifestValidation(manifest, true, kErrorCodeSuccess);
1032}
1033
1034TEST(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
1035 // The Manifest we are validating.
1036 DeltaArchiveManifest manifest;
1037
1038 DeltaPerformerTest::RunManifestValidation(
1039 manifest, false,
1040 kErrorCodeUnsupportedMinorPayloadVersion);
1041}
1042
1043TEST(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
1044 // The Manifest we are validating.
1045 DeltaArchiveManifest manifest;
1046 manifest.mutable_old_kernel_info();
1047 manifest.mutable_new_kernel_info();
1048 manifest.mutable_new_rootfs_info();
1049 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1050
1051 DeltaPerformerTest::RunManifestValidation(
1052 manifest, true,
1053 kErrorCodePayloadMismatchedType);
1054}
1055
1056TEST(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
1057 // The Manifest we are validating.
1058 DeltaArchiveManifest manifest;
1059 manifest.mutable_old_rootfs_info();
1060 manifest.mutable_new_kernel_info();
1061 manifest.mutable_new_rootfs_info();
1062 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1063
1064 DeltaPerformerTest::RunManifestValidation(
1065 manifest, true,
1066 kErrorCodePayloadMismatchedType);
1067}
1068
1069TEST(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
1070 // The Manifest we are validating.
1071 DeltaArchiveManifest manifest;
1072
1073 // Generate a bad version number.
1074 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
1075 10000);
1076
1077 DeltaPerformerTest::RunManifestValidation(
1078 manifest, false,
1079 kErrorCodeUnsupportedMinorPayloadVersion);
1080}
1081
Darin Petkov68c10d12010-10-14 09:24:37 -07001082TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001083 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001084 false);
Darin Petkov8e447e02013-04-16 16:23:50 +02001085}
1086
Don Garrett2ae37872013-10-25 13:33:20 -07001087TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
1088 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
1089 false);
1090}
1091
1092TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
1093 DeltaState state;
1094 GenerateDeltaFile(false, false, false, -1,
1095 kSignatureGeneratedPlaceholderMismatch, &state);
1096}
1097
Darin Petkov8e447e02013-04-16 16:23:50 +02001098TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001099 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001100 false);
Darin Petkov68c10d12010-10-14 09:24:37 -07001101}
1102
1103TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001104 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001105 false);
Darin Petkov7a22d792010-11-08 14:10:00 -08001106}
1107
1108TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001109 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001110 true);
Darin Petkov9fa7ec52010-10-18 11:45:23 -07001111}
1112
1113TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001114 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001115 false);
Darin Petkov9574f7e2011-01-13 10:48:12 -08001116}
1117
Darin Petkovcbfb0172011-01-14 15:24:45 -08001118TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001119 DoSmallImageTest(false, false, false, -1, kSignatureNone,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001120 false);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001121}
1122
1123TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001124 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001125 true);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001126}
1127
1128TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001129 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001130 false);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -07001131}
1132
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001133TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001134 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001135 false);
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001136}
1137
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001138TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001139 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001140 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001141}
1142
1143TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001144 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001145 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001146}
1147
Darin Petkov934bb412010-11-18 11:21:35 -08001148TEST(DeltaPerformerTest, BadDeltaMagicTest) {
1149 PrefsMock prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001150 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001151 FakeSystemState fake_system_state;
1152 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -08001153 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1154 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -08001155 EXPECT_TRUE(performer.Write("junk", 4));
1156 EXPECT_TRUE(performer.Write("morejunk", 8));
1157 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -08001158 EXPECT_LT(performer.Close(), 0);
1159}
1160
Andrew de los Reyes353777c2010-10-08 10:34:30 -07001161TEST(DeltaPerformerTest, IsIdempotentOperationTest) {
1162 DeltaArchiveManifest_InstallOperation op;
1163 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1164 *(op.add_dst_extents()) = ExtentForRange(0, 5);
1165 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1166 *(op.add_src_extents()) = ExtentForRange(4, 1);
1167 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1168 op.clear_src_extents();
1169 *(op.add_src_extents()) = ExtentForRange(5, 3);
1170 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1171 *(op.add_dst_extents()) = ExtentForRange(20, 6);
1172 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1173 *(op.add_src_extents()) = ExtentForRange(19, 2);
1174 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1175}
1176
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001177TEST(DeltaPerformerTest, WriteUpdatesPayloadState) {
1178 PrefsMock prefs;
1179 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001180 FakeSystemState fake_system_state;
1181 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001182 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1183 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
1184
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001185 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001186 DownloadProgress(4)).Times(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001187 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001188 DownloadProgress(8)).Times(2);
1189
1190 EXPECT_TRUE(performer.Write("junk", 4));
1191 EXPECT_TRUE(performer.Write("morejunk", 8));
1192 EXPECT_FALSE(performer.Write("morejunk", 8));
1193 EXPECT_LT(performer.Close(), 0);
1194}
1195
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001196TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
1197 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001198}
1199
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001200TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
1201 DoMetadataSizeTest(0, 123456, false);
1202}
1203
1204TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
1205 DoMetadataSizeTest(13000, 140000, true);
1206}
1207
1208TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
1209 DoMetadataSizeTest(40000, 50000, false);
1210}
1211
1212TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
1213 DoMetadataSizeTest(85376, 85376, true);
1214}
1215
1216TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
1217 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, true);
1218}
1219
1220TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
1221 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, false);
1222}
1223
1224TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
1225 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated, true);
1226}
1227
1228TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
1229 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated,
1230 false);
1231}
1232
1233TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
1234 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureNone, true);
1235}
1236
1237TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
1238 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, true);
1239}
1240
1241TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
1242 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, false);
1243}
1244
1245TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
1246 DoOperationHashMismatchTest(kInvalidOperationData, true);
1247}
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001248
David Zeuthene7f89172013-10-31 10:21:04 -07001249TEST(DeltaPerformerTest, UsePublicKeyFromResponse) {
1250 PrefsMock prefs;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001251 FakeSystemState fake_system_state;
David Zeuthene7f89172013-10-31 10:21:04 -07001252 InstallPlan install_plan;
1253 base::FilePath key_path;
1254
1255 // The result of the GetPublicKeyResponse() method is based on three things
1256 //
1257 // 1. Whether it's an official build; and
1258 // 2. Whether the Public RSA key to be used is in the root filesystem; and
1259 // 3. Whether the reponse has a public key
1260 //
1261 // We test all eight combinations to ensure that we only use the
1262 // public key in the response if
1263 //
1264 // a. it's not an official build; and
1265 // b. there is no key in the root filesystem.
1266
1267 DeltaPerformer *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001268 &fake_system_state,
David Zeuthene7f89172013-10-31 10:21:04 -07001269 &install_plan);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001270 FakeHardware* fake_hardware = fake_system_state.fake_hardware();
David Zeuthene7f89172013-10-31 10:21:04 -07001271
1272 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -08001273 EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
David Zeuthene7f89172013-10-31 10:21:04 -07001274 &temp_dir));
1275 string non_existing_file = temp_dir + "/non-existing";
1276 string existing_file = temp_dir + "/existing";
Alex Vakulenko75039d72014-03-25 12:36:28 -07001277 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
David Zeuthene7f89172013-10-31 10:21:04 -07001278
1279 // Non-official build, non-existing public-key, key in response -> true
Don Garrett6646b442013-11-13 15:29:11 -08001280 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001281 performer->public_key_path_ = non_existing_file;
1282 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
1283 EXPECT_TRUE(performer->GetPublicKeyFromResponse(&key_path));
1284 EXPECT_FALSE(key_path.empty());
1285 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
1286 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001287 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001288 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1289
1290 // Non-official build, existing public-key, key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001291 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001292 performer->public_key_path_ = existing_file;
1293 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
1294 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1295 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001296 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001297 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1298
1299 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001300 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001301 performer->public_key_path_ = non_existing_file;
1302 install_plan.public_key_rsa = "";
1303 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1304 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001305 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001306 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1307
1308 // Non-official build, existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001309 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001310 performer->public_key_path_ = existing_file;
1311 install_plan.public_key_rsa = "";
1312 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1313 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001314 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001315 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1316
1317 // Non-official build, non-existing public-key, key in response
1318 // but invalid base64 -> false
Don Garrett6646b442013-11-13 15:29:11 -08001319 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001320 performer->public_key_path_ = non_existing_file;
1321 install_plan.public_key_rsa = "not-valid-base64";
1322 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1323
1324 delete performer;
1325 EXPECT_TRUE(utils::RecursiveUnlinkDir(temp_dir));
1326}
1327
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001328} // namespace chromeos_update_engine