blob: f5493c2f077f8dcd5613ba86143ef882cee12d4c [file] [log] [blame]
Mike Frysinger8155d082012-04-06 15:23:18 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <sys/mount.h>
6#include <inttypes.h>
7
8#include <algorithm>
9#include <string>
10#include <vector>
11
Darin Petkov9fa7ec52010-10-18 11:45:23 -070012#include <base/file_util.h>
Chris Masoned903c3b2011-05-12 15:35:46 -070013#include <base/memory/scoped_ptr.h>
Darin Petkov73058b42010-10-06 16:32:19 -070014#include <base/string_util.h>
Mike Frysinger8155d082012-04-06 15:23:18 -040015#include <base/stringprintf.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070016#include <google/protobuf/repeated_field.h>
17#include <gtest/gtest.h>
18
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070019#include "update_engine/delta_diff_generator.h"
20#include "update_engine/delta_performer.h"
Andrew de los Reyes353777c2010-10-08 10:34:30 -070021#include "update_engine/extent_ranges.h"
Darin Petkov7a22d792010-11-08 14:10:00 -080022#include "update_engine/full_update_generator.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070023#include "update_engine/graph_types.h"
Jay Srinivasanf0572052012-10-23 18:12:56 -070024#include "update_engine/mock_system_state.h"
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070025#include "update_engine/payload_signer.h"
Darin Petkov73058b42010-10-06 16:32:19 -070026#include "update_engine/prefs_mock.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070027#include "update_engine/test_utils.h"
28#include "update_engine/update_metadata.pb.h"
29#include "update_engine/utils.h"
30
31namespace chromeos_update_engine {
32
33using std::min;
34using std::string;
35using std::vector;
Darin Petkov73058b42010-10-06 16:32:19 -070036using testing::_;
37using testing::Return;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070038
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070039extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070040extern const char* kUnittestPublicKeyPath;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070041extern const char* kUnittestPrivateKey2Path;
42extern const char* kUnittestPublicKey2Path;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070043
Jay Srinivasan738fdf32012-12-07 17:40:54 -080044static const size_t kBlockSize = 4096;
45static const char* kBogusMetadataSignature1 = "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBvJ5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQrYH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMSBmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIRfjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoVpLRtClp97kN2+tXGNBQqkA==";
46
47static const int kDefaultKernelSize = 4096; // Something small for a test
48static const char* kNewDataString = "This is new data.";
49
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070050namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080051struct DeltaState {
52 string a_img;
53 string b_img;
54 int image_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070055
Jay Srinivasan738fdf32012-12-07 17:40:54 -080056 string delta_path;
57 uint64_t metadata_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070058
Jay Srinivasan738fdf32012-12-07 17:40:54 -080059 string old_kernel;
60 vector<char> old_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070061
Jay Srinivasan738fdf32012-12-07 17:40:54 -080062 string new_kernel;
63 vector<char> new_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070064
Jay Srinivasan738fdf32012-12-07 17:40:54 -080065 // The in-memory copy of delta file.
66 vector<char> delta;
67};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070068
Jay Srinivasan738fdf32012-12-07 17:40:54 -080069enum SignatureTest {
70 kSignatureNone, // No payload signing.
71 kSignatureGenerator, // Sign the payload at generation time.
72 kSignatureGenerated, // Sign the payload after it's generated.
73 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
74 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
75 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
76 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
77};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070078
Jay Srinivasan738fdf32012-12-07 17:40:54 -080079// Different options that determine what we should fill into the
80// install_plan.metadata_signature to simulate the contents received in the
81// Omaha response.
82enum MetadataSignatureTest {
83 kEmptyMetadataSignature,
84 kInvalidMetadataSignature,
85 kValidMetadataSignature,
86};
87
88enum OperationHashTest {
89 kInvalidOperationData,
90 kValidOperationData,
91};
92
93} // namespace {}
94
95static void CompareFilesByBlock(const string& a_file, const string& b_file) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070096 vector<char> a_data, b_data;
Andrew de los Reyes3270f742010-07-15 22:28:14 -070097 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
98 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070099
100 EXPECT_EQ(a_data.size(), b_data.size());
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700101 EXPECT_EQ(0, a_data.size() % kBlockSize);
102 for (size_t i = 0; i < a_data.size(); i += kBlockSize) {
103 EXPECT_EQ(0, i % kBlockSize);
104 vector<char> a_sub(&a_data[i], &a_data[i + kBlockSize]);
105 vector<char> b_sub(&b_data[i], &b_data[i + kBlockSize]);
106 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
107 }
108}
109
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800110static bool WriteSparseFile(const string& path, off_t size) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700111 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
112 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
113 ScopedFdCloser fd_closer(&fd);
114 off_t rc = lseek(fd, size + 1, SEEK_SET);
115 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
116 int return_code = ftruncate(fd, size);
117 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
118 return true;
119}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700120
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800121static size_t GetSignatureSize(const string& private_key_path) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800122 const vector<char> data(1, 'x');
123 vector<char> hash;
124 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(data, &hash));
125 vector<char> signature;
126 EXPECT_TRUE(PayloadSigner::SignHash(hash,
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800127 private_key_path,
Darin Petkovcbfb0172011-01-14 15:24:45 -0800128 &signature));
129 return signature.size();
130}
131
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800132static void SignGeneratedPayload(const string& payload_path,
133 uint64_t* out_metadata_size) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800134 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800135 vector<char> hash;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700136 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
137 payload_path,
138 vector<int>(1, signature_size),
139 &hash));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800140 vector<char> signature;
141 ASSERT_TRUE(PayloadSigner::SignHash(hash,
142 kUnittestPrivateKeyPath,
143 &signature));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700144 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
145 payload_path,
146 vector<vector<char> >(1, signature),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800147 payload_path,
148 out_metadata_size));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700149 EXPECT_TRUE(PayloadSigner::VerifySignedPayload(
150 payload_path,
151 kUnittestPublicKeyPath,
152 kSignatureMessageOriginalVersion));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800153}
154
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800155static void SignGeneratedShellPayload(SignatureTest signature_test,
156 const string& payload_path) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800157 string private_key_path = kUnittestPrivateKeyPath;
158 if (signature_test == kSignatureGeneratedShellBadKey) {
159 ASSERT_TRUE(utils::MakeTempFile("/tmp/key.XXXXXX",
160 &private_key_path,
161 NULL));
162 } else {
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700163 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
164 signature_test == kSignatureGeneratedShellRotateCl1 ||
165 signature_test == kSignatureGeneratedShellRotateCl2);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800166 }
167 ScopedPathUnlinker key_unlinker(private_key_path);
168 key_unlinker.set_should_remove(signature_test ==
169 kSignatureGeneratedShellBadKey);
170 // Generates a new private key that will not match the public key.
171 if (signature_test == kSignatureGeneratedShellBadKey) {
172 LOG(INFO) << "Generating a mismatched private key.";
173 ASSERT_EQ(0,
174 System(StringPrintf(
Mike Frysinger2149be42012-03-12 19:23:47 -0400175 "openssl genrsa -out %s 2048",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800176 private_key_path.c_str())));
177 }
178 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800179 string hash_file;
180 ASSERT_TRUE(utils::MakeTempFile("/tmp/hash.XXXXXX", &hash_file, NULL));
181 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700182 string signature_size_string;
183 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
184 signature_test == kSignatureGeneratedShellRotateCl2)
185 signature_size_string = StringPrintf("%d:%d",
186 signature_size, signature_size);
187 else
188 signature_size_string = StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800189 ASSERT_EQ(0,
190 System(StringPrintf(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700191 "./delta_generator -in_file %s -signature_size %s "
Darin Petkovcbfb0172011-01-14 15:24:45 -0800192 "-out_hash_file %s",
193 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700194 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800195 hash_file.c_str())));
196
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700197 // Pad the hash
198 vector<char> hash;
199 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
200 ASSERT_TRUE(PayloadSigner::PadRSA2048SHA256Hash(&hash));
201 ASSERT_TRUE(WriteFileVector(hash_file, hash));
202
Darin Petkovcbfb0172011-01-14 15:24:45 -0800203 string sig_file;
204 ASSERT_TRUE(utils::MakeTempFile("/tmp/signature.XXXXXX", &sig_file, NULL));
205 ScopedPathUnlinker sig_unlinker(sig_file);
206 ASSERT_EQ(0,
207 System(StringPrintf(
Mike Frysinger2149be42012-03-12 19:23:47 -0400208 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800209 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800210 hash_file.c_str(),
211 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700212 string sig_file2;
213 ASSERT_TRUE(utils::MakeTempFile("/tmp/signature.XXXXXX", &sig_file2, NULL));
214 ScopedPathUnlinker sig2_unlinker(sig_file2);
215 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
216 signature_test == kSignatureGeneratedShellRotateCl2) {
217 ASSERT_EQ(0,
218 System(StringPrintf(
Mike Frysinger2149be42012-03-12 19:23:47 -0400219 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700220 kUnittestPrivateKey2Path,
221 hash_file.c_str(),
222 sig_file2.c_str())));
223 // Append second sig file to first path
224 sig_file += ":" + sig_file2;
225 }
226
Darin Petkovcbfb0172011-01-14 15:24:45 -0800227 ASSERT_EQ(0,
228 System(StringPrintf(
229 "./delta_generator -in_file %s -signature_file %s "
230 "-out_file %s",
231 payload_path.c_str(),
232 sig_file.c_str(),
233 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800234 int verify_result =
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700235 System(StringPrintf(
236 "./delta_generator -in_file %s -public_key %s -public_key_version %d",
237 payload_path.c_str(),
238 signature_test == kSignatureGeneratedShellRotateCl2 ?
239 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
240 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800241 if (signature_test == kSignatureGeneratedShellBadKey) {
242 ASSERT_NE(0, verify_result);
243 } else {
244 ASSERT_EQ(0, verify_result);
245 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800246}
247
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800248static void GenerateDeltaFile(bool full_kernel,
249 bool full_rootfs,
250 bool noop,
251 SignatureTest signature_test,
252 DeltaState *state) {
253 EXPECT_TRUE(utils::MakeTempFile("/tmp/a_img.XXXXXX", &state->a_img, NULL));
254 EXPECT_TRUE(utils::MakeTempFile("/tmp/b_img.XXXXXX", &state->b_img, NULL));
255 CreateExtImageAtPath(state->a_img, NULL);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700256
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800257 state->image_size = static_cast<int>(utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700258
259 // Extend the "partitions" holding the file system a bit.
260 EXPECT_EQ(0, System(base::StringPrintf(
261 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800262 state->a_img.c_str(),
263 state->image_size + 1024 * 1024 - 1)));
264 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700265
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700266 // Make some changes to the A image.
267 {
268 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800269 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700270
271 EXPECT_TRUE(utils::WriteFile(StringPrintf("%s/hardtocompress",
272 a_mnt.c_str()).c_str(),
273 reinterpret_cast<const char*>(kRandomString),
274 sizeof(kRandomString) - 1));
275 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
276 // patch fails to zero out the final block.
277 vector<char> ones(1024 * 1024, 0xff);
278 EXPECT_TRUE(utils::WriteFile(StringPrintf("%s/ones",
279 a_mnt.c_str()).c_str(),
280 &ones[0],
281 ones.size()));
282 }
283
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700284 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800285 EXPECT_TRUE(file_util::CopyFile(FilePath(state->a_img),
286 FilePath(state->b_img)));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700287 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800288 CreateExtImageAtPath(state->b_img, NULL);
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700289 EXPECT_EQ(0, System(base::StringPrintf(
290 "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800291 state->b_img.c_str(),
292 state->image_size + 1024 * 1024 - 1)));
293 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700294
295 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700296 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800297 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700298
299 EXPECT_EQ(0, system(StringPrintf("cp %s/hello %s/hello2", b_mnt.c_str(),
300 b_mnt.c_str()).c_str()));
301 EXPECT_EQ(0, system(StringPrintf("rm %s/hello", b_mnt.c_str()).c_str()));
302 EXPECT_EQ(0, system(StringPrintf("mv %s/hello2 %s/hello", b_mnt.c_str(),
303 b_mnt.c_str()).c_str()));
304 EXPECT_EQ(0, system(StringPrintf("echo foo > %s/foo",
305 b_mnt.c_str()).c_str()));
306 EXPECT_EQ(0, system(StringPrintf("touch %s/emptyfile",
307 b_mnt.c_str()).c_str()));
308 EXPECT_TRUE(WriteSparseFile(StringPrintf("%s/fullsparse", b_mnt.c_str()),
309 1024 * 1024));
310 EXPECT_EQ(0, system(StringPrintf("dd if=/dev/zero of=%s/partsparese bs=1 "
311 "seek=4096 count=1",
312 b_mnt.c_str()).c_str()));
Andrew de los Reyes29da8aa2011-02-15 13:34:57 -0800313 EXPECT_EQ(0, system(StringPrintf("cp %s/srchardlink0 %s/tmp && "
314 "mv %s/tmp %s/srchardlink1",
315 b_mnt.c_str(), b_mnt.c_str(),
316 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Andrew de los Reyes48a0a482011-02-22 15:32:11 -0800317 EXPECT_EQ(0, system(StringPrintf("rm %s/boguslink && "
318 "echo foobar > %s/boguslink",
319 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700320 EXPECT_TRUE(utils::WriteFile(StringPrintf("%s/hardtocompress",
321 b_mnt.c_str()).c_str(),
322 reinterpret_cast<const char*>(kRandomString),
323 sizeof(kRandomString)));
324 }
325
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700326 string old_kernel;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800327 EXPECT_TRUE(utils::MakeTempFile("/tmp/old_kernel.XXXXXX",
328 &state->old_kernel,
329 NULL));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700330
331 string new_kernel;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800332 EXPECT_TRUE(utils::MakeTempFile("/tmp/new_kernel.XXXXXX",
333 &state->new_kernel,
334 NULL));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700335
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800336 state->old_kernel_data.resize(kDefaultKernelSize);
337 state->new_kernel_data.resize(state->old_kernel_data.size());
338 FillWithData(&state->old_kernel_data);
339 FillWithData(&state->new_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700340
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700341 // change the new kernel data
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800342 strcpy(&state->new_kernel_data[0], kNewDataString);
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700343
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700344 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800345 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700346 }
347
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700348 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800349 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
350 &state->old_kernel_data[0],
351 state->old_kernel_data.size()));
352 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
353 &state->new_kernel_data[0],
354 state->new_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700355
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800356 EXPECT_TRUE(utils::MakeTempFile("/tmp/delta.XXXXXX",
357 &state->delta_path,
358 NULL));
359 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700360 {
361 string a_mnt, b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800362 ScopedLoopMounter a_mounter(state->a_img, &a_mnt, MS_RDONLY);
363 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, MS_RDONLY);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800364 const string private_key =
365 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700366 EXPECT_TRUE(
Darin Petkov68c10d12010-10-14 09:24:37 -0700367 DeltaDiffGenerator::GenerateDeltaUpdateFile(
Darin Petkov7a22d792010-11-08 14:10:00 -0800368 full_rootfs ? "" : a_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800369 full_rootfs ? "" : state->a_img,
Darin Petkov68c10d12010-10-14 09:24:37 -0700370 b_mnt,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800371 state->b_img,
372 full_kernel ? "" : state->old_kernel,
373 state->new_kernel,
374 state->delta_path,
375 private_key,
376 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800377 }
378
Darin Petkovcbfb0172011-01-14 15:24:45 -0800379 if (signature_test == kSignatureGenerated) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800380 // Generate the signed payload and update the metadata size in state to
381 // reflect the new size after adding the signature operation to the
382 // manifest.
383 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800384 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700385 signature_test == kSignatureGeneratedShellBadKey ||
386 signature_test == kSignatureGeneratedShellRotateCl1 ||
387 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800388 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700389 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800390}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700391
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800392static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
393 SignatureTest signature_test, DeltaState* state,
394 bool hash_checks_mandatory,
395 OperationHashTest op_hash_test,
396 DeltaPerformer** performer) {
Darin Petkov36a58222010-10-07 22:00:09 -0700397 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700398 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700399 DeltaArchiveManifest manifest;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800400 EXPECT_TRUE(PayloadSigner::LoadPayload(state->delta_path,
401 &state->delta,
402 &manifest,
403 &state->metadata_size));
404 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700405
Darin Petkovcbfb0172011-01-14 15:24:45 -0800406 if (signature_test == kSignatureNone) {
407 EXPECT_FALSE(manifest.has_signatures_offset());
408 EXPECT_FALSE(manifest.has_signatures_size());
409 } else {
410 EXPECT_TRUE(manifest.has_signatures_offset());
411 EXPECT_TRUE(manifest.has_signatures_size());
412 Signatures sigs_message;
413 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800414 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800415 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700416 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
417 signature_test == kSignatureGeneratedShellRotateCl2)
418 EXPECT_EQ(2, sigs_message.signatures_size());
419 else
420 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800421 const Signatures_Signature& signature = sigs_message.signatures(0);
422 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700423
Darin Petkovcbfb0172011-01-14 15:24:45 -0800424 uint64_t expected_sig_data_length = 0;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700425 vector<string> key_paths (1, kUnittestPrivateKeyPath);
426 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
427 signature_test == kSignatureGeneratedShellRotateCl2) {
428 key_paths.push_back(kUnittestPrivateKey2Path);
429 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800430 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700431 key_paths,
432 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800433 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
434 EXPECT_FALSE(signature.data().empty());
435 }
Darin Petkov36a58222010-10-07 22:00:09 -0700436
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700437 if (noop) {
438 EXPECT_EQ(1, manifest.install_operations_size());
439 EXPECT_EQ(1, manifest.kernel_install_operations_size());
440 }
441
Darin Petkovd43d6902010-10-14 11:17:50 -0700442 if (full_kernel) {
443 EXPECT_FALSE(manifest.has_old_kernel_info());
444 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800445 EXPECT_EQ(state->old_kernel_data.size(),
446 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700447 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
448 }
Darin Petkov698d0412010-10-13 10:59:44 -0700449
Darin Petkov7a22d792010-11-08 14:10:00 -0800450 if (full_rootfs) {
451 EXPECT_FALSE(manifest.has_old_rootfs_info());
452 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800453 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800454 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
455 }
456
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800457 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
458 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700459
Darin Petkov36a58222010-10-07 22:00:09 -0700460 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700461 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700462 }
463
Darin Petkov73058b42010-10-06 16:32:19 -0700464 PrefsMock prefs;
465 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800466 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700467 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
468 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700469 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
470 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700471 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
472 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700473 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700474 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800475 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800476 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
477 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700478 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
479 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800480 }
Darin Petkov73058b42010-10-06 16:32:19 -0700481
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700482 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700483 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800484 install_plan.hash_checks_mandatory = hash_checks_mandatory;
485 install_plan.metadata_size = state->metadata_size;
486 LOG(INFO) << "Setting payload metadata size in Omaha = "
487 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700488 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800489 &state->delta[0],
490 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700491 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700492 &install_plan.metadata_signature));
493 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700494
Jay Srinivasanf0572052012-10-23 18:12:56 -0700495 MockSystemState mock_system_state;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800496 *performer = new DeltaPerformer(&prefs, &mock_system_state, &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700497 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800498 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700499
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800500 EXPECT_EQ(state->image_size,
501 OmahaHashCalculator::RawHashOfFile(state->a_img,
502 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700503 &install_plan.rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800504 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->old_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700505 &install_plan.kernel_hash));
506
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800507 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
508 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
509
510 ActionExitCode expected_error, actual_error;
511 bool continue_writing;
512 switch(op_hash_test) {
513 case kInvalidOperationData: {
514 // Muck with some random offset post the metadata size so that
515 // some operation hash will result in a mismatch.
516 int some_offset = state->metadata_size + 300;
517 LOG(INFO) << "Tampered value at offset: " << some_offset;
518 state->delta[some_offset]++;
519 expected_error = kActionCodeDownloadOperationHashMismatch;
520 continue_writing = false;
521 break;
522 }
523
524 case kValidOperationData:
525 default:
526 // no change.
527 expected_error = kActionCodeSuccess;
528 continue_writing = true;
529 break;
530 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700531
532 // Write at some number of bytes per operation. Arbitrarily chose 5.
533 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800534 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
535 size_t count = min(state->delta.size() - i, kBytesPerWrite);
536 bool write_succeeded = ((*performer)->Write(&state->delta[i],
537 count,
538 &actual_error));
539 // Normally write_succeeded should be true every time and
540 // actual_error should be kActionCodeSuccess. If so, continue the loop.
541 // But if we seeded an operation hash error above, then write_succeeded
542 // will be false. The failure may happen at any operation n. So, all
543 // Writes until n-1 should succeed and the nth operation will fail with
544 // actual_error. In this case, we should bail out of the loop because
545 // we cannot proceed applying the delta.
546 if (!write_succeeded) {
547 LOG(INFO) << "Write failed. Checking if it failed with expected error";
548 EXPECT_EQ(expected_error, actual_error);
549 if (!continue_writing) {
550 LOG(INFO) << "Cannot continue writing. Bailing out.";
551 break;
552 }
553 }
554
555 EXPECT_EQ(kActionCodeSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700556 }
557
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800558 // If we had continued all the way through, Close should succeed.
559 // Otherwise, it should fail. Check appropriately.
560 bool close_result = (*performer)->Close();
561 if (continue_writing)
562 EXPECT_EQ(0, close_result);
563 else
564 EXPECT_LE(0, close_result);
565}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700566
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800567void VerifyPayloadResult(DeltaPerformer* performer,
568 DeltaState* state,
569 ActionExitCode expected_result) {
570 if (!performer) {
571 EXPECT_TRUE(!"Skipping payload verification since performer is NULL.");
572 return;
573 }
574
575 LOG(INFO) << "Verifying payload for expected result "
576 << expected_result;
577 EXPECT_EQ(expected_result, performer->VerifyPayload(
578 OmahaHashCalculator::OmahaHashOfData(state->delta),
579 state->delta.size()));
580 LOG(INFO) << "Verified payload.";
581
582 if (expected_result != kActionCodeSuccess) {
583 // no need to verify new partition if VerifyPayload failed.
584 return;
585 }
586
587 CompareFilesByBlock(state->old_kernel, state->new_kernel);
588 CompareFilesByBlock(state->a_img, state->b_img);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700589
590 vector<char> updated_kernel_partition;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800591 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
592 EXPECT_EQ(0, strncmp(&updated_kernel_partition[0], kNewDataString,
593 strlen(kNewDataString)));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700594
595 uint64_t new_kernel_size;
596 vector<char> new_kernel_hash;
597 uint64_t new_rootfs_size;
598 vector<char> new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800599 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700600 &new_kernel_hash,
601 &new_rootfs_size,
602 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800603 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700604 vector<char> expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800605 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700606 &expected_new_kernel_hash));
607 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800608 EXPECT_EQ(state->image_size, new_rootfs_size);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700609 vector<char> expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800610 EXPECT_EQ(state->image_size,
611 OmahaHashCalculator::RawHashOfFile(state->b_img,
612 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700613 &expected_new_rootfs_hash));
614 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
615}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800616
617void VerifyPayload(DeltaPerformer* performer,
618 DeltaState* state,
619 SignatureTest signature_test) {
620 ActionExitCode expected_result = kActionCodeSuccess;
621 switch (signature_test) {
622 case kSignatureNone:
623 expected_result = kActionCodeSignedDeltaPayloadExpectedError;
624 break;
625 case kSignatureGeneratedShellBadKey:
626 expected_result = kActionCodeDownloadPayloadPubKeyVerificationError;
627 break;
628 default: break; // appease gcc
629 }
630
631 VerifyPayloadResult(performer, state, expected_result);
632}
633
634void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
635 SignatureTest signature_test,
636 bool hash_checks_mandatory) {
637 DeltaState state;
638 DeltaPerformer *performer;
639 GenerateDeltaFile(full_kernel, full_rootfs, noop, signature_test, &state);
640 ScopedPathUnlinker a_img_unlinker(state.a_img);
641 ScopedPathUnlinker b_img_unlinker(state.b_img);
642 ScopedPathUnlinker delta_unlinker(state.delta_path);
643 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
644 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
645 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
646 &state, hash_checks_mandatory, kValidOperationData,
647 &performer);
648 VerifyPayload(performer, &state, signature_test);
649}
650
651// Calls delta performer's Write method by pretending to pass in bytes from a
652// delta file whose metadata size is actual_metadata_size and tests if all
653// checks are correctly performed if the install plan contains
654// expected_metadata_size and that the result of the parsing are as per
655// hash_checks_mandatory flag.
656void DoMetadataSizeTest(uint64_t expected_metadata_size,
657 uint64_t actual_metadata_size,
658 bool hash_checks_mandatory) {
659 PrefsMock prefs;
660 InstallPlan install_plan;
661 install_plan.hash_checks_mandatory = hash_checks_mandatory;
662 MockSystemState mock_system_state;
663 DeltaPerformer performer(&prefs, &mock_system_state, &install_plan);
664 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
665 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
666
667 // Set a valid magic string and version number 1.
668 EXPECT_TRUE(performer.Write("CrAU", 4));
669 uint64_t version = htobe64(1);
670 EXPECT_TRUE(performer.Write(&version, 8));
671
672 install_plan.metadata_size = expected_metadata_size;
673 ActionExitCode error_code;
674 // When filling in size in manifest, exclude the size of the 20-byte header.
675 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
676 bool result = performer.Write(&size_in_manifest, 8, &error_code);
677 if (expected_metadata_size == actual_metadata_size ||
678 !hash_checks_mandatory) {
679 EXPECT_TRUE(result);
680 } else {
681 EXPECT_FALSE(result);
682 EXPECT_EQ(kActionCodeDownloadInvalidMetadataSize, error_code);
683 }
684
685 EXPECT_LT(performer.Close(), 0);
686}
687
688// Generates a valid delta file but tests the delta performer by suppling
689// different metadata signatures as per omaha_metadata_signature flag and
690// sees if the result of the parsing are as per hash_checks_mandatory flag.
691void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
692 SignatureTest signature_test,
693 bool hash_checks_mandatory) {
694 DeltaState state;
695
696 // Using kSignatureNone since it doesn't affect the results of our test.
697 // If we've to use other signature options, then we'd have to get the
698 // metadata size again after adding the signing operation to the manifest.
699 GenerateDeltaFile(true, true, false, signature_test, &state);
700
701 ScopedPathUnlinker a_img_unlinker(state.a_img);
702 ScopedPathUnlinker b_img_unlinker(state.b_img);
703 ScopedPathUnlinker delta_unlinker(state.delta_path);
704 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
705 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
706
707 // Loads the payload and parses the manifest.
708 vector<char> payload;
709 EXPECT_TRUE(utils::ReadFile(state.delta_path, &payload));
710 LOG(INFO) << "Payload size: " << payload.size();
711
712 InstallPlan install_plan;
713 install_plan.hash_checks_mandatory = hash_checks_mandatory;
714 install_plan.metadata_size = state.metadata_size;
715
716 DeltaPerformer::MetadataParseResult expected_result, actual_result;
717 ActionExitCode expected_error, actual_error;
718
719 // Fill up the metadata signature in install plan according to the test.
720 switch (metadata_signature_test) {
721 case kEmptyMetadataSignature:
722 install_plan.metadata_signature.clear();
723 expected_result = DeltaPerformer::kMetadataParseError;
724 expected_error = kActionCodeDownloadMetadataSignatureMissingError;
725 break;
726
727 case kInvalidMetadataSignature:
728 install_plan.metadata_signature = kBogusMetadataSignature1;
729 expected_result = DeltaPerformer::kMetadataParseError;
730 expected_error = kActionCodeDownloadMetadataSignatureMismatch;
731 break;
732
733 case kValidMetadataSignature:
734 default:
735 // Set the install plan's metadata size to be the same as the one
736 // in the manifest so that we pass the metadata size checks. Only
737 // then we can get to manifest signature checks.
738 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
739 &payload[0],
740 state.metadata_size,
741 kUnittestPrivateKeyPath,
742 &install_plan.metadata_signature));
743 EXPECT_FALSE(install_plan.metadata_signature.empty());
744 expected_result = DeltaPerformer::kMetadataParseSuccess;
745 expected_error = kActionCodeSuccess;
746 break;
747 }
748
749 // Ignore the expected result/error if hash checks are not mandatory.
750 if (!hash_checks_mandatory) {
751 expected_result = DeltaPerformer::kMetadataParseSuccess;
752 expected_error = kActionCodeSuccess;
753 }
754
755 // Create the delta performer object.
756 PrefsMock prefs;
757 MockSystemState mock_system_state;
758 DeltaPerformer delta_performer(&prefs, &mock_system_state, &install_plan);
759
760 // Use the public key corresponding to the private key used above to
761 // sign the metadata.
762 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
763 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
764
765 // Parse the delta payload we created.
766 DeltaArchiveManifest manifest;
767 uint64_t parsed_metadata_size;
768
769 // Init actual_error with an invalid value so that we make sure
770 // ParsePayloadMetadata properly populates it in all cases.
771 actual_error = kActionCodeUmaReportedMax;
772 actual_result = delta_performer.ParsePayloadMetadata(payload, &manifest,
773 &parsed_metadata_size, &actual_error);
774
775 EXPECT_EQ(expected_result, actual_result);
776 EXPECT_EQ(expected_error, actual_error);
777
778 // Check that the parsed metadata size is what's expected. This test
779 // implicitly confirms that the metadata signature is valid, if required.
780 EXPECT_EQ(state.metadata_size, parsed_metadata_size);
781}
782
783void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
784 bool hash_checks_mandatory) {
785 DeltaState state;
786 GenerateDeltaFile(true, true, false, kSignatureGenerated, &state);
787 ScopedPathUnlinker a_img_unlinker(state.a_img);
788 ScopedPathUnlinker b_img_unlinker(state.b_img);
789 ScopedPathUnlinker delta_unlinker(state.delta_path);
790 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
791 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
792 DeltaPerformer *performer;
793 ApplyDeltaFile(true, true, false, kSignatureGenerated,
794 &state, hash_checks_mandatory, op_hash_test, &performer);
795}
796
797class DeltaPerformerTest : public ::testing::Test { };
798
799TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
800 uint64_t test[] = {1, 1, 4, 2, kSparseHole, 1, 0, 1};
801 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
802 const uint64_t block_size = 4096;
803 const uint64_t file_length = 5 * block_size - 13;
804
805 google::protobuf::RepeatedPtrField<Extent> extents;
806 for (size_t i = 0; i < arraysize(test); i += 2) {
807 Extent* extent = extents.Add();
808 extent->set_start_block(test[i]);
809 extent->set_num_blocks(test[i + 1]);
810 }
811
812 string expected_output = "4096:4096,16384:8192,-1:4096,0:4083";
813 string actual_output;
814 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
815 block_size,
816 file_length,
817 &actual_output));
818 EXPECT_EQ(expected_output, actual_output);
819}
Darin Petkov68c10d12010-10-14 09:24:37 -0700820
821TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800822 bool hash_checks_mandatory = false;
823 DoSmallImageTest(false, false, false, kSignatureGenerator,
824 hash_checks_mandatory);
Darin Petkov68c10d12010-10-14 09:24:37 -0700825}
826
827TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800828 bool hash_checks_mandatory = false;
829 DoSmallImageTest(true, false, false, kSignatureGenerator,
830 hash_checks_mandatory);
Darin Petkov7a22d792010-11-08 14:10:00 -0800831}
832
833TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800834 bool hash_checks_mandatory = true;
835 DoSmallImageTest(true, true, false, kSignatureGenerator,
836 hash_checks_mandatory);
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700837}
838
839TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800840 bool hash_checks_mandatory = false;
841 DoSmallImageTest(false, false, true, kSignatureGenerator,
842 hash_checks_mandatory);
Darin Petkov9574f7e2011-01-13 10:48:12 -0800843}
844
Darin Petkovcbfb0172011-01-14 15:24:45 -0800845TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800846 bool hash_checks_mandatory = false;
847 DoSmallImageTest(false, false, false, kSignatureNone,
848 hash_checks_mandatory);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800849}
850
851TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800852 bool hash_checks_mandatory = true;
853 DoSmallImageTest(false, false, false, kSignatureGenerated,
854 hash_checks_mandatory);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800855}
856
857TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800858 bool hash_checks_mandatory = false;
859 DoSmallImageTest(false, false, false, kSignatureGeneratedShell,
860 hash_checks_mandatory);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -0700861}
862
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800863TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800864 bool hash_checks_mandatory = false;
865 DoSmallImageTest(false, false, false, kSignatureGeneratedShellBadKey,
866 hash_checks_mandatory);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800867}
868
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700869TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800870 bool hash_checks_mandatory = false;
871 DoSmallImageTest(false, false, false, kSignatureGeneratedShellRotateCl1,
872 hash_checks_mandatory);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700873}
874
875TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800876 bool hash_checks_mandatory = false;
877 DoSmallImageTest(false, false, false, kSignatureGeneratedShellRotateCl2,
878 hash_checks_mandatory);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700879}
880
Darin Petkov934bb412010-11-18 11:21:35 -0800881TEST(DeltaPerformerTest, BadDeltaMagicTest) {
882 PrefsMock prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700883 InstallPlan install_plan;
Jay Srinivasanf0572052012-10-23 18:12:56 -0700884 MockSystemState mock_system_state;
885 DeltaPerformer performer(&prefs, &mock_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -0800886 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
887 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -0800888 EXPECT_TRUE(performer.Write("junk", 4));
889 EXPECT_TRUE(performer.Write("morejunk", 8));
890 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -0800891 EXPECT_LT(performer.Close(), 0);
892}
893
Andrew de los Reyes353777c2010-10-08 10:34:30 -0700894TEST(DeltaPerformerTest, IsIdempotentOperationTest) {
895 DeltaArchiveManifest_InstallOperation op;
896 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
897 *(op.add_dst_extents()) = ExtentForRange(0, 5);
898 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
899 *(op.add_src_extents()) = ExtentForRange(4, 1);
900 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
901 op.clear_src_extents();
902 *(op.add_src_extents()) = ExtentForRange(5, 3);
903 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
904 *(op.add_dst_extents()) = ExtentForRange(20, 6);
905 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
906 *(op.add_src_extents()) = ExtentForRange(19, 2);
907 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
908}
909
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800910TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
911 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700912}
913
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800914TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
915 DoMetadataSizeTest(0, 123456, false);
916}
917
918TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
919 DoMetadataSizeTest(13000, 140000, true);
920}
921
922TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
923 DoMetadataSizeTest(40000, 50000, false);
924}
925
926TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
927 DoMetadataSizeTest(85376, 85376, true);
928}
929
930TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
931 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, true);
932}
933
934TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
935 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, false);
936}
937
938TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
939 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated, true);
940}
941
942TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
943 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated,
944 false);
945}
946
947TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
948 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureNone, true);
949}
950
951TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
952 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, true);
953}
954
955TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
956 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, false);
957}
958
959TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
960 DoOperationHashMismatchTest(kInvalidOperationData, true);
961}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700962
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700963} // namespace chromeos_update_engine