blob: af257df5389fbdfe3b818bc47063db1a2b5befe1 [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
Alex Deymo8427b4a2014-11-05 14:00:32 -08005#include "update_engine/delta_performer.h"
6
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07007#include <inttypes.h>
Alex Deymo161c4a12014-05-16 15:56:21 -07008#include <sys/mount.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07009
10#include <algorithm>
11#include <string>
12#include <vector>
13
Ben Chan06c76a42014-09-05 08:21:06 -070014#include <base/files/file_util.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070015#include <base/strings/string_util.h>
16#include <base/strings/stringprintf.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070017#include <google/protobuf/repeated_field.h>
18#include <gtest/gtest.h>
19
Jay Srinivasand29695d2013-04-08 15:08:05 -070020#include "update_engine/constants.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 Deymo8427b4a2014-11-05 14:00:32 -080024#include "update_engine/mock_prefs.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070025#include "update_engine/payload_constants.h"
26#include "update_engine/payload_generator/delta_diff_generator.h"
Alex Deymo923d8fa2014-07-15 17:58:51 -070027#include "update_engine/payload_generator/payload_signer.h"
28#include "update_engine/payload_verifier.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
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070035using std::string;
36using std::vector;
Darin Petkov73058b42010-10-06 16:32:19 -070037using testing::Return;
Alex Deymo161c4a12014-05-16 15:56:21 -070038using testing::_;
Alex Deymo10875d92014-11-10 21:52:57 -080039using test_utils::kRandomString;
40using test_utils::ScopedLoopMounter;
41using test_utils::System;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070042
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070043extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070044extern const char* kUnittestPublicKeyPath;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070045extern const char* kUnittestPrivateKey2Path;
46extern const char* kUnittestPublicKey2Path;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070047
Jay Srinivasan738fdf32012-12-07 17:40:54 -080048static const size_t kBlockSize = 4096;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -070049static const char* kBogusMetadataSignature1 =
50 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
51 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
52 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
53 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
54 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
55 "pLRtClp97kN2+tXGNBQqkA==";
Jay Srinivasan738fdf32012-12-07 17:40:54 -080056
Alex Vakulenkod2779df2014-06-16 13:19:00 -070057static const int kDefaultKernelSize = 4096; // Something small for a test
Jay Srinivasan738fdf32012-12-07 17:40:54 -080058static const char* kNewDataString = "This is new data.";
59
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070060namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080061struct DeltaState {
62 string a_img;
63 string b_img;
64 int image_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070065
Jay Srinivasan738fdf32012-12-07 17:40:54 -080066 string delta_path;
67 uint64_t metadata_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070068
Jay Srinivasan738fdf32012-12-07 17:40:54 -080069 string old_kernel;
70 vector<char> old_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070071
Jay Srinivasan738fdf32012-12-07 17:40:54 -080072 string new_kernel;
73 vector<char> new_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070074
Jay Srinivasan738fdf32012-12-07 17:40:54 -080075 // The in-memory copy of delta file.
76 vector<char> delta;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080077
78 // The mock system state object with which we initialize the
79 // delta performer.
Gilad Arnold5bb4c902014-04-10 12:32:13 -070080 FakeSystemState fake_system_state;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080081};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070082
Jay Srinivasan738fdf32012-12-07 17:40:54 -080083enum SignatureTest {
84 kSignatureNone, // No payload signing.
85 kSignatureGenerator, // Sign the payload at generation time.
86 kSignatureGenerated, // Sign the payload after it's generated.
Don Garrett2ae37872013-10-25 13:33:20 -070087 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
Alex Vakulenkod2779df2014-06-16 13:19:00 -070088 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
Jay Srinivasan738fdf32012-12-07 17:40:54 -080089 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
90 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
91 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
92 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
93};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070094
Jay Srinivasan738fdf32012-12-07 17:40:54 -080095// Different options that determine what we should fill into the
96// install_plan.metadata_signature to simulate the contents received in the
97// Omaha response.
98enum MetadataSignatureTest {
99 kEmptyMetadataSignature,
100 kInvalidMetadataSignature,
101 kValidMetadataSignature,
102};
103
104enum OperationHashTest {
105 kInvalidOperationData,
106 kValidOperationData,
107};
108
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700109} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800110
111static void CompareFilesByBlock(const string& a_file, const string& b_file) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700112 vector<char> a_data, b_data;
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700113 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
114 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700115
116 EXPECT_EQ(a_data.size(), b_data.size());
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700117 EXPECT_EQ(0, a_data.size() % kBlockSize);
118 for (size_t i = 0; i < a_data.size(); i += kBlockSize) {
119 EXPECT_EQ(0, i % kBlockSize);
120 vector<char> a_sub(&a_data[i], &a_data[i + kBlockSize]);
121 vector<char> b_sub(&b_data[i], &b_data[i + kBlockSize]);
122 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
123 }
124}
125
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800126static bool WriteSparseFile(const string& path, off_t size) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700127 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
128 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
129 ScopedFdCloser fd_closer(&fd);
130 off_t rc = lseek(fd, size + 1, SEEK_SET);
131 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
132 int return_code = ftruncate(fd, size);
133 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
134 return true;
135}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700136
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800137static size_t GetSignatureSize(const string& private_key_path) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800138 const vector<char> data(1, 'x');
139 vector<char> hash;
140 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(data, &hash));
141 vector<char> signature;
142 EXPECT_TRUE(PayloadSigner::SignHash(hash,
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800143 private_key_path,
Darin Petkovcbfb0172011-01-14 15:24:45 -0800144 &signature));
145 return signature.size();
146}
147
Don Garrett2ae37872013-10-25 13:33:20 -0700148static bool InsertSignaturePlaceholder(int signature_size,
149 const string& payload_path,
150 uint64_t* out_metadata_size) {
Ben Chanf9cb98c2014-09-21 18:31:30 -0700151 vector<vector<char>> signatures;
Don Garrett2ae37872013-10-25 13:33:20 -0700152 signatures.push_back(vector<char>(signature_size, 0));
153
154 return PayloadSigner::AddSignatureToPayload(
155 payload_path,
156 signatures,
157 payload_path,
158 out_metadata_size);
159}
160
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800161static void SignGeneratedPayload(const string& payload_path,
162 uint64_t* out_metadata_size) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800163 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800164 vector<char> hash;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700165 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
166 payload_path,
167 vector<int>(1, signature_size),
168 &hash));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800169 vector<char> signature;
170 ASSERT_TRUE(PayloadSigner::SignHash(hash,
171 kUnittestPrivateKeyPath,
172 &signature));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700173 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
174 payload_path,
Ben Chanf9cb98c2014-09-21 18:31:30 -0700175 vector<vector<char>>(1, signature),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800176 payload_path,
177 out_metadata_size));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700178 EXPECT_TRUE(PayloadVerifier::VerifySignedPayload(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700179 payload_path,
180 kUnittestPublicKeyPath,
181 kSignatureMessageOriginalVersion));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800182}
183
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800184static void SignGeneratedShellPayload(SignatureTest signature_test,
185 const string& payload_path) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800186 string private_key_path = kUnittestPrivateKeyPath;
187 if (signature_test == kSignatureGeneratedShellBadKey) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800188 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800189 &private_key_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700190 nullptr));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800191 } else {
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700192 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
193 signature_test == kSignatureGeneratedShellRotateCl1 ||
194 signature_test == kSignatureGeneratedShellRotateCl2);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800195 }
196 ScopedPathUnlinker key_unlinker(private_key_path);
197 key_unlinker.set_should_remove(signature_test ==
198 kSignatureGeneratedShellBadKey);
199 // Generates a new private key that will not match the public key.
200 if (signature_test == kSignatureGeneratedShellBadKey) {
201 LOG(INFO) << "Generating a mismatched private key.";
Alex Deymo719bfff2014-07-11 12:12:32 -0700202 ASSERT_EQ(0, System(base::StringPrintf(
203 "%s genrsa -out %s 2048",
204 utils::GetPathOnBoard("openssl").c_str(), private_key_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800205 }
206 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800207 string hash_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700208 ASSERT_TRUE(utils::MakeTempFile("hash.XXXXXX", &hash_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800209 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700210 string signature_size_string;
211 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
212 signature_test == kSignatureGeneratedShellRotateCl2)
Alex Vakulenko75039d72014-03-25 12:36:28 -0700213 signature_size_string = base::StringPrintf("%d:%d",
214 signature_size, signature_size);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700215 else
Alex Vakulenko75039d72014-03-25 12:36:28 -0700216 signature_size_string = base::StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800217 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700218 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700219 "./delta_generator -in_file=%s -signature_size=%s "
220 "-out_hash_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800221 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700222 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800223 hash_file.c_str())));
224
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700225 // Pad the hash
226 vector<char> hash;
227 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700228 ASSERT_TRUE(PayloadVerifier::PadRSA2048SHA256Hash(&hash));
Alex Deymo10875d92014-11-10 21:52:57 -0800229 ASSERT_TRUE(test_utils::WriteFileVector(hash_file, hash));
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700230
Darin Petkovcbfb0172011-01-14 15:24:45 -0800231 string sig_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700232 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800233 ScopedPathUnlinker sig_unlinker(sig_file);
234 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700235 System(base::StringPrintf(
Alex Deymo719bfff2014-07-11 12:12:32 -0700236 "%s rsautl -raw -sign -inkey %s -in %s -out %s",
237 utils::GetPathOnBoard("openssl").c_str(),
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800238 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800239 hash_file.c_str(),
240 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700241 string sig_file2;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700242 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file2, nullptr));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700243 ScopedPathUnlinker sig2_unlinker(sig_file2);
244 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
245 signature_test == kSignatureGeneratedShellRotateCl2) {
246 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700247 System(base::StringPrintf(
Alex Deymo719bfff2014-07-11 12:12:32 -0700248 "%s rsautl -raw -sign -inkey %s -in %s -out %s",
249 utils::GetPathOnBoard("openssl").c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700250 kUnittestPrivateKey2Path,
251 hash_file.c_str(),
252 sig_file2.c_str())));
253 // Append second sig file to first path
254 sig_file += ":" + sig_file2;
255 }
256
Darin Petkovcbfb0172011-01-14 15:24:45 -0800257 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700258 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700259 "./delta_generator -in_file=%s -signature_file=%s "
260 "-out_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800261 payload_path.c_str(),
262 sig_file.c_str(),
263 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800264 int verify_result =
Alex Vakulenko75039d72014-03-25 12:36:28 -0700265 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700266 "./delta_generator -in_file=%s -public_key=%s -public_key_version=%d",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700267 payload_path.c_str(),
268 signature_test == kSignatureGeneratedShellRotateCl2 ?
269 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
270 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800271 if (signature_test == kSignatureGeneratedShellBadKey) {
272 ASSERT_NE(0, verify_result);
273 } else {
274 ASSERT_EQ(0, verify_result);
275 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800276}
277
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800278static void GenerateDeltaFile(bool full_kernel,
279 bool full_rootfs,
280 bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200281 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800282 SignatureTest signature_test,
283 DeltaState *state) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700284 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
285 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
Alex Deymo10875d92014-11-10 21:52:57 -0800286 test_utils::CreateExtImageAtPath(state->a_img, nullptr);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700287
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800288 state->image_size = static_cast<int>(utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700289
290 // Extend the "partitions" holding the file system a bit.
291 EXPECT_EQ(0, System(base::StringPrintf(
292 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800293 state->a_img.c_str(),
294 state->image_size + 1024 * 1024 - 1)));
295 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700296
Don Garrett0dd39852013-04-03 16:55:42 -0700297 // Create ImageInfo A & B
298 ImageInfo old_image_info;
299 ImageInfo new_image_info;
300
301 if (!full_rootfs) {
302 old_image_info.set_channel("src-channel");
303 old_image_info.set_board("src-board");
304 old_image_info.set_version("src-version");
305 old_image_info.set_key("src-key");
306 old_image_info.set_build_channel("src-build-channel");
307 old_image_info.set_build_version("src-build-version");
308 }
309
310 new_image_info.set_channel("test-channel");
311 new_image_info.set_board("test-board");
312 new_image_info.set_version("test-version");
313 new_image_info.set_key("test-key");
314 new_image_info.set_build_channel("test-build-channel");
315 new_image_info.set_build_version("test-build-version");
316
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700317 // Make some changes to the A image.
318 {
319 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800320 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700321
Darin Petkov8e447e02013-04-16 16:23:50 +0200322 vector<char> hardtocompress;
323 while (hardtocompress.size() < 3 * kBlockSize) {
324 hardtocompress.insert(hardtocompress.end(),
325 kRandomString,
326 kRandomString + sizeof(kRandomString) - 1);
327 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700328 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700329 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700330 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200331 hardtocompress.size()));
332
Darin Petkov8a075a72013-04-25 14:46:09 +0200333 vector<char> zeros(16 * 1024, 0);
334 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700335 base::WriteFile(base::FilePath(base::StringPrintf(
336 "%s/move-to-sparse", a_mnt.c_str())),
337 zeros.data(), zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200338
339 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700340 WriteSparseFile(base::StringPrintf("%s/move-from-sparse",
341 a_mnt.c_str()), 16 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200342
Alex Vakulenko75039d72014-03-25 12:36:28 -0700343 EXPECT_EQ(0,
Alex Deymo10875d92014-11-10 21:52:57 -0800344 System(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
345 " bs=1 seek=4096 count=1",
346 a_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200347
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700348 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
349 // patch fails to zero out the final block.
350 vector<char> ones(1024 * 1024, 0xff);
Alex Vakulenko75039d72014-03-25 12:36:28 -0700351 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/ones",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700352 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700353 ones.data(),
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700354 ones.size()));
355 }
356
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700357 if (noop) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700358 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img),
359 base::FilePath(state->b_img)));
Don Garrett0dd39852013-04-03 16:55:42 -0700360 old_image_info = new_image_info;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700361 } else {
Alex Deymo10875d92014-11-10 21:52:57 -0800362 test_utils::CreateExtImageAtPath(state->b_img, nullptr);
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700363 EXPECT_EQ(0, System(base::StringPrintf(
364 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800365 state->b_img.c_str(),
366 state->image_size + 1024 * 1024 - 1)));
367 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700368
369 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700370 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800371 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700372
Alex Deymo10875d92014-11-10 21:52:57 -0800373 EXPECT_EQ(0, System(base::StringPrintf("cp %s/hello %s/hello2",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700374 b_mnt.c_str(),
375 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800376 EXPECT_EQ(0, System(base::StringPrintf("rm %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700377 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800378 EXPECT_EQ(0, System(base::StringPrintf("mv %s/hello2 %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700379 b_mnt.c_str(),
380 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800381 EXPECT_EQ(0, System(base::StringPrintf("echo foo > %s/foo",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700382 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800383 EXPECT_EQ(0, System(base::StringPrintf("touch %s/emptyfile",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700384 b_mnt.c_str()).c_str()));
385 EXPECT_TRUE(WriteSparseFile(base::StringPrintf("%s/fullsparse",
386 b_mnt.c_str()),
387 1024 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200388
389 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700390 WriteSparseFile(base::StringPrintf("%s/move-to-sparse", b_mnt.c_str()),
Darin Petkov8a075a72013-04-25 14:46:09 +0200391 16 * 1024));
392
393 vector<char> zeros(16 * 1024, 0);
394 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700395 base::WriteFile(base::FilePath(base::StringPrintf(
396 "%s/move-from-sparse", b_mnt.c_str())),
397 zeros.data(), zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200398
Alex Deymo10875d92014-11-10 21:52:57 -0800399 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700400 "of=%s/move-semi-sparse "
401 "bs=1 seek=4096 count=1",
402 b_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200403
Alex Deymo10875d92014-11-10 21:52:57 -0800404 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700405 "of=%s/partsparse bs=1 "
406 "seek=4096 count=1",
407 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800408 EXPECT_EQ(0, System(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700409 "mv %s/tmp %s/srchardlink1",
410 b_mnt.c_str(),
411 b_mnt.c_str(),
412 b_mnt.c_str(),
413 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800414 EXPECT_EQ(0, System(
415 base::StringPrintf("rm %s/boguslink && echo foobar > %s/boguslink",
416 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Darin Petkov8e447e02013-04-16 16:23:50 +0200417
418 vector<char> hardtocompress;
419 while (hardtocompress.size() < 3 * kBlockSize) {
420 hardtocompress.insert(hardtocompress.end(),
421 kRandomString,
422 kRandomString + sizeof(kRandomString));
423 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700424 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700425 b_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700426 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200427 hardtocompress.size()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700428 }
429
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700430 string old_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800431 EXPECT_TRUE(utils::MakeTempFile("old_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800432 &state->old_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700433 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700434
435 string new_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800436 EXPECT_TRUE(utils::MakeTempFile("new_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800437 &state->new_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700438 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700439
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800440 state->old_kernel_data.resize(kDefaultKernelSize);
441 state->new_kernel_data.resize(state->old_kernel_data.size());
Alex Deymo10875d92014-11-10 21:52:57 -0800442 test_utils::FillWithData(&state->old_kernel_data);
443 test_utils::FillWithData(&state->new_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700444
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700445 // change the new kernel data
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700446 strcpy(&state->new_kernel_data[0], kNewDataString); // NOLINT(runtime/printf)
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700447
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700448 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800449 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700450 }
451
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700452 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800453 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700454 state->old_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800455 state->old_kernel_data.size()));
456 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700457 state->new_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800458 state->new_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700459
Gilad Arnolda6742b32014-01-11 00:18:34 -0800460 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800461 &state->delta_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700462 nullptr));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800463 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700464 {
465 string a_mnt, b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800466 ScopedLoopMounter a_mounter(state->a_img, &a_mnt, MS_RDONLY);
467 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, MS_RDONLY);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800468 const string private_key =
469 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700470 EXPECT_TRUE(
Darin Petkov68c10d12010-10-14 09:24:37 -0700471 DeltaDiffGenerator::GenerateDeltaUpdateFile(
Darin Petkov7a22d792010-11-08 14:10:00 -0800472 full_rootfs ? "" : a_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800473 full_rootfs ? "" : state->a_img,
Darin Petkov68c10d12010-10-14 09:24:37 -0700474 b_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800475 state->b_img,
476 full_kernel ? "" : state->old_kernel,
477 state->new_kernel,
478 state->delta_path,
479 private_key,
Darin Petkov8e447e02013-04-16 16:23:50 +0200480 chunk_size,
Chris Sosad5ae1562013-04-23 13:20:18 -0700481 kRootFSPartitionSize,
Allie Woodb8ccad02015-02-09 14:33:40 -0800482 DeltaPerformer::kSupportedMinorPayloadVersion,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700483 full_rootfs ? nullptr : &old_image_info,
Don Garrett0dd39852013-04-03 16:55:42 -0700484 &new_image_info,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800485 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800486 }
487
Don Garrett2ae37872013-10-25 13:33:20 -0700488 if (signature_test == kSignatureGeneratedPlaceholder ||
489 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Don Garrett2ae37872013-10-25 13:33:20 -0700490 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
491 LOG(INFO) << "Inserting placeholder signature.";
492 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
493 &state->metadata_size));
494
495 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
496 signature_size -= 1;
497 LOG(INFO) << "Inserting mismatched placeholder signature.";
498 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
499 &state->metadata_size));
500 return;
501 }
502 }
503
504 if (signature_test == kSignatureGenerated ||
505 signature_test == kSignatureGeneratedPlaceholder ||
506 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800507 // Generate the signed payload and update the metadata size in state to
508 // reflect the new size after adding the signature operation to the
509 // manifest.
Don Garrett2ae37872013-10-25 13:33:20 -0700510 LOG(INFO) << "Signing payload.";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800511 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800512 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700513 signature_test == kSignatureGeneratedShellBadKey ||
514 signature_test == kSignatureGeneratedShellRotateCl1 ||
515 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800516 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700517 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800518}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700519
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800520static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
521 SignatureTest signature_test, DeltaState* state,
522 bool hash_checks_mandatory,
523 OperationHashTest op_hash_test,
524 DeltaPerformer** performer) {
Darin Petkov36a58222010-10-07 22:00:09 -0700525 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700526 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700527 DeltaArchiveManifest manifest;
Alex Deymo923d8fa2014-07-15 17:58:51 -0700528 EXPECT_TRUE(PayloadVerifier::LoadPayload(state->delta_path,
529 &state->delta,
530 &manifest,
531 &state->metadata_size));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800532 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700533
Don Garrett0dd39852013-04-03 16:55:42 -0700534
535
Darin Petkovcbfb0172011-01-14 15:24:45 -0800536 if (signature_test == kSignatureNone) {
537 EXPECT_FALSE(manifest.has_signatures_offset());
538 EXPECT_FALSE(manifest.has_signatures_size());
539 } else {
540 EXPECT_TRUE(manifest.has_signatures_offset());
541 EXPECT_TRUE(manifest.has_signatures_size());
542 Signatures sigs_message;
543 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800544 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800545 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700546 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
547 signature_test == kSignatureGeneratedShellRotateCl2)
548 EXPECT_EQ(2, sigs_message.signatures_size());
549 else
550 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800551 const Signatures_Signature& signature = sigs_message.signatures(0);
552 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700553
Darin Petkovcbfb0172011-01-14 15:24:45 -0800554 uint64_t expected_sig_data_length = 0;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700555 vector<string> key_paths{kUnittestPrivateKeyPath};
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700556 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
557 signature_test == kSignatureGeneratedShellRotateCl2) {
558 key_paths.push_back(kUnittestPrivateKey2Path);
559 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800560 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700561 key_paths,
562 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800563 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
564 EXPECT_FALSE(signature.data().empty());
565 }
Darin Petkov36a58222010-10-07 22:00:09 -0700566
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700567 if (noop) {
Gilad Arnold063181c2015-02-05 12:24:49 -0800568 EXPECT_EQ(0, manifest.install_operations_size());
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700569 EXPECT_EQ(1, manifest.kernel_install_operations_size());
570 }
571
Darin Petkovd43d6902010-10-14 11:17:50 -0700572 if (full_kernel) {
573 EXPECT_FALSE(manifest.has_old_kernel_info());
574 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800575 EXPECT_EQ(state->old_kernel_data.size(),
576 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700577 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
578 }
Darin Petkov698d0412010-10-13 10:59:44 -0700579
Don Garrett0dd39852013-04-03 16:55:42 -0700580 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
581 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
582 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
583 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
584 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
585 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
586
587 if (!full_rootfs) {
Don Garrett0dd39852013-04-03 16:55:42 -0700588 if (noop) {
589 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
590 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
591 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
592 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
593 EXPECT_EQ(manifest.old_image_info().build_channel(),
594 "test-build-channel");
595 EXPECT_EQ(manifest.old_image_info().build_version(),
596 "test-build-version");
597 } else {
598 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
599 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
600 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
601 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
602 EXPECT_EQ(manifest.old_image_info().build_channel(),
603 "src-build-channel");
604 EXPECT_EQ(manifest.old_image_info().build_version(),
605 "src-build-version");
606 }
607 }
608
609
Darin Petkov7a22d792010-11-08 14:10:00 -0800610 if (full_rootfs) {
611 EXPECT_FALSE(manifest.has_old_rootfs_info());
Don Garrett0dd39852013-04-03 16:55:42 -0700612 EXPECT_FALSE(manifest.has_old_image_info());
613 EXPECT_TRUE(manifest.has_new_image_info());
Darin Petkov7a22d792010-11-08 14:10:00 -0800614 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800615 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800616 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
617 }
618
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800619 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
620 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700621
Darin Petkov36a58222010-10-07 22:00:09 -0700622 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700623 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700624 }
625
Alex Deymo8427b4a2014-11-05 14:00:32 -0800626 MockPrefs prefs;
Darin Petkov73058b42010-10-06 16:32:19 -0700627 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800628 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700629 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
630 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700631 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
632 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700633 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
634 .WillRepeatedly(Return(true));
David Zeuthen41996ad2013-09-24 15:43:24 -0700635 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
636 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700637 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700638 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800639 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800640 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
641 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700642 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
643 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800644 }
Darin Petkov73058b42010-10-06 16:32:19 -0700645
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700646 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700647 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800648 install_plan.hash_checks_mandatory = hash_checks_mandatory;
649 install_plan.metadata_size = state->metadata_size;
Don Garrettb8dd1d92013-11-22 17:40:02 -0800650 install_plan.is_full_update = full_kernel && full_rootfs;
651
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800652 LOG(INFO) << "Setting payload metadata size in Omaha = "
653 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700654 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700655 state->delta.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800656 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700657 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700658 &install_plan.metadata_signature));
659 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700660
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800661 *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700662 &state->fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800663 &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700664 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800665 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700666
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800667 EXPECT_EQ(state->image_size,
668 OmahaHashCalculator::RawHashOfFile(state->a_img,
669 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700670 &install_plan.rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800671 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->old_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700672 &install_plan.kernel_hash));
673
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800674 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
675 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
676
David Zeuthena99981f2013-04-29 13:42:47 -0700677 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800678 bool continue_writing;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700679 switch (op_hash_test) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800680 case kInvalidOperationData: {
681 // Muck with some random offset post the metadata size so that
682 // some operation hash will result in a mismatch.
683 int some_offset = state->metadata_size + 300;
684 LOG(INFO) << "Tampered value at offset: " << some_offset;
685 state->delta[some_offset]++;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700686 expected_error = ErrorCode::kDownloadOperationHashMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800687 continue_writing = false;
688 break;
689 }
690
691 case kValidOperationData:
692 default:
693 // no change.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700694 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800695 continue_writing = true;
696 break;
697 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700698
699 // Write at some number of bytes per operation. Arbitrarily chose 5.
700 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800701 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
Alex Deymof329b932014-10-30 01:37:48 -0700702 size_t count = std::min(state->delta.size() - i, kBytesPerWrite);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800703 bool write_succeeded = ((*performer)->Write(&state->delta[i],
704 count,
705 &actual_error));
706 // Normally write_succeeded should be true every time and
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700707 // actual_error should be ErrorCode::kSuccess. If so, continue the loop.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800708 // But if we seeded an operation hash error above, then write_succeeded
709 // will be false. The failure may happen at any operation n. So, all
710 // Writes until n-1 should succeed and the nth operation will fail with
711 // actual_error. In this case, we should bail out of the loop because
712 // we cannot proceed applying the delta.
713 if (!write_succeeded) {
714 LOG(INFO) << "Write failed. Checking if it failed with expected error";
715 EXPECT_EQ(expected_error, actual_error);
716 if (!continue_writing) {
717 LOG(INFO) << "Cannot continue writing. Bailing out.";
718 break;
719 }
720 }
721
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700722 EXPECT_EQ(ErrorCode::kSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700723 }
724
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800725 // If we had continued all the way through, Close should succeed.
726 // Otherwise, it should fail. Check appropriately.
727 bool close_result = (*performer)->Close();
728 if (continue_writing)
729 EXPECT_EQ(0, close_result);
730 else
731 EXPECT_LE(0, close_result);
732}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700733
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800734void VerifyPayloadResult(DeltaPerformer* performer,
735 DeltaState* state,
David Zeuthena99981f2013-04-29 13:42:47 -0700736 ErrorCode expected_result) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800737 if (!performer) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700738 EXPECT_TRUE(!"Skipping payload verification since performer is null.");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800739 return;
740 }
741
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700742 int expected_times = (expected_result == ErrorCode::kSuccess) ? 1 : 0;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700743 EXPECT_CALL(*(state->fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800744 DownloadComplete()).Times(expected_times);
745
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800746 LOG(INFO) << "Verifying payload for expected result "
747 << expected_result;
748 EXPECT_EQ(expected_result, performer->VerifyPayload(
749 OmahaHashCalculator::OmahaHashOfData(state->delta),
750 state->delta.size()));
751 LOG(INFO) << "Verified payload.";
752
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700753 if (expected_result != ErrorCode::kSuccess) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800754 // no need to verify new partition if VerifyPayload failed.
755 return;
756 }
757
758 CompareFilesByBlock(state->old_kernel, state->new_kernel);
759 CompareFilesByBlock(state->a_img, state->b_img);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700760
761 vector<char> updated_kernel_partition;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800762 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
Alex Vakulenko75039d72014-03-25 12:36:28 -0700763 EXPECT_EQ(0, strncmp(updated_kernel_partition.data(), kNewDataString,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800764 strlen(kNewDataString)));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700765
766 uint64_t new_kernel_size;
767 vector<char> new_kernel_hash;
768 uint64_t new_rootfs_size;
769 vector<char> new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800770 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Don Garrett0dd39852013-04-03 16:55:42 -0700771 &new_kernel_hash,
772 &new_rootfs_size,
773 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800774 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700775 vector<char> expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800776 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700777 &expected_new_kernel_hash));
778 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800779 EXPECT_EQ(state->image_size, new_rootfs_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700780 vector<char> expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800781 EXPECT_EQ(state->image_size,
782 OmahaHashCalculator::RawHashOfFile(state->b_img,
783 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700784 &expected_new_rootfs_hash));
785 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
786}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800787
788void VerifyPayload(DeltaPerformer* performer,
789 DeltaState* state,
790 SignatureTest signature_test) {
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700791 ErrorCode expected_result = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800792 switch (signature_test) {
793 case kSignatureNone:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700794 expected_result = ErrorCode::kSignedDeltaPayloadExpectedError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800795 break;
796 case kSignatureGeneratedShellBadKey:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700797 expected_result = ErrorCode::kDownloadPayloadPubKeyVerificationError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800798 break;
799 default: break; // appease gcc
800 }
801
802 VerifyPayloadResult(performer, state, expected_result);
803}
804
805void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200806 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800807 SignatureTest signature_test,
808 bool hash_checks_mandatory) {
809 DeltaState state;
Alex Deymo52146ce2014-05-29 11:09:45 -0700810 DeltaPerformer *performer = nullptr;
Darin Petkov8e447e02013-04-16 16:23:50 +0200811 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
812 signature_test, &state);
Don Garrett0dd39852013-04-03 16:55:42 -0700813
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800814 ScopedPathUnlinker a_img_unlinker(state.a_img);
815 ScopedPathUnlinker b_img_unlinker(state.b_img);
816 ScopedPathUnlinker delta_unlinker(state.delta_path);
817 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
818 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
819 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
820 &state, hash_checks_mandatory, kValidOperationData,
821 &performer);
822 VerifyPayload(performer, &state, signature_test);
Alex Deymo52146ce2014-05-29 11:09:45 -0700823 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800824}
825
826// Calls delta performer's Write method by pretending to pass in bytes from a
827// delta file whose metadata size is actual_metadata_size and tests if all
828// checks are correctly performed if the install plan contains
829// expected_metadata_size and that the result of the parsing are as per
830// hash_checks_mandatory flag.
831void DoMetadataSizeTest(uint64_t expected_metadata_size,
832 uint64_t actual_metadata_size,
833 bool hash_checks_mandatory) {
Alex Deymo8427b4a2014-11-05 14:00:32 -0800834 MockPrefs prefs;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800835 InstallPlan install_plan;
836 install_plan.hash_checks_mandatory = hash_checks_mandatory;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700837 FakeSystemState fake_system_state;
838 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800839 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
840 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
841
842 // Set a valid magic string and version number 1.
843 EXPECT_TRUE(performer.Write("CrAU", 4));
844 uint64_t version = htobe64(1);
845 EXPECT_TRUE(performer.Write(&version, 8));
846
847 install_plan.metadata_size = expected_metadata_size;
David Zeuthena99981f2013-04-29 13:42:47 -0700848 ErrorCode error_code;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800849 // When filling in size in manifest, exclude the size of the 20-byte header.
850 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
851 bool result = performer.Write(&size_in_manifest, 8, &error_code);
852 if (expected_metadata_size == actual_metadata_size ||
853 !hash_checks_mandatory) {
854 EXPECT_TRUE(result);
855 } else {
856 EXPECT_FALSE(result);
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700857 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800858 }
859
860 EXPECT_LT(performer.Close(), 0);
861}
862
863// Generates a valid delta file but tests the delta performer by suppling
864// different metadata signatures as per omaha_metadata_signature flag and
865// sees if the result of the parsing are as per hash_checks_mandatory flag.
866void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
867 SignatureTest signature_test,
868 bool hash_checks_mandatory) {
869 DeltaState state;
870
871 // Using kSignatureNone since it doesn't affect the results of our test.
872 // If we've to use other signature options, then we'd have to get the
873 // metadata size again after adding the signing operation to the manifest.
Darin Petkov8e447e02013-04-16 16:23:50 +0200874 GenerateDeltaFile(true, true, false, -1, signature_test, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800875
876 ScopedPathUnlinker a_img_unlinker(state.a_img);
877 ScopedPathUnlinker b_img_unlinker(state.b_img);
878 ScopedPathUnlinker delta_unlinker(state.delta_path);
879 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
880 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
881
882 // Loads the payload and parses the manifest.
883 vector<char> payload;
884 EXPECT_TRUE(utils::ReadFile(state.delta_path, &payload));
885 LOG(INFO) << "Payload size: " << payload.size();
886
887 InstallPlan install_plan;
888 install_plan.hash_checks_mandatory = hash_checks_mandatory;
889 install_plan.metadata_size = state.metadata_size;
890
891 DeltaPerformer::MetadataParseResult expected_result, actual_result;
David Zeuthena99981f2013-04-29 13:42:47 -0700892 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800893
894 // Fill up the metadata signature in install plan according to the test.
895 switch (metadata_signature_test) {
896 case kEmptyMetadataSignature:
897 install_plan.metadata_signature.clear();
898 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700899 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800900 break;
901
902 case kInvalidMetadataSignature:
903 install_plan.metadata_signature = kBogusMetadataSignature1;
904 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700905 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800906 break;
907
908 case kValidMetadataSignature:
909 default:
910 // Set the install plan's metadata size to be the same as the one
911 // in the manifest so that we pass the metadata size checks. Only
912 // then we can get to manifest signature checks.
913 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700914 payload.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800915 state.metadata_size,
916 kUnittestPrivateKeyPath,
917 &install_plan.metadata_signature));
918 EXPECT_FALSE(install_plan.metadata_signature.empty());
919 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700920 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800921 break;
922 }
923
924 // Ignore the expected result/error if hash checks are not mandatory.
925 if (!hash_checks_mandatory) {
926 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700927 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800928 }
929
930 // Create the delta performer object.
Alex Deymo8427b4a2014-11-05 14:00:32 -0800931 MockPrefs prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800932 DeltaPerformer delta_performer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700933 &state.fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800934 &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800935
936 // Use the public key corresponding to the private key used above to
937 // sign the metadata.
938 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
939 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
940
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800941 // Init actual_error with an invalid value so that we make sure
942 // ParsePayloadMetadata properly populates it in all cases.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700943 actual_error = ErrorCode::kUmaReportedMax;
Gilad Arnolddaa27402014-01-23 11:56:17 -0800944 actual_result = delta_performer.ParsePayloadMetadata(payload, &actual_error);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800945
946 EXPECT_EQ(expected_result, actual_result);
947 EXPECT_EQ(expected_error, actual_error);
948
949 // Check that the parsed metadata size is what's expected. This test
950 // implicitly confirms that the metadata signature is valid, if required.
Gilad Arnoldfe133932014-01-14 12:25:50 -0800951 EXPECT_EQ(state.metadata_size, delta_performer.GetMetadataSize());
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800952}
953
954void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
955 bool hash_checks_mandatory) {
956 DeltaState state;
Darin Petkov8e447e02013-04-16 16:23:50 +0200957 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800958 ScopedPathUnlinker a_img_unlinker(state.a_img);
959 ScopedPathUnlinker b_img_unlinker(state.b_img);
960 ScopedPathUnlinker delta_unlinker(state.delta_path);
961 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
962 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Alex Deymo52146ce2014-05-29 11:09:45 -0700963 DeltaPerformer *performer = nullptr;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800964 ApplyDeltaFile(true, true, false, kSignatureGenerated,
965 &state, hash_checks_mandatory, op_hash_test, &performer);
Alex Deymo52146ce2014-05-29 11:09:45 -0700966 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800967}
968
Don Garrettb8dd1d92013-11-22 17:40:02 -0800969
970class DeltaPerformerTest : public ::testing::Test {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800971 public:
972 // Test helper placed where it can easily be friended from DeltaPerformer.
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700973 static void RunManifestValidation(const DeltaArchiveManifest& manifest,
Don Garrettb8dd1d92013-11-22 17:40:02 -0800974 bool full_payload,
975 ErrorCode expected) {
Alex Deymo8427b4a2014-11-05 14:00:32 -0800976 MockPrefs prefs;
Don Garrettb8dd1d92013-11-22 17:40:02 -0800977 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700978 FakeSystemState fake_system_state;
979 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800980
981 // The install plan is for Full or Delta.
982 install_plan.is_full_update = full_payload;
983
984 // The Manifest we are validating.
985 performer.manifest_.CopyFrom(manifest);
986
987 EXPECT_EQ(expected, performer.ValidateManifest());
988 }
989};
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800990
991TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
992 uint64_t test[] = {1, 1, 4, 2, kSparseHole, 1, 0, 1};
993 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
994 const uint64_t block_size = 4096;
995 const uint64_t file_length = 5 * block_size - 13;
996
997 google::protobuf::RepeatedPtrField<Extent> extents;
998 for (size_t i = 0; i < arraysize(test); i += 2) {
999 Extent* extent = extents.Add();
1000 extent->set_start_block(test[i]);
1001 extent->set_num_blocks(test[i + 1]);
1002 }
1003
1004 string expected_output = "4096:4096,16384:8192,-1:4096,0:4083";
1005 string actual_output;
1006 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
1007 block_size,
1008 file_length,
1009 &actual_output));
1010 EXPECT_EQ(expected_output, actual_output);
1011}
Darin Petkov68c10d12010-10-14 09:24:37 -07001012
Don Garrettb8dd1d92013-11-22 17:40:02 -08001013TEST(DeltaPerformerTest, ValidateManifestFullGoodTest) {
1014 // The Manifest we are validating.
1015 DeltaArchiveManifest manifest;
1016 manifest.mutable_new_kernel_info();
1017 manifest.mutable_new_rootfs_info();
1018 manifest.set_minor_version(DeltaPerformer::kFullPayloadMinorVersion);
1019
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001020 DeltaPerformerTest::RunManifestValidation(manifest, true,
1021 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001022}
1023
1024TEST(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
1025 // The Manifest we are validating.
1026 DeltaArchiveManifest manifest;
1027 manifest.mutable_old_kernel_info();
1028 manifest.mutable_old_rootfs_info();
1029 manifest.mutable_new_kernel_info();
1030 manifest.mutable_new_rootfs_info();
1031 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1032
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001033 DeltaPerformerTest::RunManifestValidation(manifest, false,
1034 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001035}
1036
1037TEST(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
1038 // The Manifest we are validating.
1039 DeltaArchiveManifest manifest;
1040
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001041 DeltaPerformerTest::RunManifestValidation(manifest, true,
1042 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001043}
1044
1045TEST(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
1046 // The Manifest we are validating.
1047 DeltaArchiveManifest manifest;
1048
1049 DeltaPerformerTest::RunManifestValidation(
1050 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001051 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001052}
1053
1054TEST(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
1055 // The Manifest we are validating.
1056 DeltaArchiveManifest manifest;
1057 manifest.mutable_old_kernel_info();
1058 manifest.mutable_new_kernel_info();
1059 manifest.mutable_new_rootfs_info();
1060 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1061
1062 DeltaPerformerTest::RunManifestValidation(
1063 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001064 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001065}
1066
1067TEST(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
1068 // The Manifest we are validating.
1069 DeltaArchiveManifest manifest;
1070 manifest.mutable_old_rootfs_info();
1071 manifest.mutable_new_kernel_info();
1072 manifest.mutable_new_rootfs_info();
1073 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1074
1075 DeltaPerformerTest::RunManifestValidation(
1076 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001077 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001078}
1079
1080TEST(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
1081 // The Manifest we are validating.
1082 DeltaArchiveManifest manifest;
1083
1084 // Generate a bad version number.
1085 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
1086 10000);
1087
1088 DeltaPerformerTest::RunManifestValidation(
1089 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001090 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001091}
1092
Darin Petkov68c10d12010-10-14 09:24:37 -07001093TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001094 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001095 false);
Darin Petkov8e447e02013-04-16 16:23:50 +02001096}
1097
Don Garrett2ae37872013-10-25 13:33:20 -07001098TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
1099 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
1100 false);
1101}
1102
1103TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
1104 DeltaState state;
1105 GenerateDeltaFile(false, false, false, -1,
1106 kSignatureGeneratedPlaceholderMismatch, &state);
1107}
1108
Darin Petkov8e447e02013-04-16 16:23:50 +02001109TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001110 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001111 false);
Darin Petkov68c10d12010-10-14 09:24:37 -07001112}
1113
1114TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001115 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001116 false);
Darin Petkov7a22d792010-11-08 14:10:00 -08001117}
1118
1119TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001120 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001121 true);
Darin Petkov9fa7ec52010-10-18 11:45:23 -07001122}
1123
1124TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001125 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001126 false);
Darin Petkov9574f7e2011-01-13 10:48:12 -08001127}
1128
Darin Petkovcbfb0172011-01-14 15:24:45 -08001129TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001130 DoSmallImageTest(false, false, false, -1, kSignatureNone,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001131 false);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001132}
1133
1134TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001135 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001136 true);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001137}
1138
1139TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001140 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001141 false);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -07001142}
1143
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001144TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001145 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001146 false);
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001147}
1148
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001149TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001150 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001151 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001152}
1153
1154TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001155 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
Gilad Arnold434eb0c2013-07-22 06:47:52 -07001156 false);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001157}
1158
Darin Petkov934bb412010-11-18 11:21:35 -08001159TEST(DeltaPerformerTest, BadDeltaMagicTest) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001160 MockPrefs prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001161 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001162 FakeSystemState fake_system_state;
1163 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -08001164 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1165 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -08001166 EXPECT_TRUE(performer.Write("junk", 4));
1167 EXPECT_TRUE(performer.Write("morejunk", 8));
1168 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -08001169 EXPECT_LT(performer.Close(), 0);
1170}
1171
Andrew de los Reyes353777c2010-10-08 10:34:30 -07001172TEST(DeltaPerformerTest, IsIdempotentOperationTest) {
1173 DeltaArchiveManifest_InstallOperation op;
1174 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1175 *(op.add_dst_extents()) = ExtentForRange(0, 5);
1176 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1177 *(op.add_src_extents()) = ExtentForRange(4, 1);
1178 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1179 op.clear_src_extents();
1180 *(op.add_src_extents()) = ExtentForRange(5, 3);
1181 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1182 *(op.add_dst_extents()) = ExtentForRange(20, 6);
1183 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1184 *(op.add_src_extents()) = ExtentForRange(19, 2);
1185 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1186}
1187
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001188TEST(DeltaPerformerTest, WriteUpdatesPayloadState) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001189 MockPrefs prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001190 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001191 FakeSystemState fake_system_state;
1192 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001193 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1194 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
1195
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001196 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001197 DownloadProgress(4)).Times(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001198 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001199 DownloadProgress(8)).Times(2);
1200
1201 EXPECT_TRUE(performer.Write("junk", 4));
1202 EXPECT_TRUE(performer.Write("morejunk", 8));
1203 EXPECT_FALSE(performer.Write("morejunk", 8));
1204 EXPECT_LT(performer.Close(), 0);
1205}
1206
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001207TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
1208 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001209}
1210
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001211TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
1212 DoMetadataSizeTest(0, 123456, false);
1213}
1214
1215TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
1216 DoMetadataSizeTest(13000, 140000, true);
1217}
1218
1219TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
1220 DoMetadataSizeTest(40000, 50000, false);
1221}
1222
1223TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
1224 DoMetadataSizeTest(85376, 85376, true);
1225}
1226
1227TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
1228 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, true);
1229}
1230
1231TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
1232 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, false);
1233}
1234
1235TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
1236 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated, true);
1237}
1238
1239TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
1240 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated,
1241 false);
1242}
1243
1244TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
1245 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureNone, true);
1246}
1247
1248TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
1249 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, true);
1250}
1251
1252TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
1253 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, false);
1254}
1255
1256TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
1257 DoOperationHashMismatchTest(kInvalidOperationData, true);
1258}
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001259
David Zeuthene7f89172013-10-31 10:21:04 -07001260TEST(DeltaPerformerTest, UsePublicKeyFromResponse) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001261 MockPrefs prefs;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001262 FakeSystemState fake_system_state;
David Zeuthene7f89172013-10-31 10:21:04 -07001263 InstallPlan install_plan;
1264 base::FilePath key_path;
1265
1266 // The result of the GetPublicKeyResponse() method is based on three things
1267 //
1268 // 1. Whether it's an official build; and
1269 // 2. Whether the Public RSA key to be used is in the root filesystem; and
Alex Vakulenko072359c2014-07-18 11:41:07 -07001270 // 3. Whether the response has a public key
David Zeuthene7f89172013-10-31 10:21:04 -07001271 //
1272 // We test all eight combinations to ensure that we only use the
1273 // public key in the response if
1274 //
1275 // a. it's not an official build; and
1276 // b. there is no key in the root filesystem.
1277
1278 DeltaPerformer *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001279 &fake_system_state,
David Zeuthene7f89172013-10-31 10:21:04 -07001280 &install_plan);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001281 FakeHardware* fake_hardware = fake_system_state.fake_hardware();
David Zeuthene7f89172013-10-31 10:21:04 -07001282
1283 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -08001284 EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
David Zeuthene7f89172013-10-31 10:21:04 -07001285 &temp_dir));
1286 string non_existing_file = temp_dir + "/non-existing";
1287 string existing_file = temp_dir + "/existing";
Alex Vakulenko75039d72014-03-25 12:36:28 -07001288 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
David Zeuthene7f89172013-10-31 10:21:04 -07001289
1290 // Non-official build, non-existing public-key, key in response -> true
Don Garrett6646b442013-11-13 15:29:11 -08001291 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001292 performer->public_key_path_ = non_existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001293 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001294 EXPECT_TRUE(performer->GetPublicKeyFromResponse(&key_path));
1295 EXPECT_FALSE(key_path.empty());
1296 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
1297 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001298 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001299 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1300
1301 // Non-official build, existing public-key, key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001302 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001303 performer->public_key_path_ = existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001304 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001305 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1306 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001307 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001308 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1309
1310 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001311 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001312 performer->public_key_path_ = non_existing_file;
1313 install_plan.public_key_rsa = "";
1314 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1315 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001316 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001317 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1318
1319 // Non-official build, existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001320 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001321 performer->public_key_path_ = existing_file;
1322 install_plan.public_key_rsa = "";
1323 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1324 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001325 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001326 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1327
1328 // Non-official build, non-existing public-key, key in response
1329 // but invalid base64 -> false
Don Garrett6646b442013-11-13 15:29:11 -08001330 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001331 performer->public_key_path_ = non_existing_file;
1332 install_plan.public_key_rsa = "not-valid-base64";
1333 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1334
1335 delete performer;
Alex Deymo10875d92014-11-10 21:52:57 -08001336 EXPECT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
David Zeuthene7f89172013-10-31 10:21:04 -07001337}
1338
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001339} // namespace chromeos_update_engine