blob: d2a3ebd5e7355eba07391bfe3f844f623dcb46c1 [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>
Darin Petkov73058b42010-10-06 16:32:19 -070014#include <base/string_util.h>
Mike Frysinger8155d082012-04-06 15:23:18 -040015#include <base/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"
Darin Petkov7a22d792010-11-08 14:10:00 -080024#include "update_engine/full_update_generator.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070025#include "update_engine/graph_types.h"
Jay Srinivasanf0572052012-10-23 18:12:56 -070026#include "update_engine/mock_system_state.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.
72 MockSystemState mock_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) {
180 ASSERT_TRUE(utils::MakeTempFile("/tmp/key.XXXXXX",
181 &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,
195 System(StringPrintf(
Mike Frysinger2149be42012-03-12 19:23:47 -0400196 "openssl genrsa -out %s 2048",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800197 private_key_path.c_str())));
198 }
199 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800200 string hash_file;
201 ASSERT_TRUE(utils::MakeTempFile("/tmp/hash.XXXXXX", &hash_file, NULL));
202 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700203 string signature_size_string;
204 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
205 signature_test == kSignatureGeneratedShellRotateCl2)
206 signature_size_string = StringPrintf("%d:%d",
207 signature_size, signature_size);
208 else
209 signature_size_string = StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800210 ASSERT_EQ(0,
211 System(StringPrintf(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700212 "./delta_generator -in_file %s -signature_size %s "
Darin Petkovcbfb0172011-01-14 15:24:45 -0800213 "-out_hash_file %s",
214 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700215 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800216 hash_file.c_str())));
217
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700218 // Pad the hash
219 vector<char> hash;
220 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
221 ASSERT_TRUE(PayloadSigner::PadRSA2048SHA256Hash(&hash));
222 ASSERT_TRUE(WriteFileVector(hash_file, hash));
223
Darin Petkovcbfb0172011-01-14 15:24:45 -0800224 string sig_file;
225 ASSERT_TRUE(utils::MakeTempFile("/tmp/signature.XXXXXX", &sig_file, NULL));
226 ScopedPathUnlinker sig_unlinker(sig_file);
227 ASSERT_EQ(0,
228 System(StringPrintf(
Mike Frysinger2149be42012-03-12 19:23:47 -0400229 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800230 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800231 hash_file.c_str(),
232 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700233 string sig_file2;
234 ASSERT_TRUE(utils::MakeTempFile("/tmp/signature.XXXXXX", &sig_file2, NULL));
235 ScopedPathUnlinker sig2_unlinker(sig_file2);
236 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
237 signature_test == kSignatureGeneratedShellRotateCl2) {
238 ASSERT_EQ(0,
239 System(StringPrintf(
Mike Frysinger2149be42012-03-12 19:23:47 -0400240 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700241 kUnittestPrivateKey2Path,
242 hash_file.c_str(),
243 sig_file2.c_str())));
244 // Append second sig file to first path
245 sig_file += ":" + sig_file2;
246 }
247
Darin Petkovcbfb0172011-01-14 15:24:45 -0800248 ASSERT_EQ(0,
249 System(StringPrintf(
250 "./delta_generator -in_file %s -signature_file %s "
251 "-out_file %s",
252 payload_path.c_str(),
253 sig_file.c_str(),
254 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800255 int verify_result =
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700256 System(StringPrintf(
257 "./delta_generator -in_file %s -public_key %s -public_key_version %d",
258 payload_path.c_str(),
259 signature_test == kSignatureGeneratedShellRotateCl2 ?
260 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
261 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800262 if (signature_test == kSignatureGeneratedShellBadKey) {
263 ASSERT_NE(0, verify_result);
264 } else {
265 ASSERT_EQ(0, verify_result);
266 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800267}
268
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800269static void GenerateDeltaFile(bool full_kernel,
270 bool full_rootfs,
271 bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200272 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800273 SignatureTest signature_test,
274 DeltaState *state) {
275 EXPECT_TRUE(utils::MakeTempFile("/tmp/a_img.XXXXXX", &state->a_img, NULL));
276 EXPECT_TRUE(utils::MakeTempFile("/tmp/b_img.XXXXXX", &state->b_img, NULL));
277 CreateExtImageAtPath(state->a_img, NULL);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700278
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800279 state->image_size = static_cast<int>(utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700280
281 // Extend the "partitions" holding the file system a bit.
282 EXPECT_EQ(0, System(base::StringPrintf(
283 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800284 state->a_img.c_str(),
285 state->image_size + 1024 * 1024 - 1)));
286 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700287
Don Garrett0dd39852013-04-03 16:55:42 -0700288 // Create ImageInfo A & B
289 ImageInfo old_image_info;
290 ImageInfo new_image_info;
291
292 if (!full_rootfs) {
293 old_image_info.set_channel("src-channel");
294 old_image_info.set_board("src-board");
295 old_image_info.set_version("src-version");
296 old_image_info.set_key("src-key");
297 old_image_info.set_build_channel("src-build-channel");
298 old_image_info.set_build_version("src-build-version");
299 }
300
301 new_image_info.set_channel("test-channel");
302 new_image_info.set_board("test-board");
303 new_image_info.set_version("test-version");
304 new_image_info.set_key("test-key");
305 new_image_info.set_build_channel("test-build-channel");
306 new_image_info.set_build_version("test-build-version");
307
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700308 // Make some changes to the A image.
309 {
310 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800311 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700312
Darin Petkov8e447e02013-04-16 16:23:50 +0200313 vector<char> hardtocompress;
314 while (hardtocompress.size() < 3 * kBlockSize) {
315 hardtocompress.insert(hardtocompress.end(),
316 kRandomString,
317 kRandomString + sizeof(kRandomString) - 1);
318 }
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700319 EXPECT_TRUE(utils::WriteFile(StringPrintf("%s/hardtocompress",
320 a_mnt.c_str()).c_str(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200321 &hardtocompress[0],
322 hardtocompress.size()));
323
Darin Petkov8a075a72013-04-25 14:46:09 +0200324 vector<char> zeros(16 * 1024, 0);
325 EXPECT_EQ(zeros.size(),
326 file_util::WriteFile(
327 FilePath(StringPrintf("%s/move-to-sparse", a_mnt.c_str())),
328 &zeros[0], zeros.size()));
329
330 EXPECT_TRUE(
331 WriteSparseFile(StringPrintf("%s/move-from-sparse", a_mnt.c_str()),
332 16 * 1024));
333
334 EXPECT_EQ(0, system(StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse "
335 "bs=1 seek=4096 count=1",
336 a_mnt.c_str()).c_str()));
337
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700338 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
339 // patch fails to zero out the final block.
340 vector<char> ones(1024 * 1024, 0xff);
341 EXPECT_TRUE(utils::WriteFile(StringPrintf("%s/ones",
342 a_mnt.c_str()).c_str(),
343 &ones[0],
344 ones.size()));
345 }
346
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700347 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800348 EXPECT_TRUE(file_util::CopyFile(FilePath(state->a_img),
349 FilePath(state->b_img)));
Don Garrett0dd39852013-04-03 16:55:42 -0700350 old_image_info = new_image_info;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700351 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800352 CreateExtImageAtPath(state->b_img, NULL);
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700353 EXPECT_EQ(0, System(base::StringPrintf(
354 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800355 state->b_img.c_str(),
356 state->image_size + 1024 * 1024 - 1)));
357 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700358
359 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700360 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800361 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700362
363 EXPECT_EQ(0, system(StringPrintf("cp %s/hello %s/hello2", b_mnt.c_str(),
364 b_mnt.c_str()).c_str()));
365 EXPECT_EQ(0, system(StringPrintf("rm %s/hello", b_mnt.c_str()).c_str()));
366 EXPECT_EQ(0, system(StringPrintf("mv %s/hello2 %s/hello", b_mnt.c_str(),
367 b_mnt.c_str()).c_str()));
368 EXPECT_EQ(0, system(StringPrintf("echo foo > %s/foo",
369 b_mnt.c_str()).c_str()));
370 EXPECT_EQ(0, system(StringPrintf("touch %s/emptyfile",
371 b_mnt.c_str()).c_str()));
372 EXPECT_TRUE(WriteSparseFile(StringPrintf("%s/fullsparse", b_mnt.c_str()),
373 1024 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200374
375 EXPECT_TRUE(
376 WriteSparseFile(StringPrintf("%s/move-to-sparse", b_mnt.c_str()),
377 16 * 1024));
378
379 vector<char> zeros(16 * 1024, 0);
380 EXPECT_EQ(zeros.size(),
381 file_util::WriteFile(
382 FilePath(StringPrintf("%s/move-from-sparse", b_mnt.c_str())),
383 &zeros[0], zeros.size()));
384
385 EXPECT_EQ(0, system(StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse "
386 "bs=1 seek=4096 count=1",
387 b_mnt.c_str()).c_str()));
388
389 EXPECT_EQ(0, system(StringPrintf("dd if=/dev/zero of=%s/partsparse bs=1 "
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700390 "seek=4096 count=1",
391 b_mnt.c_str()).c_str()));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800392 EXPECT_EQ(0, system(StringPrintf("cp %s/srchardlink0 %s/tmp && "
393 "mv %s/tmp %s/srchardlink1",
394 b_mnt.c_str(), b_mnt.c_str(),
395 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800396 EXPECT_EQ(0, system(StringPrintf("rm %s/boguslink && "
397 "echo foobar > %s/boguslink",
398 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Darin Petkov8e447e02013-04-16 16:23:50 +0200399
400 vector<char> hardtocompress;
401 while (hardtocompress.size() < 3 * kBlockSize) {
402 hardtocompress.insert(hardtocompress.end(),
403 kRandomString,
404 kRandomString + sizeof(kRandomString));
405 }
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700406 EXPECT_TRUE(utils::WriteFile(StringPrintf("%s/hardtocompress",
407 b_mnt.c_str()).c_str(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200408 &hardtocompress[0],
409 hardtocompress.size()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700410 }
411
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700412 string old_kernel;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800413 EXPECT_TRUE(utils::MakeTempFile("/tmp/old_kernel.XXXXXX",
414 &state->old_kernel,
415 NULL));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700416
417 string new_kernel;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800418 EXPECT_TRUE(utils::MakeTempFile("/tmp/new_kernel.XXXXXX",
419 &state->new_kernel,
420 NULL));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700421
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800422 state->old_kernel_data.resize(kDefaultKernelSize);
423 state->new_kernel_data.resize(state->old_kernel_data.size());
424 FillWithData(&state->old_kernel_data);
425 FillWithData(&state->new_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700426
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700427 // change the new kernel data
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800428 strcpy(&state->new_kernel_data[0], kNewDataString);
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700429
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700430 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800431 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700432 }
433
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700434 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800435 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
436 &state->old_kernel_data[0],
437 state->old_kernel_data.size()));
438 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
439 &state->new_kernel_data[0],
440 state->new_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700441
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800442 EXPECT_TRUE(utils::MakeTempFile("/tmp/delta.XXXXXX",
443 &state->delta_path,
444 NULL));
445 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700446 {
447 string a_mnt, b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800448 ScopedLoopMounter a_mounter(state->a_img, &a_mnt, MS_RDONLY);
449 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, MS_RDONLY);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800450 const string private_key =
451 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700452 EXPECT_TRUE(
Darin Petkov68c10d12010-10-14 09:24:37 -0700453 DeltaDiffGenerator::GenerateDeltaUpdateFile(
Darin Petkov7a22d792010-11-08 14:10:00 -0800454 full_rootfs ? "" : a_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800455 full_rootfs ? "" : state->a_img,
Darin Petkov68c10d12010-10-14 09:24:37 -0700456 b_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800457 state->b_img,
458 full_kernel ? "" : state->old_kernel,
459 state->new_kernel,
460 state->delta_path,
461 private_key,
Darin Petkov8e447e02013-04-16 16:23:50 +0200462 chunk_size,
Chris Sosad5ae1562013-04-23 13:20:18 -0700463 kRootFSPartitionSize,
Don Garrett0dd39852013-04-03 16:55:42 -0700464 full_rootfs ? NULL : &old_image_info,
465 &new_image_info,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800466 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800467 }
468
Don Garrett2ae37872013-10-25 13:33:20 -0700469 if (signature_test == kSignatureGeneratedPlaceholder ||
470 signature_test == kSignatureGeneratedPlaceholderMismatch) {
471
472 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
473 LOG(INFO) << "Inserting placeholder signature.";
474 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
475 &state->metadata_size));
476
477 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
478 signature_size -= 1;
479 LOG(INFO) << "Inserting mismatched placeholder signature.";
480 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
481 &state->metadata_size));
482 return;
483 }
484 }
485
486 if (signature_test == kSignatureGenerated ||
487 signature_test == kSignatureGeneratedPlaceholder ||
488 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800489 // Generate the signed payload and update the metadata size in state to
490 // reflect the new size after adding the signature operation to the
491 // manifest.
Don Garrett2ae37872013-10-25 13:33:20 -0700492 LOG(INFO) << "Signing payload.";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800493 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800494 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700495 signature_test == kSignatureGeneratedShellBadKey ||
496 signature_test == kSignatureGeneratedShellRotateCl1 ||
497 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800498 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700499 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800500}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700501
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800502static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
503 SignatureTest signature_test, DeltaState* state,
504 bool hash_checks_mandatory,
505 OperationHashTest op_hash_test,
506 DeltaPerformer** performer) {
Darin Petkov36a58222010-10-07 22:00:09 -0700507 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700508 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700509 DeltaArchiveManifest manifest;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800510 EXPECT_TRUE(PayloadSigner::LoadPayload(state->delta_path,
511 &state->delta,
512 &manifest,
513 &state->metadata_size));
514 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700515
Don Garrett0dd39852013-04-03 16:55:42 -0700516
517
Darin Petkovcbfb0172011-01-14 15:24:45 -0800518 if (signature_test == kSignatureNone) {
519 EXPECT_FALSE(manifest.has_signatures_offset());
520 EXPECT_FALSE(manifest.has_signatures_size());
521 } else {
522 EXPECT_TRUE(manifest.has_signatures_offset());
523 EXPECT_TRUE(manifest.has_signatures_size());
524 Signatures sigs_message;
525 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800526 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800527 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700528 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
529 signature_test == kSignatureGeneratedShellRotateCl2)
530 EXPECT_EQ(2, sigs_message.signatures_size());
531 else
532 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800533 const Signatures_Signature& signature = sigs_message.signatures(0);
534 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700535
Darin Petkovcbfb0172011-01-14 15:24:45 -0800536 uint64_t expected_sig_data_length = 0;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700537 vector<string> key_paths (1, kUnittestPrivateKeyPath);
538 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
539 signature_test == kSignatureGeneratedShellRotateCl2) {
540 key_paths.push_back(kUnittestPrivateKey2Path);
541 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800542 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700543 key_paths,
544 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800545 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
546 EXPECT_FALSE(signature.data().empty());
547 }
Darin Petkov36a58222010-10-07 22:00:09 -0700548
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700549 if (noop) {
550 EXPECT_EQ(1, manifest.install_operations_size());
551 EXPECT_EQ(1, manifest.kernel_install_operations_size());
552 }
553
Darin Petkovd43d6902010-10-14 11:17:50 -0700554 if (full_kernel) {
555 EXPECT_FALSE(manifest.has_old_kernel_info());
556 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800557 EXPECT_EQ(state->old_kernel_data.size(),
558 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700559 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
560 }
Darin Petkov698d0412010-10-13 10:59:44 -0700561
Don Garrett0dd39852013-04-03 16:55:42 -0700562 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
563 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
564 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
565 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
566 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
567 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
568
569 if (!full_rootfs) {
570
571 if (noop) {
572 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
573 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
574 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
575 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
576 EXPECT_EQ(manifest.old_image_info().build_channel(),
577 "test-build-channel");
578 EXPECT_EQ(manifest.old_image_info().build_version(),
579 "test-build-version");
580 } else {
581 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
582 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
583 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
584 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
585 EXPECT_EQ(manifest.old_image_info().build_channel(),
586 "src-build-channel");
587 EXPECT_EQ(manifest.old_image_info().build_version(),
588 "src-build-version");
589 }
590 }
591
592
Darin Petkov7a22d792010-11-08 14:10:00 -0800593 if (full_rootfs) {
594 EXPECT_FALSE(manifest.has_old_rootfs_info());
Don Garrett0dd39852013-04-03 16:55:42 -0700595 EXPECT_FALSE(manifest.has_old_image_info());
596 EXPECT_TRUE(manifest.has_new_image_info());
Darin Petkov7a22d792010-11-08 14:10:00 -0800597 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800598 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800599 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
600 }
601
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800602 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
603 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700604
Darin Petkov36a58222010-10-07 22:00:09 -0700605 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700606 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700607 }
608
Darin Petkov73058b42010-10-06 16:32:19 -0700609 PrefsMock prefs;
610 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800611 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700612 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
613 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700614 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
615 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700616 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
617 .WillRepeatedly(Return(true));
David Zeuthen41996ad2013-09-24 15:43:24 -0700618 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
619 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700620 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700621 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800622 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800623 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
624 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700625 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
626 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800627 }
Darin Petkov73058b42010-10-06 16:32:19 -0700628
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700629 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700630 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800631 install_plan.hash_checks_mandatory = hash_checks_mandatory;
632 install_plan.metadata_size = state->metadata_size;
633 LOG(INFO) << "Setting payload metadata size in Omaha = "
634 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700635 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800636 &state->delta[0],
637 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700638 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700639 &install_plan.metadata_signature));
640 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700641
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800642 *performer = new DeltaPerformer(&prefs,
643 &state->mock_system_state,
644 &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700645 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800646 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700647
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800648 EXPECT_EQ(state->image_size,
649 OmahaHashCalculator::RawHashOfFile(state->a_img,
650 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700651 &install_plan.rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800652 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->old_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700653 &install_plan.kernel_hash));
654
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800655 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
656 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
657
David Zeuthena99981f2013-04-29 13:42:47 -0700658 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800659 bool continue_writing;
660 switch(op_hash_test) {
661 case kInvalidOperationData: {
662 // Muck with some random offset post the metadata size so that
663 // some operation hash will result in a mismatch.
664 int some_offset = state->metadata_size + 300;
665 LOG(INFO) << "Tampered value at offset: " << some_offset;
666 state->delta[some_offset]++;
David Zeuthena99981f2013-04-29 13:42:47 -0700667 expected_error = kErrorCodeDownloadOperationHashMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800668 continue_writing = false;
669 break;
670 }
671
672 case kValidOperationData:
673 default:
674 // no change.
David Zeuthena99981f2013-04-29 13:42:47 -0700675 expected_error = kErrorCodeSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800676 continue_writing = true;
677 break;
678 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700679
680 // Write at some number of bytes per operation. Arbitrarily chose 5.
681 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800682 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
683 size_t count = min(state->delta.size() - i, kBytesPerWrite);
684 bool write_succeeded = ((*performer)->Write(&state->delta[i],
685 count,
686 &actual_error));
687 // Normally write_succeeded should be true every time and
David Zeuthena99981f2013-04-29 13:42:47 -0700688 // actual_error should be kErrorCodeSuccess. If so, continue the loop.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800689 // But if we seeded an operation hash error above, then write_succeeded
690 // will be false. The failure may happen at any operation n. So, all
691 // Writes until n-1 should succeed and the nth operation will fail with
692 // actual_error. In this case, we should bail out of the loop because
693 // we cannot proceed applying the delta.
694 if (!write_succeeded) {
695 LOG(INFO) << "Write failed. Checking if it failed with expected error";
696 EXPECT_EQ(expected_error, actual_error);
697 if (!continue_writing) {
698 LOG(INFO) << "Cannot continue writing. Bailing out.";
699 break;
700 }
701 }
702
David Zeuthena99981f2013-04-29 13:42:47 -0700703 EXPECT_EQ(kErrorCodeSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700704 }
705
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800706 // If we had continued all the way through, Close should succeed.
707 // Otherwise, it should fail. Check appropriately.
708 bool close_result = (*performer)->Close();
709 if (continue_writing)
710 EXPECT_EQ(0, close_result);
711 else
712 EXPECT_LE(0, close_result);
713}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700714
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800715void VerifyPayloadResult(DeltaPerformer* performer,
716 DeltaState* state,
David Zeuthena99981f2013-04-29 13:42:47 -0700717 ErrorCode expected_result) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800718 if (!performer) {
719 EXPECT_TRUE(!"Skipping payload verification since performer is NULL.");
720 return;
721 }
722
David Zeuthena99981f2013-04-29 13:42:47 -0700723 int expected_times = (expected_result == kErrorCodeSuccess) ? 1 : 0;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800724 EXPECT_CALL(*(state->mock_system_state.mock_payload_state()),
725 DownloadComplete()).Times(expected_times);
726
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800727 LOG(INFO) << "Verifying payload for expected result "
728 << expected_result;
729 EXPECT_EQ(expected_result, performer->VerifyPayload(
730 OmahaHashCalculator::OmahaHashOfData(state->delta),
731 state->delta.size()));
732 LOG(INFO) << "Verified payload.";
733
David Zeuthena99981f2013-04-29 13:42:47 -0700734 if (expected_result != kErrorCodeSuccess) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800735 // no need to verify new partition if VerifyPayload failed.
736 return;
737 }
738
739 CompareFilesByBlock(state->old_kernel, state->new_kernel);
740 CompareFilesByBlock(state->a_img, state->b_img);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700741
742 vector<char> updated_kernel_partition;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800743 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
744 EXPECT_EQ(0, strncmp(&updated_kernel_partition[0], kNewDataString,
745 strlen(kNewDataString)));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700746
747 uint64_t new_kernel_size;
748 vector<char> new_kernel_hash;
749 uint64_t new_rootfs_size;
750 vector<char> new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800751 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Don Garrett0dd39852013-04-03 16:55:42 -0700752 &new_kernel_hash,
753 &new_rootfs_size,
754 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800755 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700756 vector<char> expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800757 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700758 &expected_new_kernel_hash));
759 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800760 EXPECT_EQ(state->image_size, new_rootfs_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700761 vector<char> expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800762 EXPECT_EQ(state->image_size,
763 OmahaHashCalculator::RawHashOfFile(state->b_img,
764 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700765 &expected_new_rootfs_hash));
766 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
767}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800768
769void VerifyPayload(DeltaPerformer* performer,
770 DeltaState* state,
771 SignatureTest signature_test) {
David Zeuthena99981f2013-04-29 13:42:47 -0700772 ErrorCode expected_result = kErrorCodeSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800773 switch (signature_test) {
774 case kSignatureNone:
David Zeuthena99981f2013-04-29 13:42:47 -0700775 expected_result = kErrorCodeSignedDeltaPayloadExpectedError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800776 break;
777 case kSignatureGeneratedShellBadKey:
David Zeuthena99981f2013-04-29 13:42:47 -0700778 expected_result = kErrorCodeDownloadPayloadPubKeyVerificationError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800779 break;
780 default: break; // appease gcc
781 }
782
783 VerifyPayloadResult(performer, state, expected_result);
784}
785
786void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200787 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800788 SignatureTest signature_test,
789 bool hash_checks_mandatory) {
790 DeltaState state;
791 DeltaPerformer *performer;
Darin Petkov8e447e02013-04-16 16:23:50 +0200792 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
793 signature_test, &state);
Don Garrett0dd39852013-04-03 16:55:42 -0700794
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800795 ScopedPathUnlinker a_img_unlinker(state.a_img);
796 ScopedPathUnlinker b_img_unlinker(state.b_img);
797 ScopedPathUnlinker delta_unlinker(state.delta_path);
798 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
799 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
800 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
801 &state, hash_checks_mandatory, kValidOperationData,
802 &performer);
803 VerifyPayload(performer, &state, signature_test);
804}
805
806// Calls delta performer's Write method by pretending to pass in bytes from a
807// delta file whose metadata size is actual_metadata_size and tests if all
808// checks are correctly performed if the install plan contains
809// expected_metadata_size and that the result of the parsing are as per
810// hash_checks_mandatory flag.
811void DoMetadataSizeTest(uint64_t expected_metadata_size,
812 uint64_t actual_metadata_size,
813 bool hash_checks_mandatory) {
814 PrefsMock prefs;
815 InstallPlan install_plan;
816 install_plan.hash_checks_mandatory = hash_checks_mandatory;
817 MockSystemState mock_system_state;
818 DeltaPerformer performer(&prefs, &mock_system_state, &install_plan);
819 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
820 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
821
822 // Set a valid magic string and version number 1.
823 EXPECT_TRUE(performer.Write("CrAU", 4));
824 uint64_t version = htobe64(1);
825 EXPECT_TRUE(performer.Write(&version, 8));
826
827 install_plan.metadata_size = expected_metadata_size;
David Zeuthena99981f2013-04-29 13:42:47 -0700828 ErrorCode error_code;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800829 // When filling in size in manifest, exclude the size of the 20-byte header.
830 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
831 bool result = performer.Write(&size_in_manifest, 8, &error_code);
832 if (expected_metadata_size == actual_metadata_size ||
833 !hash_checks_mandatory) {
834 EXPECT_TRUE(result);
835 } else {
836 EXPECT_FALSE(result);
David Zeuthena99981f2013-04-29 13:42:47 -0700837 EXPECT_EQ(kErrorCodeDownloadInvalidMetadataSize, error_code);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800838 }
839
840 EXPECT_LT(performer.Close(), 0);
841}
842
843// Generates a valid delta file but tests the delta performer by suppling
844// different metadata signatures as per omaha_metadata_signature flag and
845// sees if the result of the parsing are as per hash_checks_mandatory flag.
846void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
847 SignatureTest signature_test,
848 bool hash_checks_mandatory) {
849 DeltaState state;
850
851 // Using kSignatureNone since it doesn't affect the results of our test.
852 // If we've to use other signature options, then we'd have to get the
853 // metadata size again after adding the signing operation to the manifest.
Darin Petkov8e447e02013-04-16 16:23:50 +0200854 GenerateDeltaFile(true, true, false, -1, signature_test, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800855
856 ScopedPathUnlinker a_img_unlinker(state.a_img);
857 ScopedPathUnlinker b_img_unlinker(state.b_img);
858 ScopedPathUnlinker delta_unlinker(state.delta_path);
859 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
860 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
861
862 // Loads the payload and parses the manifest.
863 vector<char> payload;
864 EXPECT_TRUE(utils::ReadFile(state.delta_path, &payload));
865 LOG(INFO) << "Payload size: " << payload.size();
866
867 InstallPlan install_plan;
868 install_plan.hash_checks_mandatory = hash_checks_mandatory;
869 install_plan.metadata_size = state.metadata_size;
870
871 DeltaPerformer::MetadataParseResult expected_result, actual_result;
David Zeuthena99981f2013-04-29 13:42:47 -0700872 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800873
874 // Fill up the metadata signature in install plan according to the test.
875 switch (metadata_signature_test) {
876 case kEmptyMetadataSignature:
877 install_plan.metadata_signature.clear();
878 expected_result = DeltaPerformer::kMetadataParseError;
David Zeuthena99981f2013-04-29 13:42:47 -0700879 expected_error = kErrorCodeDownloadMetadataSignatureMissingError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800880 break;
881
882 case kInvalidMetadataSignature:
883 install_plan.metadata_signature = kBogusMetadataSignature1;
884 expected_result = DeltaPerformer::kMetadataParseError;
David Zeuthena99981f2013-04-29 13:42:47 -0700885 expected_error = kErrorCodeDownloadMetadataSignatureMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800886 break;
887
888 case kValidMetadataSignature:
889 default:
890 // Set the install plan's metadata size to be the same as the one
891 // in the manifest so that we pass the metadata size checks. Only
892 // then we can get to manifest signature checks.
893 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
894 &payload[0],
895 state.metadata_size,
896 kUnittestPrivateKeyPath,
897 &install_plan.metadata_signature));
898 EXPECT_FALSE(install_plan.metadata_signature.empty());
899 expected_result = DeltaPerformer::kMetadataParseSuccess;
David Zeuthena99981f2013-04-29 13:42:47 -0700900 expected_error = kErrorCodeSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800901 break;
902 }
903
904 // Ignore the expected result/error if hash checks are not mandatory.
905 if (!hash_checks_mandatory) {
906 expected_result = DeltaPerformer::kMetadataParseSuccess;
David Zeuthena99981f2013-04-29 13:42:47 -0700907 expected_error = kErrorCodeSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800908 }
909
910 // Create the delta performer object.
911 PrefsMock prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800912 DeltaPerformer delta_performer(&prefs,
913 &state.mock_system_state,
914 &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800915
916 // Use the public key corresponding to the private key used above to
917 // sign the metadata.
918 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
919 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
920
921 // Parse the delta payload we created.
922 DeltaArchiveManifest manifest;
923 uint64_t parsed_metadata_size;
924
925 // Init actual_error with an invalid value so that we make sure
926 // ParsePayloadMetadata properly populates it in all cases.
David Zeuthena99981f2013-04-29 13:42:47 -0700927 actual_error = kErrorCodeUmaReportedMax;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800928 actual_result = delta_performer.ParsePayloadMetadata(payload, &manifest,
929 &parsed_metadata_size, &actual_error);
930
931 EXPECT_EQ(expected_result, actual_result);
932 EXPECT_EQ(expected_error, actual_error);
933
934 // Check that the parsed metadata size is what's expected. This test
935 // implicitly confirms that the metadata signature is valid, if required.
936 EXPECT_EQ(state.metadata_size, parsed_metadata_size);
937}
938
939void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
940 bool hash_checks_mandatory) {
941 DeltaState state;
Darin Petkov8e447e02013-04-16 16:23:50 +0200942 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800943 ScopedPathUnlinker a_img_unlinker(state.a_img);
944 ScopedPathUnlinker b_img_unlinker(state.b_img);
945 ScopedPathUnlinker delta_unlinker(state.delta_path);
946 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
947 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
948 DeltaPerformer *performer;
949 ApplyDeltaFile(true, true, false, kSignatureGenerated,
950 &state, hash_checks_mandatory, op_hash_test, &performer);
951}
952
953class DeltaPerformerTest : public ::testing::Test { };
954
955TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
956 uint64_t test[] = {1, 1, 4, 2, kSparseHole, 1, 0, 1};
957 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
958 const uint64_t block_size = 4096;
959 const uint64_t file_length = 5 * block_size - 13;
960
961 google::protobuf::RepeatedPtrField<Extent> extents;
962 for (size_t i = 0; i < arraysize(test); i += 2) {
963 Extent* extent = extents.Add();
964 extent->set_start_block(test[i]);
965 extent->set_num_blocks(test[i + 1]);
966 }
967
968 string expected_output = "4096:4096,16384:8192,-1:4096,0:4083";
969 string actual_output;
970 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
971 block_size,
972 file_length,
973 &actual_output));
974 EXPECT_EQ(expected_output, actual_output);
975}
Darin Petkov68c10d12010-10-14 09:24:37 -0700976
977TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +0200978 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -0700979 false);
Darin Petkov8e447e02013-04-16 16:23:50 +0200980}
981
Don Garrett2ae37872013-10-25 13:33:20 -0700982TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
983 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
984 false);
985}
986
987TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
988 DeltaState state;
989 GenerateDeltaFile(false, false, false, -1,
990 kSignatureGeneratedPlaceholderMismatch, &state);
991}
992
Darin Petkov8e447e02013-04-16 16:23:50 +0200993TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +0200994 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -0700995 false);
Darin Petkov68c10d12010-10-14 09:24:37 -0700996}
997
998TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +0200999 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001000 false);
Darin Petkov7a22d792010-11-08 14:10:00 -08001001}
1002
1003TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001004 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001005 true);
Darin Petkov9fa7ec52010-10-18 11:45:23 -07001006}
1007
1008TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001009 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001010 false);
Darin Petkov9574f7e2011-01-13 10:48:12 -08001011}
1012
Darin Petkovcbfb0172011-01-14 15:24:45 -08001013TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001014 DoSmallImageTest(false, false, false, -1, kSignatureNone,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001015 false);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001016}
1017
1018TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001019 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001020 true);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001021}
1022
1023TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001024 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001025 false);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -07001026}
1027
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001028TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001029 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001030 false);
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001031}
1032
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001033TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001034 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001035 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001036}
1037
1038TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001039 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001040 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001041}
1042
Darin Petkov934bb412010-11-18 11:21:35 -08001043TEST(DeltaPerformerTest, BadDeltaMagicTest) {
1044 PrefsMock prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001045 InstallPlan install_plan;
Jay Srinivasanf0572052012-10-23 18:12:56 -07001046 MockSystemState mock_system_state;
1047 DeltaPerformer performer(&prefs, &mock_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -08001048 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1049 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -08001050 EXPECT_TRUE(performer.Write("junk", 4));
1051 EXPECT_TRUE(performer.Write("morejunk", 8));
1052 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -08001053 EXPECT_LT(performer.Close(), 0);
1054}
1055
Andrew de los Reyes353777c2010-10-08 10:34:30 -07001056TEST(DeltaPerformerTest, IsIdempotentOperationTest) {
1057 DeltaArchiveManifest_InstallOperation op;
1058 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1059 *(op.add_dst_extents()) = ExtentForRange(0, 5);
1060 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1061 *(op.add_src_extents()) = ExtentForRange(4, 1);
1062 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1063 op.clear_src_extents();
1064 *(op.add_src_extents()) = ExtentForRange(5, 3);
1065 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1066 *(op.add_dst_extents()) = ExtentForRange(20, 6);
1067 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1068 *(op.add_src_extents()) = ExtentForRange(19, 2);
1069 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1070}
1071
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001072TEST(DeltaPerformerTest, WriteUpdatesPayloadState) {
1073 PrefsMock prefs;
1074 InstallPlan install_plan;
1075 MockSystemState mock_system_state;
1076 DeltaPerformer performer(&prefs, &mock_system_state, &install_plan);
1077 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1078 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
1079
1080 EXPECT_CALL(*(mock_system_state.mock_payload_state()),
1081 DownloadProgress(4)).Times(1);
1082 EXPECT_CALL(*(mock_system_state.mock_payload_state()),
1083 DownloadProgress(8)).Times(2);
1084
1085 EXPECT_TRUE(performer.Write("junk", 4));
1086 EXPECT_TRUE(performer.Write("morejunk", 8));
1087 EXPECT_FALSE(performer.Write("morejunk", 8));
1088 EXPECT_LT(performer.Close(), 0);
1089}
1090
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001091TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
1092 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001093}
1094
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001095TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
1096 DoMetadataSizeTest(0, 123456, false);
1097}
1098
1099TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
1100 DoMetadataSizeTest(13000, 140000, true);
1101}
1102
1103TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
1104 DoMetadataSizeTest(40000, 50000, false);
1105}
1106
1107TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
1108 DoMetadataSizeTest(85376, 85376, true);
1109}
1110
1111TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
1112 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, true);
1113}
1114
1115TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
1116 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, false);
1117}
1118
1119TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
1120 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated, true);
1121}
1122
1123TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
1124 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated,
1125 false);
1126}
1127
1128TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
1129 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureNone, true);
1130}
1131
1132TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
1133 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, true);
1134}
1135
1136TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
1137 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, false);
1138}
1139
1140TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
1141 DoOperationHashMismatchTest(kInvalidOperationData, true);
1142}
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001143
David Zeuthene7f89172013-10-31 10:21:04 -07001144TEST(DeltaPerformerTest, UsePublicKeyFromResponse) {
1145 PrefsMock prefs;
1146 MockSystemState mock_system_state;
1147 InstallPlan install_plan;
1148 base::FilePath key_path;
1149
1150 // The result of the GetPublicKeyResponse() method is based on three things
1151 //
1152 // 1. Whether it's an official build; and
1153 // 2. Whether the Public RSA key to be used is in the root filesystem; and
1154 // 3. Whether the reponse has a public key
1155 //
1156 // We test all eight combinations to ensure that we only use the
1157 // public key in the response if
1158 //
1159 // a. it's not an official build; and
1160 // b. there is no key in the root filesystem.
1161
1162 DeltaPerformer *performer = new DeltaPerformer(&prefs,
1163 &mock_system_state,
1164 &install_plan);
Don Garrett83692e42013-11-08 10:11:30 -08001165 FakeHardware& fake_hardware = mock_system_state.get_mock_hardware().fake();
David Zeuthene7f89172013-10-31 10:21:04 -07001166
1167 string temp_dir;
1168 EXPECT_TRUE(utils::MakeTempDirectory("/tmp/PublicKeyFromResponseTests.XXXXXX",
1169 &temp_dir));
1170 string non_existing_file = temp_dir + "/non-existing";
1171 string existing_file = temp_dir + "/existing";
1172 EXPECT_EQ(0, System(StringPrintf("touch %s", existing_file.c_str())));
1173
1174 // Non-official build, non-existing public-key, key in response -> true
Don Garrett83692e42013-11-08 10:11:30 -08001175 fake_hardware.SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001176 performer->public_key_path_ = non_existing_file;
1177 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
1178 EXPECT_TRUE(performer->GetPublicKeyFromResponse(&key_path));
1179 EXPECT_FALSE(key_path.empty());
1180 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
1181 // Same with official build -> false
Don Garrett83692e42013-11-08 10:11:30 -08001182 fake_hardware.SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001183 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1184
1185 // Non-official build, existing public-key, key in response -> false
Don Garrett83692e42013-11-08 10:11:30 -08001186 fake_hardware.SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001187 performer->public_key_path_ = existing_file;
1188 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
1189 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1190 // Same with official build -> false
Don Garrett83692e42013-11-08 10:11:30 -08001191 fake_hardware.SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001192 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1193
1194 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett83692e42013-11-08 10:11:30 -08001195 fake_hardware.SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001196 performer->public_key_path_ = non_existing_file;
1197 install_plan.public_key_rsa = "";
1198 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1199 // Same with official build -> false
Don Garrett83692e42013-11-08 10:11:30 -08001200 fake_hardware.SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001201 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1202
1203 // Non-official build, existing public-key, no key in response -> false
Don Garrett83692e42013-11-08 10:11:30 -08001204 fake_hardware.SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001205 performer->public_key_path_ = existing_file;
1206 install_plan.public_key_rsa = "";
1207 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1208 // Same with official build -> false
Don Garrett83692e42013-11-08 10:11:30 -08001209 fake_hardware.SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001210 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1211
1212 // Non-official build, non-existing public-key, key in response
1213 // but invalid base64 -> false
Don Garrett83692e42013-11-08 10:11:30 -08001214 fake_hardware.SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001215 performer->public_key_path_ = non_existing_file;
1216 install_plan.public_key_rsa = "not-valid-base64";
1217 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1218
1219 delete performer;
1220 EXPECT_TRUE(utils::RecursiveUnlinkDir(temp_dir));
1221}
1222
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001223} // namespace chromeos_update_engine