blob: a72061bf1263085423af737b96cb3fa790af4531 [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
Allie Wood78750a42015-02-11 15:42:11 -080014#include <base/files/file_path.h>
Ben Chan06c76a42014-09-05 08:21:06 -070015#include <base/files/file_util.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070016#include <base/strings/stringprintf.h>
Alex Deymof1cbe172015-03-05 15:58:37 -080017#include <base/strings/string_util.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070018#include <google/protobuf/repeated_field.h>
19#include <gtest/gtest.h>
20
Jay Srinivasand29695d2013-04-08 15:08:05 -070021#include "update_engine/constants.h"
Andrew de los Reyes353777c2010-10-08 10:34:30 -070022#include "update_engine/extent_ranges.h"
David Zeuthene7f89172013-10-31 10:21:04 -070023#include "update_engine/fake_hardware.h"
Gilad Arnold5bb4c902014-04-10 12:32:13 -070024#include "update_engine/fake_system_state.h"
Alex Deymo8427b4a2014-11-05 14:00:32 -080025#include "update_engine/mock_prefs.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070026#include "update_engine/payload_constants.h"
27#include "update_engine/payload_generator/delta_diff_generator.h"
Alex Deymo923d8fa2014-07-15 17:58:51 -070028#include "update_engine/payload_generator/payload_signer.h"
29#include "update_engine/payload_verifier.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070030#include "update_engine/test_utils.h"
31#include "update_engine/update_metadata.pb.h"
32#include "update_engine/utils.h"
33
34namespace chromeos_update_engine {
35
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070036using std::string;
37using std::vector;
Darin Petkov73058b42010-10-06 16:32:19 -070038using testing::Return;
Alex Deymo161c4a12014-05-16 15:56:21 -070039using testing::_;
Alex Deymo10875d92014-11-10 21:52:57 -080040using test_utils::kRandomString;
41using test_utils::ScopedLoopMounter;
42using test_utils::System;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070043
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070044extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070045extern const char* kUnittestPublicKeyPath;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070046extern const char* kUnittestPrivateKey2Path;
47extern const char* kUnittestPublicKey2Path;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070048
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
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080058static const uint8_t kNewData[] = {'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
59 'n', 'e', 'w', ' ', 'd', 'a', 't', 'a', '.'};
Jay Srinivasan738fdf32012-12-07 17:40:54 -080060
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070061namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080062struct DeltaState {
63 string a_img;
64 string b_img;
Allie Wood9f6f0a52015-03-30 11:25:47 -070065 string result_img;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080066 int image_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070067
Jay Srinivasan738fdf32012-12-07 17:40:54 -080068 string delta_path;
69 uint64_t metadata_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070070
Jay Srinivasan738fdf32012-12-07 17:40:54 -080071 string old_kernel;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080072 chromeos::Blob old_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070073
Jay Srinivasan738fdf32012-12-07 17:40:54 -080074 string new_kernel;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080075 chromeos::Blob new_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070076
Allie Wood9f6f0a52015-03-30 11:25:47 -070077 string result_kernel;
78 chromeos::Blob result_kernel_data;
79
Jay Srinivasan738fdf32012-12-07 17:40:54 -080080 // The in-memory copy of delta file.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080081 chromeos::Blob delta;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080082
83 // The mock system state object with which we initialize the
84 // delta performer.
Gilad Arnold5bb4c902014-04-10 12:32:13 -070085 FakeSystemState fake_system_state;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080086};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070087
Jay Srinivasan738fdf32012-12-07 17:40:54 -080088enum SignatureTest {
89 kSignatureNone, // No payload signing.
90 kSignatureGenerator, // Sign the payload at generation time.
91 kSignatureGenerated, // Sign the payload after it's generated.
Don Garrett2ae37872013-10-25 13:33:20 -070092 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
Alex Vakulenkod2779df2014-06-16 13:19:00 -070093 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
Jay Srinivasan738fdf32012-12-07 17:40:54 -080094 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
95 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
96 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
97 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
98};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070099
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800100// Different options that determine what we should fill into the
101// install_plan.metadata_signature to simulate the contents received in the
102// Omaha response.
103enum MetadataSignatureTest {
104 kEmptyMetadataSignature,
105 kInvalidMetadataSignature,
106 kValidMetadataSignature,
107};
108
109enum OperationHashTest {
110 kInvalidOperationData,
111 kValidOperationData,
112};
113
Gilad Arnold542032d2015-05-11 04:44:55 +0000114// Chuck size used for full payloads during test.
115size_t kDefaultFullChunkSize = 1024 * 1024;
116
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700117} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800118
Allie Woodfdf00512015-03-02 13:34:55 -0800119class DeltaPerformerTest : public ::testing::Test {
120 public:
121 // Test helper placed where it can easily be friended from DeltaPerformer.
122 static void RunManifestValidation(const DeltaArchiveManifest& manifest,
123 bool full_payload,
124 ErrorCode expected) {
125 MockPrefs prefs;
126 InstallPlan install_plan;
127 FakeSystemState fake_system_state;
128 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
129
130 // The install plan is for Full or Delta.
131 install_plan.is_full_update = full_payload;
132
133 // The Manifest we are validating.
134 performer.manifest_.CopyFrom(manifest);
135
136 EXPECT_EQ(expected, performer.ValidateManifest());
137 }
138
139 static void SetSupportedVersion(DeltaPerformer* performer,
140 uint64_t minor_version) {
141 performer->supported_minor_version_ = minor_version;
142 }
143};
144
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800145static void CompareFilesByBlock(const string& a_file, const string& b_file) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800146 chromeos::Blob a_data, b_data;
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700147 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
148 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700149
150 EXPECT_EQ(a_data.size(), b_data.size());
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700151 EXPECT_EQ(0, a_data.size() % kBlockSize);
152 for (size_t i = 0; i < a_data.size(); i += kBlockSize) {
153 EXPECT_EQ(0, i % kBlockSize);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800154 chromeos::Blob a_sub(&a_data[i], &a_data[i + kBlockSize]);
155 chromeos::Blob b_sub(&b_data[i], &b_data[i + kBlockSize]);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700156 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
157 }
158}
159
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800160static bool WriteSparseFile(const string& path, off_t size) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700161 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
162 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
163 ScopedFdCloser fd_closer(&fd);
164 off_t rc = lseek(fd, size + 1, SEEK_SET);
165 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
166 int return_code = ftruncate(fd, size);
167 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
168 return true;
169}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700170
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800171static size_t GetSignatureSize(const string& private_key_path) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800172 const chromeos::Blob data(1, 'x');
173 chromeos::Blob hash;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800174 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(data, &hash));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800175 chromeos::Blob signature;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800176 EXPECT_TRUE(PayloadSigner::SignHash(hash,
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800177 private_key_path,
Darin Petkovcbfb0172011-01-14 15:24:45 -0800178 &signature));
179 return signature.size();
180}
181
Don Garrett2ae37872013-10-25 13:33:20 -0700182static bool InsertSignaturePlaceholder(int signature_size,
183 const string& payload_path,
184 uint64_t* out_metadata_size) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800185 vector<chromeos::Blob> signatures;
186 signatures.push_back(chromeos::Blob(signature_size, 0));
Don Garrett2ae37872013-10-25 13:33:20 -0700187
188 return PayloadSigner::AddSignatureToPayload(
189 payload_path,
190 signatures,
191 payload_path,
192 out_metadata_size);
193}
194
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800195static void SignGeneratedPayload(const string& payload_path,
196 uint64_t* out_metadata_size) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800197 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800198 chromeos::Blob hash;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700199 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
200 payload_path,
201 vector<int>(1, signature_size),
202 &hash));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800203 chromeos::Blob signature;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800204 ASSERT_TRUE(PayloadSigner::SignHash(hash,
205 kUnittestPrivateKeyPath,
206 &signature));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700207 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
208 payload_path,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800209 vector<chromeos::Blob>(1, signature),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800210 payload_path,
211 out_metadata_size));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700212 EXPECT_TRUE(PayloadVerifier::VerifySignedPayload(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700213 payload_path,
214 kUnittestPublicKeyPath,
215 kSignatureMessageOriginalVersion));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800216}
217
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800218static void SignGeneratedShellPayload(SignatureTest signature_test,
219 const string& payload_path) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800220 string private_key_path = kUnittestPrivateKeyPath;
221 if (signature_test == kSignatureGeneratedShellBadKey) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800222 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800223 &private_key_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700224 nullptr));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800225 } else {
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700226 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
227 signature_test == kSignatureGeneratedShellRotateCl1 ||
228 signature_test == kSignatureGeneratedShellRotateCl2);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800229 }
230 ScopedPathUnlinker key_unlinker(private_key_path);
231 key_unlinker.set_should_remove(signature_test ==
232 kSignatureGeneratedShellBadKey);
233 // Generates a new private key that will not match the public key.
234 if (signature_test == kSignatureGeneratedShellBadKey) {
235 LOG(INFO) << "Generating a mismatched private key.";
Alex Deymo719bfff2014-07-11 12:12:32 -0700236 ASSERT_EQ(0, System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400237 "openssl genrsa -out %s 2048", private_key_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800238 }
239 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800240 string hash_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700241 ASSERT_TRUE(utils::MakeTempFile("hash.XXXXXX", &hash_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800242 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700243 string signature_size_string;
244 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
245 signature_test == kSignatureGeneratedShellRotateCl2)
Alex Vakulenko75039d72014-03-25 12:36:28 -0700246 signature_size_string = base::StringPrintf("%d:%d",
247 signature_size, signature_size);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700248 else
Alex Vakulenko75039d72014-03-25 12:36:28 -0700249 signature_size_string = base::StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800250 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700251 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700252 "./delta_generator -in_file=%s -signature_size=%s "
253 "-out_hash_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800254 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700255 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800256 hash_file.c_str())));
257
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700258 // Pad the hash
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800259 chromeos::Blob hash;
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700260 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700261 ASSERT_TRUE(PayloadVerifier::PadRSA2048SHA256Hash(&hash));
Alex Deymo10875d92014-11-10 21:52:57 -0800262 ASSERT_TRUE(test_utils::WriteFileVector(hash_file, hash));
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700263
Darin Petkovcbfb0172011-01-14 15:24:45 -0800264 string sig_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700265 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800266 ScopedPathUnlinker sig_unlinker(sig_file);
267 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700268 System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400269 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800270 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800271 hash_file.c_str(),
272 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700273 string sig_file2;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700274 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file2, nullptr));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700275 ScopedPathUnlinker sig2_unlinker(sig_file2);
276 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
277 signature_test == kSignatureGeneratedShellRotateCl2) {
278 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700279 System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400280 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700281 kUnittestPrivateKey2Path,
282 hash_file.c_str(),
283 sig_file2.c_str())));
284 // Append second sig file to first path
285 sig_file += ":" + sig_file2;
286 }
287
Darin Petkovcbfb0172011-01-14 15:24:45 -0800288 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700289 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700290 "./delta_generator -in_file=%s -signature_file=%s "
291 "-out_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800292 payload_path.c_str(),
293 sig_file.c_str(),
294 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800295 int verify_result =
Alex Vakulenko75039d72014-03-25 12:36:28 -0700296 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700297 "./delta_generator -in_file=%s -public_key=%s -public_key_version=%d",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700298 payload_path.c_str(),
299 signature_test == kSignatureGeneratedShellRotateCl2 ?
300 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
301 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800302 if (signature_test == kSignatureGeneratedShellBadKey) {
303 ASSERT_NE(0, verify_result);
304 } else {
305 ASSERT_EQ(0, verify_result);
306 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800307}
308
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800309static void GenerateDeltaFile(bool full_kernel,
310 bool full_rootfs,
311 bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200312 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800313 SignatureTest signature_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800314 DeltaState *state,
315 uint32_t minor_version) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700316 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
317 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
Allie Wood9f6f0a52015-03-30 11:25:47 -0700318
319 // result_img is used in minor version 2. Instead of applying the update
320 // in-place on A, we apply it to a new image, result_img.
321 EXPECT_TRUE(
322 utils::MakeTempFile("result_img.XXXXXX", &state->result_img, nullptr));
Alex Deymo10875d92014-11-10 21:52:57 -0800323 test_utils::CreateExtImageAtPath(state->a_img, nullptr);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700324
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800325 state->image_size = static_cast<int>(utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700326
327 // Extend the "partitions" holding the file system a bit.
328 EXPECT_EQ(0, System(base::StringPrintf(
Alex Deymo1f93d032015-03-10 18:58:32 -0700329 "dd if=/dev/zero of=%s seek=%d bs=1 count=1 status=none",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800330 state->a_img.c_str(),
331 state->image_size + 1024 * 1024 - 1)));
332 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700333
Don Garrett0dd39852013-04-03 16:55:42 -0700334 // Create ImageInfo A & B
335 ImageInfo old_image_info;
336 ImageInfo new_image_info;
337
338 if (!full_rootfs) {
339 old_image_info.set_channel("src-channel");
340 old_image_info.set_board("src-board");
341 old_image_info.set_version("src-version");
342 old_image_info.set_key("src-key");
343 old_image_info.set_build_channel("src-build-channel");
344 old_image_info.set_build_version("src-build-version");
345 }
346
347 new_image_info.set_channel("test-channel");
348 new_image_info.set_board("test-board");
349 new_image_info.set_version("test-version");
350 new_image_info.set_key("test-key");
351 new_image_info.set_build_channel("test-build-channel");
352 new_image_info.set_build_version("test-build-version");
353
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700354 // Make some changes to the A image.
355 {
356 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800357 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700358
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800359 chromeos::Blob hardtocompress;
Darin Petkov8e447e02013-04-16 16:23:50 +0200360 while (hardtocompress.size() < 3 * kBlockSize) {
361 hardtocompress.insert(hardtocompress.end(),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800362 std::begin(kRandomString), std::end(kRandomString));
Darin Petkov8e447e02013-04-16 16:23:50 +0200363 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700364 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800365 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700366 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200367 hardtocompress.size()));
368
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800369 chromeos::Blob zeros(16 * 1024, 0);
Darin Petkov8a075a72013-04-25 14:46:09 +0200370 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700371 base::WriteFile(base::FilePath(base::StringPrintf(
372 "%s/move-to-sparse", a_mnt.c_str())),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800373 reinterpret_cast<const char*>(zeros.data()),
374 zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200375
376 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700377 WriteSparseFile(base::StringPrintf("%s/move-from-sparse",
378 a_mnt.c_str()), 16 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200379
Alex Vakulenko75039d72014-03-25 12:36:28 -0700380 EXPECT_EQ(0,
Alex Deymo10875d92014-11-10 21:52:57 -0800381 System(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
Alex Deymo1f93d032015-03-10 18:58:32 -0700382 " bs=1 seek=4096 count=1 status=none",
Alex Deymo10875d92014-11-10 21:52:57 -0800383 a_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200384
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700385 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
386 // patch fails to zero out the final block.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800387 chromeos::Blob ones(1024 * 1024, 0xff);
Alex Vakulenko75039d72014-03-25 12:36:28 -0700388 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/ones",
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800389 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700390 ones.data(),
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700391 ones.size()));
392 }
393
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700394 if (noop) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700395 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img),
396 base::FilePath(state->b_img)));
Don Garrett0dd39852013-04-03 16:55:42 -0700397 old_image_info = new_image_info;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700398 } else {
Allie Wood9f6f0a52015-03-30 11:25:47 -0700399 if (minor_version == kSourceMinorPayloadVersion) {
400 // Create a result image with image_size bytes of garbage, followed by
401 // zeroes after the rootfs, like image A and B have.
402 chromeos::Blob ones(state->image_size, 0xff);
403 ones.insert(ones.end(), 1024 * 1024, 0);
404 EXPECT_TRUE(utils::WriteFile(state->result_img.c_str(),
405 ones.data(),
406 ones.size()));
407 EXPECT_EQ(utils::FileSize(state->a_img),
408 utils::FileSize(state->result_img));
409 }
410
Alex Deymo10875d92014-11-10 21:52:57 -0800411 test_utils::CreateExtImageAtPath(state->b_img, nullptr);
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700412 EXPECT_EQ(0, System(base::StringPrintf(
Alex Deymo1f93d032015-03-10 18:58:32 -0700413 "dd if=/dev/zero of=%s seek=%d bs=1 count=1 status=none",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800414 state->b_img.c_str(),
415 state->image_size + 1024 * 1024 - 1)));
416 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700417
418 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700419 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800420 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700421
Alex Deymo10875d92014-11-10 21:52:57 -0800422 EXPECT_EQ(0, System(base::StringPrintf("cp %s/hello %s/hello2",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700423 b_mnt.c_str(),
424 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800425 EXPECT_EQ(0, System(base::StringPrintf("rm %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700426 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800427 EXPECT_EQ(0, System(base::StringPrintf("mv %s/hello2 %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700428 b_mnt.c_str(),
429 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800430 EXPECT_EQ(0, System(base::StringPrintf("echo foo > %s/foo",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700431 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800432 EXPECT_EQ(0, System(base::StringPrintf("touch %s/emptyfile",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700433 b_mnt.c_str()).c_str()));
434 EXPECT_TRUE(WriteSparseFile(base::StringPrintf("%s/fullsparse",
435 b_mnt.c_str()),
436 1024 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200437
438 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700439 WriteSparseFile(base::StringPrintf("%s/move-to-sparse", b_mnt.c_str()),
Darin Petkov8a075a72013-04-25 14:46:09 +0200440 16 * 1024));
441
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800442 chromeos::Blob zeros(16 * 1024, 0);
Darin Petkov8a075a72013-04-25 14:46:09 +0200443 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700444 base::WriteFile(base::FilePath(base::StringPrintf(
445 "%s/move-from-sparse", b_mnt.c_str())),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800446 reinterpret_cast<const char*>(zeros.data()),
447 zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200448
Alex Deymo10875d92014-11-10 21:52:57 -0800449 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700450 "of=%s/move-semi-sparse "
Alex Deymo1f93d032015-03-10 18:58:32 -0700451 "bs=1 seek=4096 count=1 status=none",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700452 b_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200453
Alex Deymo10875d92014-11-10 21:52:57 -0800454 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700455 "of=%s/partsparse bs=1 "
Alex Deymo1f93d032015-03-10 18:58:32 -0700456 "seek=4096 count=1 status=none",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700457 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800458 EXPECT_EQ(0, System(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700459 "mv %s/tmp %s/srchardlink1",
460 b_mnt.c_str(),
461 b_mnt.c_str(),
462 b_mnt.c_str(),
463 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800464 EXPECT_EQ(0, System(
465 base::StringPrintf("rm %s/boguslink && echo foobar > %s/boguslink",
466 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Darin Petkov8e447e02013-04-16 16:23:50 +0200467
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800468 chromeos::Blob hardtocompress;
Darin Petkov8e447e02013-04-16 16:23:50 +0200469 while (hardtocompress.size() < 3 * kBlockSize) {
470 hardtocompress.insert(hardtocompress.end(),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800471 std::begin(kRandomString), std::end(kRandomString));
Darin Petkov8e447e02013-04-16 16:23:50 +0200472 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700473 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700474 b_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700475 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200476 hardtocompress.size()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700477 }
478
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700479 string old_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800480 EXPECT_TRUE(utils::MakeTempFile("old_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800481 &state->old_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700482 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700483
484 string new_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800485 EXPECT_TRUE(utils::MakeTempFile("new_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800486 &state->new_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700487 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700488
Allie Wood9f6f0a52015-03-30 11:25:47 -0700489 string result_kernel;
490 EXPECT_TRUE(utils::MakeTempFile("result_kernel.XXXXXX",
491 &state->result_kernel,
492 nullptr));
493
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800494 state->old_kernel_data.resize(kDefaultKernelSize);
495 state->new_kernel_data.resize(state->old_kernel_data.size());
Allie Wood9f6f0a52015-03-30 11:25:47 -0700496 state->result_kernel_data.resize(state->old_kernel_data.size());
Alex Deymo10875d92014-11-10 21:52:57 -0800497 test_utils::FillWithData(&state->old_kernel_data);
498 test_utils::FillWithData(&state->new_kernel_data);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700499 test_utils::FillWithData(&state->result_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700500
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700501 // change the new kernel data
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800502 std::copy(std::begin(kNewData), std::end(kNewData),
503 state->new_kernel_data.begin());
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700504
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700505 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800506 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700507 }
508
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700509 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800510 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700511 state->old_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800512 state->old_kernel_data.size()));
513 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700514 state->new_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800515 state->new_kernel_data.size()));
Allie Wood9f6f0a52015-03-30 11:25:47 -0700516 EXPECT_TRUE(utils::WriteFile(state->result_kernel.c_str(),
517 state->result_kernel_data.data(),
518 state->result_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700519
Gilad Arnolda6742b32014-01-11 00:18:34 -0800520 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800521 &state->delta_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700522 nullptr));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800523 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700524 {
525 string a_mnt, b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800526 ScopedLoopMounter a_mounter(state->a_img, &a_mnt, MS_RDONLY);
527 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, MS_RDONLY);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800528 const string private_key =
529 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Alex Deymof1cbe172015-03-05 15:58:37 -0800530
531 PayloadGenerationConfig payload_config;
532 payload_config.is_delta = !full_rootfs;
533 payload_config.chunk_size = chunk_size;
Alex Deymo9b244df2015-03-11 21:51:18 -0700534 payload_config.rootfs_partition_size = kRootFSPartitionSize;
Allie Woodfdf00512015-03-02 13:34:55 -0800535 payload_config.minor_version = minor_version;
Alex Deymof1cbe172015-03-05 15:58:37 -0800536 if (!full_rootfs) {
537 payload_config.source.rootfs_part = state->a_img;
538 payload_config.source.rootfs_mountpt = a_mnt;
539 if (!full_kernel)
540 payload_config.source.kernel_part = state->old_kernel;
541 payload_config.source.image_info = old_image_info;
542 EXPECT_TRUE(payload_config.source.LoadImageSize());
543
Alex Deymof1cbe172015-03-05 15:58:37 -0800544 } else {
Allie Woodfdf00512015-03-02 13:34:55 -0800545 if (payload_config.chunk_size == -1)
Gilad Arnold542032d2015-05-11 04:44:55 +0000546 payload_config.chunk_size = kDefaultFullChunkSize;
Alex Deymof1cbe172015-03-05 15:58:37 -0800547 }
548 payload_config.target.rootfs_part = state->b_img;
549 payload_config.target.rootfs_mountpt = b_mnt;
550 payload_config.target.kernel_part = state->new_kernel;
551 payload_config.target.image_info = new_image_info;
552 EXPECT_TRUE(payload_config.target.LoadImageSize());
553
554 EXPECT_TRUE(payload_config.Validate());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700555 EXPECT_TRUE(
Alex Deymo477aec22015-03-24 23:40:48 -0700556 GenerateUpdatePayloadFile(
Alex Deymof1cbe172015-03-05 15:58:37 -0800557 payload_config,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800558 state->delta_path,
559 private_key,
560 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800561 }
562
Don Garrett2ae37872013-10-25 13:33:20 -0700563 if (signature_test == kSignatureGeneratedPlaceholder ||
564 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Don Garrett2ae37872013-10-25 13:33:20 -0700565 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
566 LOG(INFO) << "Inserting placeholder signature.";
567 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
568 &state->metadata_size));
569
570 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
571 signature_size -= 1;
572 LOG(INFO) << "Inserting mismatched placeholder signature.";
573 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
574 &state->metadata_size));
575 return;
576 }
577 }
578
579 if (signature_test == kSignatureGenerated ||
580 signature_test == kSignatureGeneratedPlaceholder ||
581 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800582 // Generate the signed payload and update the metadata size in state to
583 // reflect the new size after adding the signature operation to the
584 // manifest.
Don Garrett2ae37872013-10-25 13:33:20 -0700585 LOG(INFO) << "Signing payload.";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800586 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800587 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700588 signature_test == kSignatureGeneratedShellBadKey ||
589 signature_test == kSignatureGeneratedShellRotateCl1 ||
590 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800591 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700592 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800593}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700594
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800595static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
596 SignatureTest signature_test, DeltaState* state,
597 bool hash_checks_mandatory,
598 OperationHashTest op_hash_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800599 DeltaPerformer** performer,
600 uint32_t minor_version) {
Darin Petkov36a58222010-10-07 22:00:09 -0700601 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700602 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700603 DeltaArchiveManifest manifest;
Alex Deymo923d8fa2014-07-15 17:58:51 -0700604 EXPECT_TRUE(PayloadVerifier::LoadPayload(state->delta_path,
605 &state->delta,
606 &manifest,
607 &state->metadata_size));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800608 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700609
Don Garrett0dd39852013-04-03 16:55:42 -0700610
611
Darin Petkovcbfb0172011-01-14 15:24:45 -0800612 if (signature_test == kSignatureNone) {
613 EXPECT_FALSE(manifest.has_signatures_offset());
614 EXPECT_FALSE(manifest.has_signatures_size());
615 } else {
616 EXPECT_TRUE(manifest.has_signatures_offset());
617 EXPECT_TRUE(manifest.has_signatures_size());
618 Signatures sigs_message;
619 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800620 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800621 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700622 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
623 signature_test == kSignatureGeneratedShellRotateCl2)
624 EXPECT_EQ(2, sigs_message.signatures_size());
625 else
626 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800627 const Signatures_Signature& signature = sigs_message.signatures(0);
628 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700629
Darin Petkovcbfb0172011-01-14 15:24:45 -0800630 uint64_t expected_sig_data_length = 0;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700631 vector<string> key_paths{kUnittestPrivateKeyPath};
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700632 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
633 signature_test == kSignatureGeneratedShellRotateCl2) {
634 key_paths.push_back(kUnittestPrivateKey2Path);
635 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800636 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700637 key_paths,
638 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800639 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
640 EXPECT_FALSE(signature.data().empty());
641 }
Darin Petkov36a58222010-10-07 22:00:09 -0700642
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700643 if (noop) {
Gilad Arnold063181c2015-02-05 12:24:49 -0800644 EXPECT_EQ(0, manifest.install_operations_size());
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700645 EXPECT_EQ(1, manifest.kernel_install_operations_size());
646 }
647
Darin Petkovd43d6902010-10-14 11:17:50 -0700648 if (full_kernel) {
649 EXPECT_FALSE(manifest.has_old_kernel_info());
650 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800651 EXPECT_EQ(state->old_kernel_data.size(),
652 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700653 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
654 }
Darin Petkov698d0412010-10-13 10:59:44 -0700655
Don Garrett0dd39852013-04-03 16:55:42 -0700656 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
657 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
658 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
659 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
660 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
661 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
662
663 if (!full_rootfs) {
Don Garrett0dd39852013-04-03 16:55:42 -0700664 if (noop) {
665 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
666 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
667 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
668 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
669 EXPECT_EQ(manifest.old_image_info().build_channel(),
670 "test-build-channel");
671 EXPECT_EQ(manifest.old_image_info().build_version(),
672 "test-build-version");
673 } else {
674 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
675 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
676 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
677 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
678 EXPECT_EQ(manifest.old_image_info().build_channel(),
679 "src-build-channel");
680 EXPECT_EQ(manifest.old_image_info().build_version(),
681 "src-build-version");
682 }
683 }
684
685
Darin Petkov7a22d792010-11-08 14:10:00 -0800686 if (full_rootfs) {
687 EXPECT_FALSE(manifest.has_old_rootfs_info());
Don Garrett0dd39852013-04-03 16:55:42 -0700688 EXPECT_FALSE(manifest.has_old_image_info());
689 EXPECT_TRUE(manifest.has_new_image_info());
Darin Petkov7a22d792010-11-08 14:10:00 -0800690 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800691 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800692 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
693 }
694
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800695 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
696 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700697
Darin Petkov36a58222010-10-07 22:00:09 -0700698 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700699 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700700 }
701
Alex Deymo8427b4a2014-11-05 14:00:32 -0800702 MockPrefs prefs;
Darin Petkov73058b42010-10-06 16:32:19 -0700703 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800704 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700705 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
706 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700707 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
708 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700709 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
710 .WillRepeatedly(Return(true));
David Zeuthen41996ad2013-09-24 15:43:24 -0700711 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
712 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700713 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700714 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800715 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800716 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
717 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700718 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
719 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800720 }
Darin Petkov73058b42010-10-06 16:32:19 -0700721
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700722 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700723 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800724 install_plan.hash_checks_mandatory = hash_checks_mandatory;
725 install_plan.metadata_size = state->metadata_size;
Don Garrettb8dd1d92013-11-22 17:40:02 -0800726 install_plan.is_full_update = full_kernel && full_rootfs;
Allie Woodfdf00512015-03-02 13:34:55 -0800727 install_plan.source_path = state->a_img.c_str();
728 install_plan.kernel_source_path = state->old_kernel.c_str();
Don Garrettb8dd1d92013-11-22 17:40:02 -0800729
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800730 LOG(INFO) << "Setting payload metadata size in Omaha = "
731 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700732 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700733 state->delta.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800734 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700735 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700736 &install_plan.metadata_signature));
737 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700738
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800739 *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700740 &state->fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800741 &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700742 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800743 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Allie Woodfdf00512015-03-02 13:34:55 -0800744 DeltaPerformerTest::SetSupportedVersion(*performer, minor_version);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700745
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800746 EXPECT_EQ(state->image_size,
Allie Woodeb9e6d82015-04-17 13:55:30 -0700747 OmahaHashCalculator::RawHashOfFile(
748 state->a_img,
749 state->image_size,
750 &install_plan.source_rootfs_hash));
751 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(
752 state->old_kernel_data,
753 &install_plan.source_kernel_hash));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700754
Allie Wood9f6f0a52015-03-30 11:25:47 -0700755 // With minor version 2, we want the target to be the new image, result_img,
756 // but with version 1, we want to update A in place.
757 if (minor_version == kSourceMinorPayloadVersion) {
758 EXPECT_EQ(0, (*performer)->Open(state->result_img.c_str(), 0, 0));
759 EXPECT_TRUE((*performer)->OpenKernel(state->result_kernel.c_str()));
760 } else {
761 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
762 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
763 }
764
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800765
David Zeuthena99981f2013-04-29 13:42:47 -0700766 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800767 bool continue_writing;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700768 switch (op_hash_test) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800769 case kInvalidOperationData: {
770 // Muck with some random offset post the metadata size so that
771 // some operation hash will result in a mismatch.
772 int some_offset = state->metadata_size + 300;
773 LOG(INFO) << "Tampered value at offset: " << some_offset;
774 state->delta[some_offset]++;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700775 expected_error = ErrorCode::kDownloadOperationHashMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800776 continue_writing = false;
777 break;
778 }
779
780 case kValidOperationData:
781 default:
782 // no change.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700783 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800784 continue_writing = true;
785 break;
786 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700787
788 // Write at some number of bytes per operation. Arbitrarily chose 5.
789 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800790 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
Alex Deymof329b932014-10-30 01:37:48 -0700791 size_t count = std::min(state->delta.size() - i, kBytesPerWrite);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800792 bool write_succeeded = ((*performer)->Write(&state->delta[i],
793 count,
794 &actual_error));
795 // Normally write_succeeded should be true every time and
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700796 // actual_error should be ErrorCode::kSuccess. If so, continue the loop.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800797 // But if we seeded an operation hash error above, then write_succeeded
798 // will be false. The failure may happen at any operation n. So, all
799 // Writes until n-1 should succeed and the nth operation will fail with
800 // actual_error. In this case, we should bail out of the loop because
801 // we cannot proceed applying the delta.
802 if (!write_succeeded) {
803 LOG(INFO) << "Write failed. Checking if it failed with expected error";
804 EXPECT_EQ(expected_error, actual_error);
805 if (!continue_writing) {
806 LOG(INFO) << "Cannot continue writing. Bailing out.";
807 break;
808 }
809 }
810
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700811 EXPECT_EQ(ErrorCode::kSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700812 }
813
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800814 // If we had continued all the way through, Close should succeed.
815 // Otherwise, it should fail. Check appropriately.
816 bool close_result = (*performer)->Close();
817 if (continue_writing)
818 EXPECT_EQ(0, close_result);
819 else
820 EXPECT_LE(0, close_result);
821}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700822
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800823void VerifyPayloadResult(DeltaPerformer* performer,
824 DeltaState* state,
Allie Wood9f6f0a52015-03-30 11:25:47 -0700825 ErrorCode expected_result,
826 uint32_t minor_version) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800827 if (!performer) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700828 EXPECT_TRUE(!"Skipping payload verification since performer is null.");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800829 return;
830 }
831
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700832 int expected_times = (expected_result == ErrorCode::kSuccess) ? 1 : 0;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700833 EXPECT_CALL(*(state->fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800834 DownloadComplete()).Times(expected_times);
835
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800836 LOG(INFO) << "Verifying payload for expected result "
837 << expected_result;
838 EXPECT_EQ(expected_result, performer->VerifyPayload(
839 OmahaHashCalculator::OmahaHashOfData(state->delta),
840 state->delta.size()));
841 LOG(INFO) << "Verified payload.";
842
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700843 if (expected_result != ErrorCode::kSuccess) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800844 // no need to verify new partition if VerifyPayload failed.
845 return;
846 }
847
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800848 chromeos::Blob updated_kernel_partition;
Allie Wood9f6f0a52015-03-30 11:25:47 -0700849 if (minor_version == kSourceMinorPayloadVersion) {
850 CompareFilesByBlock(state->result_kernel, state->new_kernel);
851 CompareFilesByBlock(state->result_img, state->b_img);
852 EXPECT_TRUE(utils::ReadFile(state->result_kernel,
853 &updated_kernel_partition));
854 } else {
855 CompareFilesByBlock(state->old_kernel, state->new_kernel);
856 CompareFilesByBlock(state->a_img, state->b_img);
857 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
858 }
859
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800860 ASSERT_GE(updated_kernel_partition.size(), arraysize(kNewData));
861 EXPECT_TRUE(std::equal(std::begin(kNewData), std::end(kNewData),
862 updated_kernel_partition.begin()));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700863
864 uint64_t new_kernel_size;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800865 chromeos::Blob new_kernel_hash;
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700866 uint64_t new_rootfs_size;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800867 chromeos::Blob new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800868 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Don Garrett0dd39852013-04-03 16:55:42 -0700869 &new_kernel_hash,
870 &new_rootfs_size,
871 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800872 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800873 chromeos::Blob expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800874 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700875 &expected_new_kernel_hash));
876 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800877 EXPECT_EQ(state->image_size, new_rootfs_size);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800878 chromeos::Blob expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800879 EXPECT_EQ(state->image_size,
880 OmahaHashCalculator::RawHashOfFile(state->b_img,
881 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700882 &expected_new_rootfs_hash));
883 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
884}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800885
886void VerifyPayload(DeltaPerformer* performer,
887 DeltaState* state,
Allie Wood9f6f0a52015-03-30 11:25:47 -0700888 SignatureTest signature_test,
889 uint32_t minor_version) {
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700890 ErrorCode expected_result = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800891 switch (signature_test) {
892 case kSignatureNone:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700893 expected_result = ErrorCode::kSignedDeltaPayloadExpectedError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800894 break;
895 case kSignatureGeneratedShellBadKey:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700896 expected_result = ErrorCode::kDownloadPayloadPubKeyVerificationError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800897 break;
898 default: break; // appease gcc
899 }
900
Allie Wood9f6f0a52015-03-30 11:25:47 -0700901 VerifyPayloadResult(performer, state, expected_result, minor_version);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800902}
903
904void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200905 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800906 SignatureTest signature_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800907 bool hash_checks_mandatory, uint32_t minor_version) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800908 DeltaState state;
Alex Deymo52146ce2014-05-29 11:09:45 -0700909 DeltaPerformer *performer = nullptr;
Darin Petkov8e447e02013-04-16 16:23:50 +0200910 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
Allie Woodfdf00512015-03-02 13:34:55 -0800911 signature_test, &state, minor_version);
Don Garrett0dd39852013-04-03 16:55:42 -0700912
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800913 ScopedPathUnlinker a_img_unlinker(state.a_img);
914 ScopedPathUnlinker b_img_unlinker(state.b_img);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700915 ScopedPathUnlinker new_img_unlinker(state.result_img);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800916 ScopedPathUnlinker delta_unlinker(state.delta_path);
917 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
918 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700919 ScopedPathUnlinker result_kernel_unlinker(state.result_kernel);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800920 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
921 &state, hash_checks_mandatory, kValidOperationData,
Allie Woodfdf00512015-03-02 13:34:55 -0800922 &performer, minor_version);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700923 VerifyPayload(performer, &state, signature_test, minor_version);
Alex Deymo52146ce2014-05-29 11:09:45 -0700924 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800925}
926
927// Calls delta performer's Write method by pretending to pass in bytes from a
928// delta file whose metadata size is actual_metadata_size and tests if all
929// checks are correctly performed if the install plan contains
930// expected_metadata_size and that the result of the parsing are as per
931// hash_checks_mandatory flag.
932void DoMetadataSizeTest(uint64_t expected_metadata_size,
933 uint64_t actual_metadata_size,
934 bool hash_checks_mandatory) {
Alex Deymo8427b4a2014-11-05 14:00:32 -0800935 MockPrefs prefs;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800936 InstallPlan install_plan;
937 install_plan.hash_checks_mandatory = hash_checks_mandatory;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700938 FakeSystemState fake_system_state;
939 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800940 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
941 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
942
943 // Set a valid magic string and version number 1.
944 EXPECT_TRUE(performer.Write("CrAU", 4));
945 uint64_t version = htobe64(1);
946 EXPECT_TRUE(performer.Write(&version, 8));
947
948 install_plan.metadata_size = expected_metadata_size;
David Zeuthena99981f2013-04-29 13:42:47 -0700949 ErrorCode error_code;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800950 // When filling in size in manifest, exclude the size of the 20-byte header.
951 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
952 bool result = performer.Write(&size_in_manifest, 8, &error_code);
953 if (expected_metadata_size == actual_metadata_size ||
954 !hash_checks_mandatory) {
955 EXPECT_TRUE(result);
956 } else {
957 EXPECT_FALSE(result);
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700958 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800959 }
960
961 EXPECT_LT(performer.Close(), 0);
962}
963
964// Generates a valid delta file but tests the delta performer by suppling
965// different metadata signatures as per omaha_metadata_signature flag and
966// sees if the result of the parsing are as per hash_checks_mandatory flag.
967void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
968 SignatureTest signature_test,
969 bool hash_checks_mandatory) {
970 DeltaState state;
971
972 // Using kSignatureNone since it doesn't affect the results of our test.
973 // If we've to use other signature options, then we'd have to get the
974 // metadata size again after adding the signing operation to the manifest.
Allie Woodfdf00512015-03-02 13:34:55 -0800975 GenerateDeltaFile(true, true, false, -1, signature_test, &state,
976 DeltaPerformer::kFullPayloadMinorVersion);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800977
978 ScopedPathUnlinker a_img_unlinker(state.a_img);
979 ScopedPathUnlinker b_img_unlinker(state.b_img);
980 ScopedPathUnlinker delta_unlinker(state.delta_path);
981 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
982 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
983
984 // Loads the payload and parses the manifest.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800985 chromeos::Blob payload;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800986 EXPECT_TRUE(utils::ReadFile(state.delta_path, &payload));
987 LOG(INFO) << "Payload size: " << payload.size();
988
989 InstallPlan install_plan;
990 install_plan.hash_checks_mandatory = hash_checks_mandatory;
991 install_plan.metadata_size = state.metadata_size;
992
993 DeltaPerformer::MetadataParseResult expected_result, actual_result;
David Zeuthena99981f2013-04-29 13:42:47 -0700994 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800995
996 // Fill up the metadata signature in install plan according to the test.
997 switch (metadata_signature_test) {
998 case kEmptyMetadataSignature:
999 install_plan.metadata_signature.clear();
1000 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001001 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001002 break;
1003
1004 case kInvalidMetadataSignature:
1005 install_plan.metadata_signature = kBogusMetadataSignature1;
1006 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001007 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001008 break;
1009
1010 case kValidMetadataSignature:
1011 default:
1012 // Set the install plan's metadata size to be the same as the one
1013 // in the manifest so that we pass the metadata size checks. Only
1014 // then we can get to manifest signature checks.
1015 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -07001016 payload.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001017 state.metadata_size,
1018 kUnittestPrivateKeyPath,
1019 &install_plan.metadata_signature));
1020 EXPECT_FALSE(install_plan.metadata_signature.empty());
1021 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001022 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001023 break;
1024 }
1025
1026 // Ignore the expected result/error if hash checks are not mandatory.
1027 if (!hash_checks_mandatory) {
1028 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001029 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001030 }
1031
1032 // Create the delta performer object.
Alex Deymo8427b4a2014-11-05 14:00:32 -08001033 MockPrefs prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001034 DeltaPerformer delta_performer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001035 &state.fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001036 &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001037
1038 // Use the public key corresponding to the private key used above to
1039 // sign the metadata.
1040 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
1041 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
1042
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001043 // Init actual_error with an invalid value so that we make sure
1044 // ParsePayloadMetadata properly populates it in all cases.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001045 actual_error = ErrorCode::kUmaReportedMax;
Gilad Arnolddaa27402014-01-23 11:56:17 -08001046 actual_result = delta_performer.ParsePayloadMetadata(payload, &actual_error);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001047
1048 EXPECT_EQ(expected_result, actual_result);
1049 EXPECT_EQ(expected_error, actual_error);
1050
1051 // Check that the parsed metadata size is what's expected. This test
1052 // implicitly confirms that the metadata signature is valid, if required.
Gilad Arnoldfe133932014-01-14 12:25:50 -08001053 EXPECT_EQ(state.metadata_size, delta_performer.GetMetadataSize());
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001054}
1055
1056void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
1057 bool hash_checks_mandatory) {
1058 DeltaState state;
Allie Woodfdf00512015-03-02 13:34:55 -08001059 uint64_t minor_version = DeltaPerformer::kFullPayloadMinorVersion;
1060 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state,
1061 minor_version);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001062 ScopedPathUnlinker a_img_unlinker(state.a_img);
1063 ScopedPathUnlinker b_img_unlinker(state.b_img);
1064 ScopedPathUnlinker delta_unlinker(state.delta_path);
1065 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
1066 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Alex Deymo52146ce2014-05-29 11:09:45 -07001067 DeltaPerformer *performer = nullptr;
Allie Woodfdf00512015-03-02 13:34:55 -08001068 ApplyDeltaFile(true, true, false, kSignatureGenerated, &state,
1069 hash_checks_mandatory, op_hash_test, &performer,
1070 minor_version);
Alex Deymo52146ce2014-05-29 11:09:45 -07001071 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001072}
1073
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001074TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
Allie Wood56873452015-03-27 17:48:40 -07001075 uint64_t test[] = {1, 1, 4, 2, 0, 1};
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001076 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
1077 const uint64_t block_size = 4096;
Allie Wood56873452015-03-27 17:48:40 -07001078 const uint64_t file_length = 4 * block_size - 13;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001079
1080 google::protobuf::RepeatedPtrField<Extent> extents;
1081 for (size_t i = 0; i < arraysize(test); i += 2) {
1082 Extent* extent = extents.Add();
1083 extent->set_start_block(test[i]);
1084 extent->set_num_blocks(test[i + 1]);
1085 }
1086
Allie Wood56873452015-03-27 17:48:40 -07001087 string expected_output = "4096:4096,16384:8192,0:4083";
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001088 string actual_output;
1089 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
1090 block_size,
1091 file_length,
1092 &actual_output));
1093 EXPECT_EQ(expected_output, actual_output);
1094}
Darin Petkov68c10d12010-10-14 09:24:37 -07001095
Don Garrettb8dd1d92013-11-22 17:40:02 -08001096TEST(DeltaPerformerTest, ValidateManifestFullGoodTest) {
1097 // The Manifest we are validating.
1098 DeltaArchiveManifest manifest;
1099 manifest.mutable_new_kernel_info();
1100 manifest.mutable_new_rootfs_info();
1101 manifest.set_minor_version(DeltaPerformer::kFullPayloadMinorVersion);
1102
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001103 DeltaPerformerTest::RunManifestValidation(manifest, true,
1104 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001105}
1106
1107TEST(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
1108 // The Manifest we are validating.
1109 DeltaArchiveManifest manifest;
1110 manifest.mutable_old_kernel_info();
1111 manifest.mutable_old_rootfs_info();
1112 manifest.mutable_new_kernel_info();
1113 manifest.mutable_new_rootfs_info();
1114 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1115
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001116 DeltaPerformerTest::RunManifestValidation(manifest, false,
1117 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001118}
1119
1120TEST(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
1121 // The Manifest we are validating.
1122 DeltaArchiveManifest manifest;
1123
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001124 DeltaPerformerTest::RunManifestValidation(manifest, true,
1125 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001126}
1127
1128TEST(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
1129 // The Manifest we are validating.
1130 DeltaArchiveManifest manifest;
1131
1132 DeltaPerformerTest::RunManifestValidation(
1133 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001134 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001135}
1136
1137TEST(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
1138 // The Manifest we are validating.
1139 DeltaArchiveManifest manifest;
1140 manifest.mutable_old_kernel_info();
1141 manifest.mutable_new_kernel_info();
1142 manifest.mutable_new_rootfs_info();
1143 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1144
1145 DeltaPerformerTest::RunManifestValidation(
1146 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001147 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001148}
1149
1150TEST(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
1151 // The Manifest we are validating.
1152 DeltaArchiveManifest manifest;
1153 manifest.mutable_old_rootfs_info();
1154 manifest.mutable_new_kernel_info();
1155 manifest.mutable_new_rootfs_info();
1156 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1157
1158 DeltaPerformerTest::RunManifestValidation(
1159 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001160 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001161}
1162
1163TEST(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
1164 // The Manifest we are validating.
1165 DeltaArchiveManifest manifest;
1166
1167 // Generate a bad version number.
1168 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
1169 10000);
1170
1171 DeltaPerformerTest::RunManifestValidation(
1172 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001173 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001174}
1175
Darin Petkov68c10d12010-10-14 09:24:37 -07001176TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001177 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001178 false, kInPlaceMinorPayloadVersion);
Darin Petkov8e447e02013-04-16 16:23:50 +02001179}
1180
Don Garrett2ae37872013-10-25 13:33:20 -07001181TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
1182 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
Allie Woodfdf00512015-03-02 13:34:55 -08001183 false, kInPlaceMinorPayloadVersion);
Don Garrett2ae37872013-10-25 13:33:20 -07001184}
1185
1186TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
1187 DeltaState state;
1188 GenerateDeltaFile(false, false, false, -1,
Allie Woodfdf00512015-03-02 13:34:55 -08001189 kSignatureGeneratedPlaceholderMismatch, &state,
1190 kInPlaceMinorPayloadVersion);
Don Garrett2ae37872013-10-25 13:33:20 -07001191}
1192
Darin Petkov8e447e02013-04-16 16:23:50 +02001193TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001194 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001195 false, kInPlaceMinorPayloadVersion);
Darin Petkov68c10d12010-10-14 09:24:37 -07001196}
1197
1198TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001199 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001200 false, kInPlaceMinorPayloadVersion);
Darin Petkov7a22d792010-11-08 14:10:00 -08001201}
1202
1203TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001204 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001205 true, DeltaPerformer::kFullPayloadMinorVersion);
Darin Petkov9fa7ec52010-10-18 11:45:23 -07001206}
1207
1208TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001209 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001210 false, kInPlaceMinorPayloadVersion);
Darin Petkov9574f7e2011-01-13 10:48:12 -08001211}
1212
Darin Petkovcbfb0172011-01-14 15:24:45 -08001213TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001214 DoSmallImageTest(false, false, false, -1, kSignatureNone,
Allie Woodfdf00512015-03-02 13:34:55 -08001215 false, kInPlaceMinorPayloadVersion);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001216}
1217
1218TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001219 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
Allie Woodfdf00512015-03-02 13:34:55 -08001220 true, kInPlaceMinorPayloadVersion);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001221}
1222
1223TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001224 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
Allie Woodfdf00512015-03-02 13:34:55 -08001225 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -07001226}
1227
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001228TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001229 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
Allie Woodfdf00512015-03-02 13:34:55 -08001230 false, kInPlaceMinorPayloadVersion);
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001231}
1232
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001233TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001234 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
Allie Woodfdf00512015-03-02 13:34:55 -08001235 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001236}
1237
1238TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001239 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
Allie Woodfdf00512015-03-02 13:34:55 -08001240 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001241}
1242
Allie Wood9f6f0a52015-03-30 11:25:47 -07001243TEST(DeltaPerformerTest, RunAsRootSmallImageSourceOpsTest) {
1244 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
1245 false, kSourceMinorPayloadVersion);
1246}
1247
Darin Petkov934bb412010-11-18 11:21:35 -08001248TEST(DeltaPerformerTest, BadDeltaMagicTest) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001249 MockPrefs prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001250 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001251 FakeSystemState fake_system_state;
1252 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -08001253 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1254 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -08001255 EXPECT_TRUE(performer.Write("junk", 4));
1256 EXPECT_TRUE(performer.Write("morejunk", 8));
1257 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -08001258 EXPECT_LT(performer.Close(), 0);
1259}
1260
Andrew de los Reyes353777c2010-10-08 10:34:30 -07001261TEST(DeltaPerformerTest, IsIdempotentOperationTest) {
1262 DeltaArchiveManifest_InstallOperation op;
1263 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1264 *(op.add_dst_extents()) = ExtentForRange(0, 5);
1265 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1266 *(op.add_src_extents()) = ExtentForRange(4, 1);
1267 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1268 op.clear_src_extents();
1269 *(op.add_src_extents()) = ExtentForRange(5, 3);
1270 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1271 *(op.add_dst_extents()) = ExtentForRange(20, 6);
1272 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op));
1273 *(op.add_src_extents()) = ExtentForRange(19, 2);
1274 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op));
1275}
1276
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001277TEST(DeltaPerformerTest, WriteUpdatesPayloadState) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001278 MockPrefs prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001279 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001280 FakeSystemState fake_system_state;
1281 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001282 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1283 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
1284
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001285 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001286 DownloadProgress(4)).Times(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001287 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001288 DownloadProgress(8)).Times(2);
1289
1290 EXPECT_TRUE(performer.Write("junk", 4));
1291 EXPECT_TRUE(performer.Write("morejunk", 8));
1292 EXPECT_FALSE(performer.Write("morejunk", 8));
1293 EXPECT_LT(performer.Close(), 0);
1294}
1295
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001296TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
1297 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001298}
1299
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001300TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
1301 DoMetadataSizeTest(0, 123456, false);
1302}
1303
1304TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
1305 DoMetadataSizeTest(13000, 140000, true);
1306}
1307
1308TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
1309 DoMetadataSizeTest(40000, 50000, false);
1310}
1311
1312TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
1313 DoMetadataSizeTest(85376, 85376, true);
1314}
1315
1316TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
1317 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, true);
1318}
1319
1320TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
1321 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, false);
1322}
1323
1324TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
1325 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated, true);
1326}
1327
1328TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
1329 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated,
1330 false);
1331}
1332
1333TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
1334 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureNone, true);
1335}
1336
1337TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
1338 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, true);
1339}
1340
1341TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
1342 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, false);
1343}
1344
1345TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
1346 DoOperationHashMismatchTest(kInvalidOperationData, true);
1347}
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001348
David Zeuthene7f89172013-10-31 10:21:04 -07001349TEST(DeltaPerformerTest, UsePublicKeyFromResponse) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001350 MockPrefs prefs;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001351 FakeSystemState fake_system_state;
David Zeuthene7f89172013-10-31 10:21:04 -07001352 InstallPlan install_plan;
1353 base::FilePath key_path;
1354
1355 // The result of the GetPublicKeyResponse() method is based on three things
1356 //
1357 // 1. Whether it's an official build; and
1358 // 2. Whether the Public RSA key to be used is in the root filesystem; and
Alex Vakulenko072359c2014-07-18 11:41:07 -07001359 // 3. Whether the response has a public key
David Zeuthene7f89172013-10-31 10:21:04 -07001360 //
1361 // We test all eight combinations to ensure that we only use the
1362 // public key in the response if
1363 //
1364 // a. it's not an official build; and
1365 // b. there is no key in the root filesystem.
1366
1367 DeltaPerformer *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001368 &fake_system_state,
David Zeuthene7f89172013-10-31 10:21:04 -07001369 &install_plan);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001370 FakeHardware* fake_hardware = fake_system_state.fake_hardware();
David Zeuthene7f89172013-10-31 10:21:04 -07001371
1372 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -08001373 EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
David Zeuthene7f89172013-10-31 10:21:04 -07001374 &temp_dir));
1375 string non_existing_file = temp_dir + "/non-existing";
1376 string existing_file = temp_dir + "/existing";
Alex Vakulenko75039d72014-03-25 12:36:28 -07001377 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
David Zeuthene7f89172013-10-31 10:21:04 -07001378
1379 // Non-official build, non-existing public-key, key in response -> true
Don Garrett6646b442013-11-13 15:29:11 -08001380 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001381 performer->public_key_path_ = non_existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001382 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001383 EXPECT_TRUE(performer->GetPublicKeyFromResponse(&key_path));
1384 EXPECT_FALSE(key_path.empty());
1385 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
1386 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001387 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001388 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1389
1390 // Non-official build, existing public-key, key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001391 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001392 performer->public_key_path_ = existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001393 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001394 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1395 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001396 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001397 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1398
1399 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001400 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001401 performer->public_key_path_ = non_existing_file;
1402 install_plan.public_key_rsa = "";
1403 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1404 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001405 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001406 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1407
1408 // Non-official build, existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001409 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001410 performer->public_key_path_ = existing_file;
1411 install_plan.public_key_rsa = "";
1412 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1413 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001414 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001415 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1416
1417 // Non-official build, non-existing public-key, key in response
1418 // but invalid base64 -> false
Don Garrett6646b442013-11-13 15:29:11 -08001419 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001420 performer->public_key_path_ = non_existing_file;
1421 install_plan.public_key_rsa = "not-valid-base64";
1422 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1423
1424 delete performer;
Alex Deymo10875d92014-11-10 21:52:57 -08001425 EXPECT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
David Zeuthene7f89172013-10-31 10:21:04 -07001426}
1427
Allie Wood78750a42015-02-11 15:42:11 -08001428TEST(DeltaPerformerTest, MinorVersionsMatch) {
1429 // Test that the minor version in update_engine.conf that is installed to
1430 // the image matches the supported delta minor version in the update engine.
1431 uint32_t minor_version;
1432 base::FilePath conf_path("update_engine.conf");
1433 EXPECT_TRUE(utils::GetMinorVersion(conf_path, &minor_version));
1434 ASSERT_EQ(DeltaPerformer::kSupportedMinorPayloadVersion, minor_version);
1435}
1436
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001437} // namespace chromeos_update_engine