blob: 226427f5e05ba30958f54c064001eb397bb77d35 [file] [log] [blame]
Mike Frysinger8155d082012-04-06 15:23:18 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07005#include <inttypes.h>
Alex Deymo161c4a12014-05-16 15:56:21 -07006#include <sys/mount.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07007
8#include <algorithm>
9#include <string>
10#include <vector>
11
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_performer.h"
Andrew de los Reyes353777c2010-10-08 10:34:30 -070021#include "update_engine/extent_ranges.h"
David Zeuthene7f89172013-10-31 10:21:04 -070022#include "update_engine/fake_hardware.h"
Gilad Arnold5bb4c902014-04-10 12:32:13 -070023#include "update_engine/fake_system_state.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070024#include "update_engine/payload_constants.h"
25#include "update_engine/payload_generator/delta_diff_generator.h"
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070026#include "update_engine/payload_signer.h"
Darin Petkov73058b42010-10-06 16:32:19 -070027#include "update_engine/prefs_mock.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070028#include "update_engine/test_utils.h"
29#include "update_engine/update_metadata.pb.h"
30#include "update_engine/utils.h"
31
32namespace chromeos_update_engine {
33
34using std::min;
35using std::string;
36using std::vector;
Darin Petkov73058b42010-10-06 16:32:19 -070037using testing::Return;
Alex Deymo161c4a12014-05-16 15:56:21 -070038using testing::_;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070039
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070040extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070041extern const char* kUnittestPublicKeyPath;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070042extern const char* kUnittestPrivateKey2Path;
43extern const char* kUnittestPublicKey2Path;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070044
Jay Srinivasan738fdf32012-12-07 17:40:54 -080045static const size_t kBlockSize = 4096;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -070046static const char* kBogusMetadataSignature1 =
47 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
48 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
49 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
50 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
51 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
52 "pLRtClp97kN2+tXGNBQqkA==";
Jay Srinivasan738fdf32012-12-07 17:40:54 -080053
Alex Vakulenkod2779df2014-06-16 13:19:00 -070054static const int kDefaultKernelSize = 4096; // Something small for a test
Jay Srinivasan738fdf32012-12-07 17:40:54 -080055static const char* kNewDataString = "This is new data.";
56
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070057namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080058struct DeltaState {
59 string a_img;
60 string b_img;
61 int image_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070062
Jay Srinivasan738fdf32012-12-07 17:40:54 -080063 string delta_path;
64 uint64_t metadata_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070065
Jay Srinivasan738fdf32012-12-07 17:40:54 -080066 string old_kernel;
67 vector<char> old_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070068
Jay Srinivasan738fdf32012-12-07 17:40:54 -080069 string new_kernel;
70 vector<char> new_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070071
Jay Srinivasan738fdf32012-12-07 17:40:54 -080072 // The in-memory copy of delta file.
73 vector<char> delta;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080074
75 // The mock system state object with which we initialize the
76 // delta performer.
Gilad Arnold5bb4c902014-04-10 12:32:13 -070077 FakeSystemState fake_system_state;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080078};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070079
Jay Srinivasan738fdf32012-12-07 17:40:54 -080080enum SignatureTest {
81 kSignatureNone, // No payload signing.
82 kSignatureGenerator, // Sign the payload at generation time.
83 kSignatureGenerated, // Sign the payload after it's generated.
Don Garrett2ae37872013-10-25 13:33:20 -070084 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
Alex Vakulenkod2779df2014-06-16 13:19:00 -070085 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
Jay Srinivasan738fdf32012-12-07 17:40:54 -080086 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
87 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
88 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
89 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
90};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070091
Jay Srinivasan738fdf32012-12-07 17:40:54 -080092// Different options that determine what we should fill into the
93// install_plan.metadata_signature to simulate the contents received in the
94// Omaha response.
95enum MetadataSignatureTest {
96 kEmptyMetadataSignature,
97 kInvalidMetadataSignature,
98 kValidMetadataSignature,
99};
100
101enum OperationHashTest {
102 kInvalidOperationData,
103 kValidOperationData,
104};
105
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700106} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800107
108static void CompareFilesByBlock(const string& a_file, const string& b_file) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700109 vector<char> a_data, b_data;
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700110 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
111 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700112
113 EXPECT_EQ(a_data.size(), b_data.size());
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700114 EXPECT_EQ(0, a_data.size() % kBlockSize);
115 for (size_t i = 0; i < a_data.size(); i += kBlockSize) {
116 EXPECT_EQ(0, i % kBlockSize);
117 vector<char> a_sub(&a_data[i], &a_data[i + kBlockSize]);
118 vector<char> b_sub(&b_data[i], &b_data[i + kBlockSize]);
119 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
120 }
121}
122
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800123static bool WriteSparseFile(const string& path, off_t size) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700124 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
125 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
126 ScopedFdCloser fd_closer(&fd);
127 off_t rc = lseek(fd, size + 1, SEEK_SET);
128 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
129 int return_code = ftruncate(fd, size);
130 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
131 return true;
132}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700133
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800134static size_t GetSignatureSize(const string& private_key_path) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800135 const vector<char> data(1, 'x');
136 vector<char> hash;
137 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(data, &hash));
138 vector<char> signature;
139 EXPECT_TRUE(PayloadSigner::SignHash(hash,
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800140 private_key_path,
Darin Petkovcbfb0172011-01-14 15:24:45 -0800141 &signature));
142 return signature.size();
143}
144
Don Garrett2ae37872013-10-25 13:33:20 -0700145static bool InsertSignaturePlaceholder(int signature_size,
146 const string& payload_path,
147 uint64_t* out_metadata_size) {
148 vector<vector<char> > signatures;
149 signatures.push_back(vector<char>(signature_size, 0));
150
151 return PayloadSigner::AddSignatureToPayload(
152 payload_path,
153 signatures,
154 payload_path,
155 out_metadata_size);
156}
157
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800158static void SignGeneratedPayload(const string& payload_path,
159 uint64_t* out_metadata_size) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800160 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800161 vector<char> hash;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700162 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
163 payload_path,
164 vector<int>(1, signature_size),
165 &hash));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800166 vector<char> signature;
167 ASSERT_TRUE(PayloadSigner::SignHash(hash,
168 kUnittestPrivateKeyPath,
169 &signature));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700170 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
171 payload_path,
172 vector<vector<char> >(1, signature),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800173 payload_path,
174 out_metadata_size));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700175 EXPECT_TRUE(PayloadSigner::VerifySignedPayload(
176 payload_path,
177 kUnittestPublicKeyPath,
178 kSignatureMessageOriginalVersion));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800179}
180
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800181static void SignGeneratedShellPayload(SignatureTest signature_test,
182 const string& payload_path) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800183 string private_key_path = kUnittestPrivateKeyPath;
184 if (signature_test == kSignatureGeneratedShellBadKey) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800185 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800186 &private_key_path,
187 NULL));
188 } else {
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700189 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
190 signature_test == kSignatureGeneratedShellRotateCl1 ||
191 signature_test == kSignatureGeneratedShellRotateCl2);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800192 }
193 ScopedPathUnlinker key_unlinker(private_key_path);
194 key_unlinker.set_should_remove(signature_test ==
195 kSignatureGeneratedShellBadKey);
196 // Generates a new private key that will not match the public key.
197 if (signature_test == kSignatureGeneratedShellBadKey) {
198 LOG(INFO) << "Generating a mismatched private key.";
Alex Deymo719bfff2014-07-11 12:12:32 -0700199 ASSERT_EQ(0, System(base::StringPrintf(
200 "%s genrsa -out %s 2048",
201 utils::GetPathOnBoard("openssl").c_str(), private_key_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800202 }
203 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800204 string hash_file;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800205 ASSERT_TRUE(utils::MakeTempFile("hash.XXXXXX", &hash_file, NULL));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800206 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700207 string signature_size_string;
208 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
209 signature_test == kSignatureGeneratedShellRotateCl2)
Alex Vakulenko75039d72014-03-25 12:36:28 -0700210 signature_size_string = base::StringPrintf("%d:%d",
211 signature_size, signature_size);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700212 else
Alex Vakulenko75039d72014-03-25 12:36:28 -0700213 signature_size_string = base::StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800214 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700215 System(base::StringPrintf(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700216 "./delta_generator -in_file %s -signature_size %s "
Darin Petkovcbfb0172011-01-14 15:24:45 -0800217 "-out_hash_file %s",
218 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700219 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800220 hash_file.c_str())));
221
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700222 // Pad the hash
223 vector<char> hash;
224 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
225 ASSERT_TRUE(PayloadSigner::PadRSA2048SHA256Hash(&hash));
226 ASSERT_TRUE(WriteFileVector(hash_file, hash));
227
Darin Petkovcbfb0172011-01-14 15:24:45 -0800228 string sig_file;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800229 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file, NULL));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800230 ScopedPathUnlinker sig_unlinker(sig_file);
231 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700232 System(base::StringPrintf(
Alex Deymo719bfff2014-07-11 12:12:32 -0700233 "%s rsautl -raw -sign -inkey %s -in %s -out %s",
234 utils::GetPathOnBoard("openssl").c_str(),
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800235 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800236 hash_file.c_str(),
237 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700238 string sig_file2;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800239 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file2, NULL));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700240 ScopedPathUnlinker sig2_unlinker(sig_file2);
241 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
242 signature_test == kSignatureGeneratedShellRotateCl2) {
243 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700244 System(base::StringPrintf(
Alex Deymo719bfff2014-07-11 12:12:32 -0700245 "%s rsautl -raw -sign -inkey %s -in %s -out %s",
246 utils::GetPathOnBoard("openssl").c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700247 kUnittestPrivateKey2Path,
248 hash_file.c_str(),
249 sig_file2.c_str())));
250 // Append second sig file to first path
251 sig_file += ":" + sig_file2;
252 }
253
Darin Petkovcbfb0172011-01-14 15:24:45 -0800254 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700255 System(base::StringPrintf(
Darin Petkovcbfb0172011-01-14 15:24:45 -0800256 "./delta_generator -in_file %s -signature_file %s "
257 "-out_file %s",
258 payload_path.c_str(),
259 sig_file.c_str(),
260 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800261 int verify_result =
Alex Vakulenko75039d72014-03-25 12:36:28 -0700262 System(base::StringPrintf(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700263 "./delta_generator -in_file %s -public_key %s -public_key_version %d",
264 payload_path.c_str(),
265 signature_test == kSignatureGeneratedShellRotateCl2 ?
266 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
267 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800268 if (signature_test == kSignatureGeneratedShellBadKey) {
269 ASSERT_NE(0, verify_result);
270 } else {
271 ASSERT_EQ(0, verify_result);
272 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800273}
274
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800275static void GenerateDeltaFile(bool full_kernel,
276 bool full_rootfs,
277 bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200278 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800279 SignatureTest signature_test,
280 DeltaState *state) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800281 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, NULL));
282 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, NULL));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800283 CreateExtImageAtPath(state->a_img, NULL);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700284
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800285 state->image_size = static_cast<int>(utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700286
287 // Extend the "partitions" holding the file system a bit.
288 EXPECT_EQ(0, System(base::StringPrintf(
289 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800290 state->a_img.c_str(),
291 state->image_size + 1024 * 1024 - 1)));
292 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700293
Don Garrett0dd39852013-04-03 16:55:42 -0700294 // Create ImageInfo A & B
295 ImageInfo old_image_info;
296 ImageInfo new_image_info;
297
298 if (!full_rootfs) {
299 old_image_info.set_channel("src-channel");
300 old_image_info.set_board("src-board");
301 old_image_info.set_version("src-version");
302 old_image_info.set_key("src-key");
303 old_image_info.set_build_channel("src-build-channel");
304 old_image_info.set_build_version("src-build-version");
305 }
306
307 new_image_info.set_channel("test-channel");
308 new_image_info.set_board("test-board");
309 new_image_info.set_version("test-version");
310 new_image_info.set_key("test-key");
311 new_image_info.set_build_channel("test-build-channel");
312 new_image_info.set_build_version("test-build-version");
313
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700314 // Make some changes to the A image.
315 {
316 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800317 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700318
Darin Petkov8e447e02013-04-16 16:23:50 +0200319 vector<char> hardtocompress;
320 while (hardtocompress.size() < 3 * kBlockSize) {
321 hardtocompress.insert(hardtocompress.end(),
322 kRandomString,
323 kRandomString + sizeof(kRandomString) - 1);
324 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700325 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700326 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700327 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200328 hardtocompress.size()));
329
Darin Petkov8a075a72013-04-25 14:46:09 +0200330 vector<char> zeros(16 * 1024, 0);
331 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700332 base::WriteFile(base::FilePath(base::StringPrintf(
333 "%s/move-to-sparse", a_mnt.c_str())),
334 zeros.data(), zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200335
336 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700337 WriteSparseFile(base::StringPrintf("%s/move-from-sparse",
338 a_mnt.c_str()), 16 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200339
Alex Vakulenko75039d72014-03-25 12:36:28 -0700340 EXPECT_EQ(0,
341 system(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
342 " bs=1 seek=4096 count=1",
Darin Petkov8a075a72013-04-25 14:46:09 +0200343 a_mnt.c_str()).c_str()));
344
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700345 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
346 // patch fails to zero out the final block.
347 vector<char> ones(1024 * 1024, 0xff);
Alex Vakulenko75039d72014-03-25 12:36:28 -0700348 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/ones",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700349 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700350 ones.data(),
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700351 ones.size()));
352 }
353
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700354 if (noop) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700355 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img),
356 base::FilePath(state->b_img)));
Don Garrett0dd39852013-04-03 16:55:42 -0700357 old_image_info = new_image_info;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700358 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800359 CreateExtImageAtPath(state->b_img, NULL);
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700360 EXPECT_EQ(0, System(base::StringPrintf(
361 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800362 state->b_img.c_str(),
363 state->image_size + 1024 * 1024 - 1)));
364 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700365
366 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700367 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800368 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700369
Alex Vakulenko75039d72014-03-25 12:36:28 -0700370 EXPECT_EQ(0, system(base::StringPrintf("cp %s/hello %s/hello2",
371 b_mnt.c_str(),
372 b_mnt.c_str()).c_str()));
373 EXPECT_EQ(0, system(base::StringPrintf("rm %s/hello",
374 b_mnt.c_str()).c_str()));
375 EXPECT_EQ(0, system(base::StringPrintf("mv %s/hello2 %s/hello",
376 b_mnt.c_str(),
377 b_mnt.c_str()).c_str()));
378 EXPECT_EQ(0, system(base::StringPrintf("echo foo > %s/foo",
379 b_mnt.c_str()).c_str()));
380 EXPECT_EQ(0, system(base::StringPrintf("touch %s/emptyfile",
381 b_mnt.c_str()).c_str()));
382 EXPECT_TRUE(WriteSparseFile(base::StringPrintf("%s/fullsparse",
383 b_mnt.c_str()),
384 1024 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200385
386 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700387 WriteSparseFile(base::StringPrintf("%s/move-to-sparse", b_mnt.c_str()),
Darin Petkov8a075a72013-04-25 14:46:09 +0200388 16 * 1024));
389
390 vector<char> zeros(16 * 1024, 0);
391 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700392 base::WriteFile(base::FilePath(base::StringPrintf(
393 "%s/move-from-sparse", b_mnt.c_str())),
394 zeros.data(), zeros.size()));
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/move-semi-sparse "
398 "bs=1 seek=4096 count=1",
399 b_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200400
Alex Vakulenko75039d72014-03-25 12:36:28 -0700401 EXPECT_EQ(0, system(base::StringPrintf("dd if=/dev/zero "
402 "of=%s/partsparse bs=1 "
403 "seek=4096 count=1",
404 b_mnt.c_str()).c_str()));
405 EXPECT_EQ(0, system(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
406 "mv %s/tmp %s/srchardlink1",
407 b_mnt.c_str(),
408 b_mnt.c_str(),
409 b_mnt.c_str(),
410 b_mnt.c_str()).c_str()));
411 EXPECT_EQ(0, system(base::StringPrintf("rm %s/boguslink && "
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800412 "echo foobar > %s/boguslink",
413 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Darin Petkov8e447e02013-04-16 16:23:50 +0200414
415 vector<char> hardtocompress;
416 while (hardtocompress.size() < 3 * kBlockSize) {
417 hardtocompress.insert(hardtocompress.end(),
418 kRandomString,
419 kRandomString + sizeof(kRandomString));
420 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700421 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700422 b_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700423 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200424 hardtocompress.size()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700425 }
426
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700427 string old_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800428 EXPECT_TRUE(utils::MakeTempFile("old_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800429 &state->old_kernel,
430 NULL));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700431
432 string new_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800433 EXPECT_TRUE(utils::MakeTempFile("new_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800434 &state->new_kernel,
435 NULL));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700436
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800437 state->old_kernel_data.resize(kDefaultKernelSize);
438 state->new_kernel_data.resize(state->old_kernel_data.size());
439 FillWithData(&state->old_kernel_data);
440 FillWithData(&state->new_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700441
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700442 // change the new kernel data
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700443 strcpy(&state->new_kernel_data[0], kNewDataString); // NOLINT(runtime/printf)
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700444
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700445 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800446 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700447 }
448
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700449 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800450 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700451 state->old_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800452 state->old_kernel_data.size()));
453 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700454 state->new_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800455 state->new_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700456
Gilad Arnolda6742b32014-01-11 00:18:34 -0800457 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800458 &state->delta_path,
459 NULL));
460 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700461 {
462 string a_mnt, b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800463 ScopedLoopMounter a_mounter(state->a_img, &a_mnt, MS_RDONLY);
464 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, MS_RDONLY);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800465 const string private_key =
466 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700467 EXPECT_TRUE(
Darin Petkov68c10d12010-10-14 09:24:37 -0700468 DeltaDiffGenerator::GenerateDeltaUpdateFile(
Darin Petkov7a22d792010-11-08 14:10:00 -0800469 full_rootfs ? "" : a_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800470 full_rootfs ? "" : state->a_img,
Darin Petkov68c10d12010-10-14 09:24:37 -0700471 b_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800472 state->b_img,
473 full_kernel ? "" : state->old_kernel,
474 state->new_kernel,
475 state->delta_path,
476 private_key,
Darin Petkov8e447e02013-04-16 16:23:50 +0200477 chunk_size,
Chris Sosad5ae1562013-04-23 13:20:18 -0700478 kRootFSPartitionSize,
Don Garrett0dd39852013-04-03 16:55:42 -0700479 full_rootfs ? NULL : &old_image_info,
480 &new_image_info,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800481 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800482 }
483
Don Garrett2ae37872013-10-25 13:33:20 -0700484 if (signature_test == kSignatureGeneratedPlaceholder ||
485 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Don Garrett2ae37872013-10-25 13:33:20 -0700486 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
487 LOG(INFO) << "Inserting placeholder signature.";
488 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
489 &state->metadata_size));
490
491 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
492 signature_size -= 1;
493 LOG(INFO) << "Inserting mismatched placeholder signature.";
494 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
495 &state->metadata_size));
496 return;
497 }
498 }
499
500 if (signature_test == kSignatureGenerated ||
501 signature_test == kSignatureGeneratedPlaceholder ||
502 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800503 // Generate the signed payload and update the metadata size in state to
504 // reflect the new size after adding the signature operation to the
505 // manifest.
Don Garrett2ae37872013-10-25 13:33:20 -0700506 LOG(INFO) << "Signing payload.";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800507 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800508 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700509 signature_test == kSignatureGeneratedShellBadKey ||
510 signature_test == kSignatureGeneratedShellRotateCl1 ||
511 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800512 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700513 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800514}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700515
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800516static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
517 SignatureTest signature_test, DeltaState* state,
518 bool hash_checks_mandatory,
519 OperationHashTest op_hash_test,
520 DeltaPerformer** performer) {
Darin Petkov36a58222010-10-07 22:00:09 -0700521 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700522 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700523 DeltaArchiveManifest manifest;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800524 EXPECT_TRUE(PayloadSigner::LoadPayload(state->delta_path,
525 &state->delta,
526 &manifest,
527 &state->metadata_size));
528 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700529
Don Garrett0dd39852013-04-03 16:55:42 -0700530
531
Darin Petkovcbfb0172011-01-14 15:24:45 -0800532 if (signature_test == kSignatureNone) {
533 EXPECT_FALSE(manifest.has_signatures_offset());
534 EXPECT_FALSE(manifest.has_signatures_size());
535 } else {
536 EXPECT_TRUE(manifest.has_signatures_offset());
537 EXPECT_TRUE(manifest.has_signatures_size());
538 Signatures sigs_message;
539 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800540 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800541 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700542 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
543 signature_test == kSignatureGeneratedShellRotateCl2)
544 EXPECT_EQ(2, sigs_message.signatures_size());
545 else
546 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800547 const Signatures_Signature& signature = sigs_message.signatures(0);
548 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700549
Darin Petkovcbfb0172011-01-14 15:24:45 -0800550 uint64_t expected_sig_data_length = 0;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700551 vector<string> key_paths{kUnittestPrivateKeyPath};
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700552 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
553 signature_test == kSignatureGeneratedShellRotateCl2) {
554 key_paths.push_back(kUnittestPrivateKey2Path);
555 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800556 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700557 key_paths,
558 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800559 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
560 EXPECT_FALSE(signature.data().empty());
561 }
Darin Petkov36a58222010-10-07 22:00:09 -0700562
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700563 if (noop) {
564 EXPECT_EQ(1, manifest.install_operations_size());
565 EXPECT_EQ(1, manifest.kernel_install_operations_size());
566 }
567
Darin Petkovd43d6902010-10-14 11:17:50 -0700568 if (full_kernel) {
569 EXPECT_FALSE(manifest.has_old_kernel_info());
570 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800571 EXPECT_EQ(state->old_kernel_data.size(),
572 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700573 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
574 }
Darin Petkov698d0412010-10-13 10:59:44 -0700575
Don Garrett0dd39852013-04-03 16:55:42 -0700576 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
577 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
578 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
579 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
580 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
581 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
582
583 if (!full_rootfs) {
Don Garrett0dd39852013-04-03 16:55:42 -0700584 if (noop) {
585 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
586 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
587 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
588 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
589 EXPECT_EQ(manifest.old_image_info().build_channel(),
590 "test-build-channel");
591 EXPECT_EQ(manifest.old_image_info().build_version(),
592 "test-build-version");
593 } else {
594 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
595 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
596 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
597 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
598 EXPECT_EQ(manifest.old_image_info().build_channel(),
599 "src-build-channel");
600 EXPECT_EQ(manifest.old_image_info().build_version(),
601 "src-build-version");
602 }
603 }
604
605
Darin Petkov7a22d792010-11-08 14:10:00 -0800606 if (full_rootfs) {
607 EXPECT_FALSE(manifest.has_old_rootfs_info());
Don Garrett0dd39852013-04-03 16:55:42 -0700608 EXPECT_FALSE(manifest.has_old_image_info());
609 EXPECT_TRUE(manifest.has_new_image_info());
Darin Petkov7a22d792010-11-08 14:10:00 -0800610 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800611 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800612 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
613 }
614
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800615 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
616 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700617
Darin Petkov36a58222010-10-07 22:00:09 -0700618 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700619 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700620 }
621
Darin Petkov73058b42010-10-06 16:32:19 -0700622 PrefsMock prefs;
623 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800624 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700625 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
626 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700627 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
628 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700629 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
630 .WillRepeatedly(Return(true));
David Zeuthen41996ad2013-09-24 15:43:24 -0700631 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
632 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700633 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700634 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800635 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800636 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
637 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700638 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
639 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800640 }
Darin Petkov73058b42010-10-06 16:32:19 -0700641
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700642 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700643 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800644 install_plan.hash_checks_mandatory = hash_checks_mandatory;
645 install_plan.metadata_size = state->metadata_size;
Don Garrettb8dd1d92013-11-22 17:40:02 -0800646 install_plan.is_full_update = full_kernel && full_rootfs;
647
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800648 LOG(INFO) << "Setting payload metadata size in Omaha = "
649 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700650 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700651 state->delta.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800652 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700653 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700654 &install_plan.metadata_signature));
655 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700656
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800657 *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700658 &state->fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800659 &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700660 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800661 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700662
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800663 EXPECT_EQ(state->image_size,
664 OmahaHashCalculator::RawHashOfFile(state->a_img,
665 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700666 &install_plan.rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800667 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->old_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700668 &install_plan.kernel_hash));
669
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800670 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
671 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
672
David Zeuthena99981f2013-04-29 13:42:47 -0700673 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800674 bool continue_writing;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700675 switch (op_hash_test) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800676 case kInvalidOperationData: {
677 // Muck with some random offset post the metadata size so that
678 // some operation hash will result in a mismatch.
679 int some_offset = state->metadata_size + 300;
680 LOG(INFO) << "Tampered value at offset: " << some_offset;
681 state->delta[some_offset]++;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700682 expected_error = ErrorCode::kDownloadOperationHashMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800683 continue_writing = false;
684 break;
685 }
686
687 case kValidOperationData:
688 default:
689 // no change.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700690 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800691 continue_writing = true;
692 break;
693 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700694
695 // Write at some number of bytes per operation. Arbitrarily chose 5.
696 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800697 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
698 size_t count = min(state->delta.size() - i, kBytesPerWrite);
699 bool write_succeeded = ((*performer)->Write(&state->delta[i],
700 count,
701 &actual_error));
702 // Normally write_succeeded should be true every time and
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700703 // actual_error should be ErrorCode::kSuccess. If so, continue the loop.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800704 // But if we seeded an operation hash error above, then write_succeeded
705 // will be false. The failure may happen at any operation n. So, all
706 // Writes until n-1 should succeed and the nth operation will fail with
707 // actual_error. In this case, we should bail out of the loop because
708 // we cannot proceed applying the delta.
709 if (!write_succeeded) {
710 LOG(INFO) << "Write failed. Checking if it failed with expected error";
711 EXPECT_EQ(expected_error, actual_error);
712 if (!continue_writing) {
713 LOG(INFO) << "Cannot continue writing. Bailing out.";
714 break;
715 }
716 }
717
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700718 EXPECT_EQ(ErrorCode::kSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700719 }
720
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800721 // If we had continued all the way through, Close should succeed.
722 // Otherwise, it should fail. Check appropriately.
723 bool close_result = (*performer)->Close();
724 if (continue_writing)
725 EXPECT_EQ(0, close_result);
726 else
727 EXPECT_LE(0, close_result);
728}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700729
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800730void VerifyPayloadResult(DeltaPerformer* performer,
731 DeltaState* state,
David Zeuthena99981f2013-04-29 13:42:47 -0700732 ErrorCode expected_result) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800733 if (!performer) {
734 EXPECT_TRUE(!"Skipping payload verification since performer is NULL.");
735 return;
736 }
737
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700738 int expected_times = (expected_result == ErrorCode::kSuccess) ? 1 : 0;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700739 EXPECT_CALL(*(state->fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800740 DownloadComplete()).Times(expected_times);
741
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800742 LOG(INFO) << "Verifying payload for expected result "
743 << expected_result;
744 EXPECT_EQ(expected_result, performer->VerifyPayload(
745 OmahaHashCalculator::OmahaHashOfData(state->delta),
746 state->delta.size()));
747 LOG(INFO) << "Verified payload.";
748
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700749 if (expected_result != ErrorCode::kSuccess) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800750 // no need to verify new partition if VerifyPayload failed.
751 return;
752 }
753
754 CompareFilesByBlock(state->old_kernel, state->new_kernel);
755 CompareFilesByBlock(state->a_img, state->b_img);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700756
757 vector<char> updated_kernel_partition;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800758 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
Alex Vakulenko75039d72014-03-25 12:36:28 -0700759 EXPECT_EQ(0, strncmp(updated_kernel_partition.data(), kNewDataString,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800760 strlen(kNewDataString)));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700761
762 uint64_t new_kernel_size;
763 vector<char> new_kernel_hash;
764 uint64_t new_rootfs_size;
765 vector<char> new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800766 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Don Garrett0dd39852013-04-03 16:55:42 -0700767 &new_kernel_hash,
768 &new_rootfs_size,
769 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800770 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700771 vector<char> expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800772 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700773 &expected_new_kernel_hash));
774 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800775 EXPECT_EQ(state->image_size, new_rootfs_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700776 vector<char> expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800777 EXPECT_EQ(state->image_size,
778 OmahaHashCalculator::RawHashOfFile(state->b_img,
779 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700780 &expected_new_rootfs_hash));
781 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
782}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800783
784void VerifyPayload(DeltaPerformer* performer,
785 DeltaState* state,
786 SignatureTest signature_test) {
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700787 ErrorCode expected_result = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800788 switch (signature_test) {
789 case kSignatureNone:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700790 expected_result = ErrorCode::kSignedDeltaPayloadExpectedError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800791 break;
792 case kSignatureGeneratedShellBadKey:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700793 expected_result = ErrorCode::kDownloadPayloadPubKeyVerificationError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800794 break;
795 default: break; // appease gcc
796 }
797
798 VerifyPayloadResult(performer, state, expected_result);
799}
800
801void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200802 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800803 SignatureTest signature_test,
804 bool hash_checks_mandatory) {
805 DeltaState state;
Alex Deymo52146ce2014-05-29 11:09:45 -0700806 DeltaPerformer *performer = nullptr;
Darin Petkov8e447e02013-04-16 16:23:50 +0200807 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
808 signature_test, &state);
Don Garrett0dd39852013-04-03 16:55:42 -0700809
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800810 ScopedPathUnlinker a_img_unlinker(state.a_img);
811 ScopedPathUnlinker b_img_unlinker(state.b_img);
812 ScopedPathUnlinker delta_unlinker(state.delta_path);
813 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
814 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
815 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
816 &state, hash_checks_mandatory, kValidOperationData,
817 &performer);
818 VerifyPayload(performer, &state, signature_test);
Alex Deymo52146ce2014-05-29 11:09:45 -0700819 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800820}
821
822// Calls delta performer's Write method by pretending to pass in bytes from a
823// delta file whose metadata size is actual_metadata_size and tests if all
824// checks are correctly performed if the install plan contains
825// expected_metadata_size and that the result of the parsing are as per
826// hash_checks_mandatory flag.
827void DoMetadataSizeTest(uint64_t expected_metadata_size,
828 uint64_t actual_metadata_size,
829 bool hash_checks_mandatory) {
830 PrefsMock prefs;
831 InstallPlan install_plan;
832 install_plan.hash_checks_mandatory = hash_checks_mandatory;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700833 FakeSystemState fake_system_state;
834 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800835 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
836 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
837
838 // Set a valid magic string and version number 1.
839 EXPECT_TRUE(performer.Write("CrAU", 4));
840 uint64_t version = htobe64(1);
841 EXPECT_TRUE(performer.Write(&version, 8));
842
843 install_plan.metadata_size = expected_metadata_size;
David Zeuthena99981f2013-04-29 13:42:47 -0700844 ErrorCode error_code;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800845 // When filling in size in manifest, exclude the size of the 20-byte header.
846 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
847 bool result = performer.Write(&size_in_manifest, 8, &error_code);
848 if (expected_metadata_size == actual_metadata_size ||
849 !hash_checks_mandatory) {
850 EXPECT_TRUE(result);
851 } else {
852 EXPECT_FALSE(result);
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700853 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800854 }
855
856 EXPECT_LT(performer.Close(), 0);
857}
858
859// Generates a valid delta file but tests the delta performer by suppling
860// different metadata signatures as per omaha_metadata_signature flag and
861// sees if the result of the parsing are as per hash_checks_mandatory flag.
862void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
863 SignatureTest signature_test,
864 bool hash_checks_mandatory) {
865 DeltaState state;
866
867 // Using kSignatureNone since it doesn't affect the results of our test.
868 // If we've to use other signature options, then we'd have to get the
869 // metadata size again after adding the signing operation to the manifest.
Darin Petkov8e447e02013-04-16 16:23:50 +0200870 GenerateDeltaFile(true, true, false, -1, signature_test, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800871
872 ScopedPathUnlinker a_img_unlinker(state.a_img);
873 ScopedPathUnlinker b_img_unlinker(state.b_img);
874 ScopedPathUnlinker delta_unlinker(state.delta_path);
875 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
876 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
877
878 // Loads the payload and parses the manifest.
879 vector<char> payload;
880 EXPECT_TRUE(utils::ReadFile(state.delta_path, &payload));
881 LOG(INFO) << "Payload size: " << payload.size();
882
883 InstallPlan install_plan;
884 install_plan.hash_checks_mandatory = hash_checks_mandatory;
885 install_plan.metadata_size = state.metadata_size;
886
887 DeltaPerformer::MetadataParseResult expected_result, actual_result;
David Zeuthena99981f2013-04-29 13:42:47 -0700888 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800889
890 // Fill up the metadata signature in install plan according to the test.
891 switch (metadata_signature_test) {
892 case kEmptyMetadataSignature:
893 install_plan.metadata_signature.clear();
894 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700895 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800896 break;
897
898 case kInvalidMetadataSignature:
899 install_plan.metadata_signature = kBogusMetadataSignature1;
900 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700901 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800902 break;
903
904 case kValidMetadataSignature:
905 default:
906 // Set the install plan's metadata size to be the same as the one
907 // in the manifest so that we pass the metadata size checks. Only
908 // then we can get to manifest signature checks.
909 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700910 payload.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800911 state.metadata_size,
912 kUnittestPrivateKeyPath,
913 &install_plan.metadata_signature));
914 EXPECT_FALSE(install_plan.metadata_signature.empty());
915 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700916 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800917 break;
918 }
919
920 // Ignore the expected result/error if hash checks are not mandatory.
921 if (!hash_checks_mandatory) {
922 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700923 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800924 }
925
926 // Create the delta performer object.
927 PrefsMock prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800928 DeltaPerformer delta_performer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700929 &state.fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800930 &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800931
932 // Use the public key corresponding to the private key used above to
933 // sign the metadata.
934 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
935 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
936
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800937 // Init actual_error with an invalid value so that we make sure
938 // ParsePayloadMetadata properly populates it in all cases.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700939 actual_error = ErrorCode::kUmaReportedMax;
Gilad Arnolddaa27402014-01-23 11:56:17 -0800940 actual_result = delta_performer.ParsePayloadMetadata(payload, &actual_error);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800941
942 EXPECT_EQ(expected_result, actual_result);
943 EXPECT_EQ(expected_error, actual_error);
944
945 // Check that the parsed metadata size is what's expected. This test
946 // implicitly confirms that the metadata signature is valid, if required.
Gilad Arnoldfe133932014-01-14 12:25:50 -0800947 EXPECT_EQ(state.metadata_size, delta_performer.GetMetadataSize());
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800948}
949
950void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
951 bool hash_checks_mandatory) {
952 DeltaState state;
Darin Petkov8e447e02013-04-16 16:23:50 +0200953 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800954 ScopedPathUnlinker a_img_unlinker(state.a_img);
955 ScopedPathUnlinker b_img_unlinker(state.b_img);
956 ScopedPathUnlinker delta_unlinker(state.delta_path);
957 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
958 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Alex Deymo52146ce2014-05-29 11:09:45 -0700959 DeltaPerformer *performer = nullptr;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800960 ApplyDeltaFile(true, true, false, kSignatureGenerated,
961 &state, hash_checks_mandatory, op_hash_test, &performer);
Alex Deymo52146ce2014-05-29 11:09:45 -0700962 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800963}
964
Don Garrettb8dd1d92013-11-22 17:40:02 -0800965
966class DeltaPerformerTest : public ::testing::Test {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800967 public:
968 // Test helper placed where it can easily be friended from DeltaPerformer.
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700969 static void RunManifestValidation(const DeltaArchiveManifest& manifest,
Don Garrettb8dd1d92013-11-22 17:40:02 -0800970 bool full_payload,
971 ErrorCode expected) {
972 PrefsMock prefs;
973 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700974 FakeSystemState fake_system_state;
975 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800976
977 // The install plan is for Full or Delta.
978 install_plan.is_full_update = full_payload;
979
980 // The Manifest we are validating.
981 performer.manifest_.CopyFrom(manifest);
982
983 EXPECT_EQ(expected, performer.ValidateManifest());
984 }
985};
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800986
987TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
988 uint64_t test[] = {1, 1, 4, 2, kSparseHole, 1, 0, 1};
989 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
990 const uint64_t block_size = 4096;
991 const uint64_t file_length = 5 * block_size - 13;
992
993 google::protobuf::RepeatedPtrField<Extent> extents;
994 for (size_t i = 0; i < arraysize(test); i += 2) {
995 Extent* extent = extents.Add();
996 extent->set_start_block(test[i]);
997 extent->set_num_blocks(test[i + 1]);
998 }
999
1000 string expected_output = "4096:4096,16384:8192,-1:4096,0:4083";
1001 string actual_output;
1002 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
1003 block_size,
1004 file_length,
1005 &actual_output));
1006 EXPECT_EQ(expected_output, actual_output);
1007}
Darin Petkov68c10d12010-10-14 09:24:37 -07001008
Don Garrettb8dd1d92013-11-22 17:40:02 -08001009TEST(DeltaPerformerTest, ValidateManifestFullGoodTest) {
1010 // The Manifest we are validating.
1011 DeltaArchiveManifest manifest;
1012 manifest.mutable_new_kernel_info();
1013 manifest.mutable_new_rootfs_info();
1014 manifest.set_minor_version(DeltaPerformer::kFullPayloadMinorVersion);
1015
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001016 DeltaPerformerTest::RunManifestValidation(manifest, true,
1017 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001018}
1019
1020TEST(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
1021 // The Manifest we are validating.
1022 DeltaArchiveManifest manifest;
1023 manifest.mutable_old_kernel_info();
1024 manifest.mutable_old_rootfs_info();
1025 manifest.mutable_new_kernel_info();
1026 manifest.mutable_new_rootfs_info();
1027 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1028
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001029 DeltaPerformerTest::RunManifestValidation(manifest, false,
1030 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001031}
1032
1033TEST(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
1034 // The Manifest we are validating.
1035 DeltaArchiveManifest manifest;
1036
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001037 DeltaPerformerTest::RunManifestValidation(manifest, true,
1038 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001039}
1040
1041TEST(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
1042 // The Manifest we are validating.
1043 DeltaArchiveManifest manifest;
1044
1045 DeltaPerformerTest::RunManifestValidation(
1046 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001047 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001048}
1049
1050TEST(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
1051 // The Manifest we are validating.
1052 DeltaArchiveManifest manifest;
1053 manifest.mutable_old_kernel_info();
1054 manifest.mutable_new_kernel_info();
1055 manifest.mutable_new_rootfs_info();
1056 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1057
1058 DeltaPerformerTest::RunManifestValidation(
1059 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001060 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001061}
1062
1063TEST(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
1064 // The Manifest we are validating.
1065 DeltaArchiveManifest manifest;
1066 manifest.mutable_old_rootfs_info();
1067 manifest.mutable_new_kernel_info();
1068 manifest.mutable_new_rootfs_info();
1069 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1070
1071 DeltaPerformerTest::RunManifestValidation(
1072 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001073 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001074}
1075
1076TEST(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
1077 // The Manifest we are validating.
1078 DeltaArchiveManifest manifest;
1079
1080 // Generate a bad version number.
1081 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
1082 10000);
1083
1084 DeltaPerformerTest::RunManifestValidation(
1085 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001086 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001087}
1088
Darin Petkov68c10d12010-10-14 09:24:37 -07001089TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001090 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001091 false);
Darin Petkov8e447e02013-04-16 16:23:50 +02001092}
1093
Don Garrett2ae37872013-10-25 13:33:20 -07001094TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
1095 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
1096 false);
1097}
1098
1099TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
1100 DeltaState state;
1101 GenerateDeltaFile(false, false, false, -1,
1102 kSignatureGeneratedPlaceholderMismatch, &state);
1103}
1104
Darin Petkov8e447e02013-04-16 16:23:50 +02001105TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001106 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001107 false);
Darin Petkov68c10d12010-10-14 09:24:37 -07001108}
1109
1110TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001111 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001112 false);
Darin Petkov7a22d792010-11-08 14:10:00 -08001113}
1114
1115TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001116 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001117 true);
Darin Petkov9fa7ec52010-10-18 11:45:23 -07001118}
1119
1120TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001121 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001122 false);
Darin Petkov9574f7e2011-01-13 10:48:12 -08001123}
1124
Darin Petkovcbfb0172011-01-14 15:24:45 -08001125TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001126 DoSmallImageTest(false, false, false, -1, kSignatureNone,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001127 false);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001128}
1129
1130TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001131 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001132 true);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001133}
1134
1135TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001136 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001137 false);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -07001138}
1139
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001140TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001141 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001142 false);
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001143}
1144
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001145TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001146 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001147 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001148}
1149
1150TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001151 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001152 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001153}
1154
Darin Petkov934bb412010-11-18 11:21:35 -08001155TEST(DeltaPerformerTest, BadDeltaMagicTest) {
1156 PrefsMock prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001157 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001158 FakeSystemState fake_system_state;
1159 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -08001160 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1161 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -08001162 EXPECT_TRUE(performer.Write("junk", 4));
1163 EXPECT_TRUE(performer.Write("morejunk", 8));
1164 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -08001165 EXPECT_LT(performer.Close(), 0);
1166}
1167
Andrew de los Reyes353777c2010-10-08 10:34:30 -07001168TEST(DeltaPerformerTest, IsIdempotentOperationTest) {
1169 DeltaArchiveManifest_InstallOperation op;
1170 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1171 *(op.add_dst_extents()) = ExtentForRange(0, 5);
1172 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1173 *(op.add_src_extents()) = ExtentForRange(4, 1);
1174 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1175 op.clear_src_extents();
1176 *(op.add_src_extents()) = ExtentForRange(5, 3);
1177 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1178 *(op.add_dst_extents()) = ExtentForRange(20, 6);
1179 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1180 *(op.add_src_extents()) = ExtentForRange(19, 2);
1181 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1182}
1183
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001184TEST(DeltaPerformerTest, WriteUpdatesPayloadState) {
1185 PrefsMock prefs;
1186 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001187 FakeSystemState fake_system_state;
1188 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001189 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1190 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
1191
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001192 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001193 DownloadProgress(4)).Times(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001194 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001195 DownloadProgress(8)).Times(2);
1196
1197 EXPECT_TRUE(performer.Write("junk", 4));
1198 EXPECT_TRUE(performer.Write("morejunk", 8));
1199 EXPECT_FALSE(performer.Write("morejunk", 8));
1200 EXPECT_LT(performer.Close(), 0);
1201}
1202
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001203TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
1204 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001205}
1206
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001207TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
1208 DoMetadataSizeTest(0, 123456, false);
1209}
1210
1211TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
1212 DoMetadataSizeTest(13000, 140000, true);
1213}
1214
1215TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
1216 DoMetadataSizeTest(40000, 50000, false);
1217}
1218
1219TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
1220 DoMetadataSizeTest(85376, 85376, true);
1221}
1222
1223TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
1224 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, true);
1225}
1226
1227TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
1228 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, false);
1229}
1230
1231TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
1232 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated, true);
1233}
1234
1235TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
1236 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated,
1237 false);
1238}
1239
1240TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
1241 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureNone, true);
1242}
1243
1244TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
1245 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, true);
1246}
1247
1248TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
1249 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, false);
1250}
1251
1252TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
1253 DoOperationHashMismatchTest(kInvalidOperationData, true);
1254}
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001255
David Zeuthene7f89172013-10-31 10:21:04 -07001256TEST(DeltaPerformerTest, UsePublicKeyFromResponse) {
1257 PrefsMock prefs;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001258 FakeSystemState fake_system_state;
David Zeuthene7f89172013-10-31 10:21:04 -07001259 InstallPlan install_plan;
1260 base::FilePath key_path;
1261
1262 // The result of the GetPublicKeyResponse() method is based on three things
1263 //
1264 // 1. Whether it's an official build; and
1265 // 2. Whether the Public RSA key to be used is in the root filesystem; and
1266 // 3. Whether the reponse has a public key
1267 //
1268 // We test all eight combinations to ensure that we only use the
1269 // public key in the response if
1270 //
1271 // a. it's not an official build; and
1272 // b. there is no key in the root filesystem.
1273
1274 DeltaPerformer *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001275 &fake_system_state,
David Zeuthene7f89172013-10-31 10:21:04 -07001276 &install_plan);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001277 FakeHardware* fake_hardware = fake_system_state.fake_hardware();
David Zeuthene7f89172013-10-31 10:21:04 -07001278
1279 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -08001280 EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
David Zeuthene7f89172013-10-31 10:21:04 -07001281 &temp_dir));
1282 string non_existing_file = temp_dir + "/non-existing";
1283 string existing_file = temp_dir + "/existing";
Alex Vakulenko75039d72014-03-25 12:36:28 -07001284 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
David Zeuthene7f89172013-10-31 10:21:04 -07001285
1286 // Non-official build, non-existing public-key, key in response -> true
Don Garrett6646b442013-11-13 15:29:11 -08001287 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001288 performer->public_key_path_ = non_existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001289 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001290 EXPECT_TRUE(performer->GetPublicKeyFromResponse(&key_path));
1291 EXPECT_FALSE(key_path.empty());
1292 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
1293 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001294 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001295 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1296
1297 // Non-official build, existing public-key, key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001298 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001299 performer->public_key_path_ = existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001300 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001301 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1302 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001303 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001304 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1305
1306 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001307 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001308 performer->public_key_path_ = non_existing_file;
1309 install_plan.public_key_rsa = "";
1310 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1311 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001312 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001313 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1314
1315 // Non-official build, existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001316 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001317 performer->public_key_path_ = existing_file;
1318 install_plan.public_key_rsa = "";
1319 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1320 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001321 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001322 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1323
1324 // Non-official build, non-existing public-key, key in response
1325 // but invalid base64 -> false
Don Garrett6646b442013-11-13 15:29:11 -08001326 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001327 performer->public_key_path_ = non_existing_file;
1328 install_plan.public_key_rsa = "not-valid-base64";
1329 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1330
1331 delete performer;
1332 EXPECT_TRUE(utils::RecursiveUnlinkDir(temp_dir));
1333}
1334
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001335} // namespace chromeos_update_engine