blob: 57374220feada017fd7a19a49cc3c3452f47c069 [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"
David Zeuthene7f89172013-10-31 10:21:04 -070022#include "update_engine/fake_hardware.h"
Gilad Arnold5bb4c902014-04-10 12:32:13 -070023#include "update_engine/fake_system_state.h"
Alex Deymo8427b4a2014-11-05 14:00:32 -080024#include "update_engine/mock_prefs.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070025#include "update_engine/payload_constants.h"
26#include "update_engine/payload_generator/delta_diff_generator.h"
Alex Deymo923d8fa2014-07-15 17:58:51 -070027#include "update_engine/payload_generator/payload_signer.h"
28#include "update_engine/payload_verifier.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070029#include "update_engine/test_utils.h"
30#include "update_engine/update_metadata.pb.h"
31#include "update_engine/utils.h"
32
33namespace chromeos_update_engine {
34
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070035using std::string;
36using std::vector;
Darin Petkov73058b42010-10-06 16:32:19 -070037using testing::Return;
Alex Deymo161c4a12014-05-16 15:56:21 -070038using testing::_;
Alex Deymo10875d92014-11-10 21:52:57 -080039using test_utils::kRandomString;
40using test_utils::ScopedLoopMounter;
41using test_utils::System;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070042
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070043extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070044extern const char* kUnittestPublicKeyPath;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -070045extern const char* kUnittestPrivateKey2Path;
46extern const char* kUnittestPublicKey2Path;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070047
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -070048static const char* kBogusMetadataSignature1 =
49 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
50 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
51 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
52 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
53 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
54 "pLRtClp97kN2+tXGNBQqkA==";
Jay Srinivasan738fdf32012-12-07 17:40:54 -080055
Alex Vakulenkod2779df2014-06-16 13:19:00 -070056static const int kDefaultKernelSize = 4096; // Something small for a test
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080057static const uint8_t kNewData[] = {'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
58 'n', 'e', 'w', ' ', 'd', 'a', 't', 'a', '.'};
Jay Srinivasan738fdf32012-12-07 17:40:54 -080059
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070060namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080061struct DeltaState {
62 string a_img;
63 string b_img;
Allie Wood9f6f0a52015-03-30 11:25:47 -070064 string result_img;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080065 int image_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070066
Jay Srinivasan738fdf32012-12-07 17:40:54 -080067 string delta_path;
68 uint64_t metadata_size;
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070069
Jay Srinivasan738fdf32012-12-07 17:40:54 -080070 string old_kernel;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080071 chromeos::Blob old_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070072
Jay Srinivasan738fdf32012-12-07 17:40:54 -080073 string new_kernel;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080074 chromeos::Blob new_kernel_data;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070075
Allie Wood9f6f0a52015-03-30 11:25:47 -070076 string result_kernel;
77 chromeos::Blob result_kernel_data;
78
Jay Srinivasan738fdf32012-12-07 17:40:54 -080079 // The in-memory copy of delta file.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080080 chromeos::Blob delta;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -080081
82 // The mock system state object with which we initialize the
83 // delta performer.
Gilad Arnold5bb4c902014-04-10 12:32:13 -070084 FakeSystemState fake_system_state;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080085};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070086
Jay Srinivasan738fdf32012-12-07 17:40:54 -080087enum SignatureTest {
88 kSignatureNone, // No payload signing.
89 kSignatureGenerator, // Sign the payload at generation time.
90 kSignatureGenerated, // Sign the payload after it's generated.
Don Garrett2ae37872013-10-25 13:33:20 -070091 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
Alex Vakulenkod2779df2014-06-16 13:19:00 -070092 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
Jay Srinivasan738fdf32012-12-07 17:40:54 -080093 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
94 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
95 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
96 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
97};
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070098
Jay Srinivasan738fdf32012-12-07 17:40:54 -080099// Different options that determine what we should fill into the
100// install_plan.metadata_signature to simulate the contents received in the
101// Omaha response.
102enum MetadataSignatureTest {
103 kEmptyMetadataSignature,
104 kInvalidMetadataSignature,
105 kValidMetadataSignature,
106};
107
108enum OperationHashTest {
109 kInvalidOperationData,
110 kValidOperationData,
111};
112
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700113} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800114
Allie Woodfdf00512015-03-02 13:34:55 -0800115class DeltaPerformerTest : public ::testing::Test {
116 public:
117 // Test helper placed where it can easily be friended from DeltaPerformer.
118 static void RunManifestValidation(const DeltaArchiveManifest& manifest,
119 bool full_payload,
120 ErrorCode expected) {
121 MockPrefs prefs;
122 InstallPlan install_plan;
123 FakeSystemState fake_system_state;
124 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
125
126 // The install plan is for Full or Delta.
127 install_plan.is_full_update = full_payload;
128
129 // The Manifest we are validating.
130 performer.manifest_.CopyFrom(manifest);
131
132 EXPECT_EQ(expected, performer.ValidateManifest());
133 }
134
135 static void SetSupportedVersion(DeltaPerformer* performer,
136 uint64_t minor_version) {
137 performer->supported_minor_version_ = minor_version;
138 }
139};
140
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800141static void CompareFilesByBlock(const string& a_file, const string& b_file) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800142 chromeos::Blob a_data, b_data;
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700143 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
144 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700145
146 EXPECT_EQ(a_data.size(), b_data.size());
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700147 EXPECT_EQ(0, a_data.size() % kBlockSize);
148 for (size_t i = 0; i < a_data.size(); i += kBlockSize) {
149 EXPECT_EQ(0, i % kBlockSize);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800150 chromeos::Blob a_sub(&a_data[i], &a_data[i + kBlockSize]);
151 chromeos::Blob b_sub(&b_data[i], &b_data[i + kBlockSize]);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700152 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
153 }
154}
155
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800156static bool WriteSparseFile(const string& path, off_t size) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700157 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
158 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
159 ScopedFdCloser fd_closer(&fd);
160 off_t rc = lseek(fd, size + 1, SEEK_SET);
161 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
162 int return_code = ftruncate(fd, size);
163 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
164 return true;
165}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700166
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800167static size_t GetSignatureSize(const string& private_key_path) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800168 const chromeos::Blob data(1, 'x');
169 chromeos::Blob hash;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800170 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(data, &hash));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800171 chromeos::Blob signature;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800172 EXPECT_TRUE(PayloadSigner::SignHash(hash,
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800173 private_key_path,
Darin Petkovcbfb0172011-01-14 15:24:45 -0800174 &signature));
175 return signature.size();
176}
177
Don Garrett2ae37872013-10-25 13:33:20 -0700178static bool InsertSignaturePlaceholder(int signature_size,
179 const string& payload_path,
180 uint64_t* out_metadata_size) {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800181 vector<chromeos::Blob> signatures;
182 signatures.push_back(chromeos::Blob(signature_size, 0));
Don Garrett2ae37872013-10-25 13:33:20 -0700183
184 return PayloadSigner::AddSignatureToPayload(
185 payload_path,
186 signatures,
187 payload_path,
188 out_metadata_size);
189}
190
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800191static void SignGeneratedPayload(const string& payload_path,
192 uint64_t* out_metadata_size) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800193 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800194 chromeos::Blob hash;
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700195 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
196 payload_path,
197 vector<int>(1, signature_size),
198 &hash));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800199 chromeos::Blob signature;
Darin Petkovcbfb0172011-01-14 15:24:45 -0800200 ASSERT_TRUE(PayloadSigner::SignHash(hash,
201 kUnittestPrivateKeyPath,
202 &signature));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700203 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
204 payload_path,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800205 vector<chromeos::Blob>(1, signature),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800206 payload_path,
207 out_metadata_size));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700208 EXPECT_TRUE(PayloadVerifier::VerifySignedPayload(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700209 payload_path,
210 kUnittestPublicKeyPath,
211 kSignatureMessageOriginalVersion));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800212}
213
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800214static void SignGeneratedShellPayload(SignatureTest signature_test,
215 const string& payload_path) {
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800216 string private_key_path = kUnittestPrivateKeyPath;
217 if (signature_test == kSignatureGeneratedShellBadKey) {
Gilad Arnolda6742b32014-01-11 00:18:34 -0800218 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800219 &private_key_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700220 nullptr));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800221 } else {
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700222 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
223 signature_test == kSignatureGeneratedShellRotateCl1 ||
224 signature_test == kSignatureGeneratedShellRotateCl2);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800225 }
226 ScopedPathUnlinker key_unlinker(private_key_path);
227 key_unlinker.set_should_remove(signature_test ==
228 kSignatureGeneratedShellBadKey);
229 // Generates a new private key that will not match the public key.
230 if (signature_test == kSignatureGeneratedShellBadKey) {
231 LOG(INFO) << "Generating a mismatched private key.";
Alex Deymo719bfff2014-07-11 12:12:32 -0700232 ASSERT_EQ(0, System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400233 "openssl genrsa -out %s 2048", private_key_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800234 }
235 int signature_size = GetSignatureSize(private_key_path);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800236 string hash_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700237 ASSERT_TRUE(utils::MakeTempFile("hash.XXXXXX", &hash_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800238 ScopedPathUnlinker hash_unlinker(hash_file);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700239 string signature_size_string;
240 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
241 signature_test == kSignatureGeneratedShellRotateCl2)
Alex Vakulenko75039d72014-03-25 12:36:28 -0700242 signature_size_string = base::StringPrintf("%d:%d",
243 signature_size, signature_size);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700244 else
Alex Vakulenko75039d72014-03-25 12:36:28 -0700245 signature_size_string = base::StringPrintf("%d", signature_size);
Darin Petkovcbfb0172011-01-14 15:24:45 -0800246 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700247 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700248 "./delta_generator -in_file=%s -signature_size=%s "
249 "-out_hash_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800250 payload_path.c_str(),
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700251 signature_size_string.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800252 hash_file.c_str())));
253
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700254 // Pad the hash
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800255 chromeos::Blob hash;
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700256 ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
Alex Deymo923d8fa2014-07-15 17:58:51 -0700257 ASSERT_TRUE(PayloadVerifier::PadRSA2048SHA256Hash(&hash));
Alex Deymo10875d92014-11-10 21:52:57 -0800258 ASSERT_TRUE(test_utils::WriteFileVector(hash_file, hash));
Andrew de los Reyesbdfaaf02011-03-30 10:35:12 -0700259
Darin Petkovcbfb0172011-01-14 15:24:45 -0800260 string sig_file;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700261 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file, nullptr));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800262 ScopedPathUnlinker sig_unlinker(sig_file);
263 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700264 System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400265 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800266 private_key_path.c_str(),
Darin Petkovcbfb0172011-01-14 15:24:45 -0800267 hash_file.c_str(),
268 sig_file.c_str())));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700269 string sig_file2;
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700270 ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file2, nullptr));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700271 ScopedPathUnlinker sig2_unlinker(sig_file2);
272 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
273 signature_test == kSignatureGeneratedShellRotateCl2) {
274 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700275 System(base::StringPrintf(
Mike Frysingerc31e4a72015-05-07 05:51:31 -0400276 "openssl rsautl -raw -sign -inkey %s -in %s -out %s",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700277 kUnittestPrivateKey2Path,
278 hash_file.c_str(),
279 sig_file2.c_str())));
280 // Append second sig file to first path
281 sig_file += ":" + sig_file2;
282 }
283
Darin Petkovcbfb0172011-01-14 15:24:45 -0800284 ASSERT_EQ(0,
Alex Vakulenko75039d72014-03-25 12:36:28 -0700285 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700286 "./delta_generator -in_file=%s -signature_file=%s "
287 "-out_file=%s",
Darin Petkovcbfb0172011-01-14 15:24:45 -0800288 payload_path.c_str(),
289 sig_file.c_str(),
290 payload_path.c_str())));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800291 int verify_result =
Alex Vakulenko75039d72014-03-25 12:36:28 -0700292 System(base::StringPrintf(
Steve Fung97b6f5a2014-10-07 12:39:51 -0700293 "./delta_generator -in_file=%s -public_key=%s -public_key_version=%d",
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700294 payload_path.c_str(),
295 signature_test == kSignatureGeneratedShellRotateCl2 ?
296 kUnittestPublicKey2Path : kUnittestPublicKeyPath,
297 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800298 if (signature_test == kSignatureGeneratedShellBadKey) {
299 ASSERT_NE(0, verify_result);
300 } else {
301 ASSERT_EQ(0, verify_result);
302 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800303}
304
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800305static void GenerateDeltaFile(bool full_kernel,
306 bool full_rootfs,
307 bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200308 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800309 SignatureTest signature_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800310 DeltaState *state,
311 uint32_t minor_version) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700312 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
313 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
Allie Wood9f6f0a52015-03-30 11:25:47 -0700314
315 // result_img is used in minor version 2. Instead of applying the update
316 // in-place on A, we apply it to a new image, result_img.
317 EXPECT_TRUE(
318 utils::MakeTempFile("result_img.XXXXXX", &state->result_img, nullptr));
Alex Deymo10875d92014-11-10 21:52:57 -0800319 test_utils::CreateExtImageAtPath(state->a_img, nullptr);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700320
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800321 state->image_size = static_cast<int>(utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700322
323 // Extend the "partitions" holding the file system a bit.
324 EXPECT_EQ(0, System(base::StringPrintf(
Alex Deymo1f93d032015-03-10 18:58:32 -0700325 "dd if=/dev/zero of=%s seek=%d bs=1 count=1 status=none",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800326 state->a_img.c_str(),
327 state->image_size + 1024 * 1024 - 1)));
328 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->a_img));
Darin Petkov7ea32332010-10-13 10:46:11 -0700329
Don Garrett0dd39852013-04-03 16:55:42 -0700330 // Create ImageInfo A & B
331 ImageInfo old_image_info;
332 ImageInfo new_image_info;
333
334 if (!full_rootfs) {
335 old_image_info.set_channel("src-channel");
336 old_image_info.set_board("src-board");
337 old_image_info.set_version("src-version");
338 old_image_info.set_key("src-key");
339 old_image_info.set_build_channel("src-build-channel");
340 old_image_info.set_build_version("src-build-version");
341 }
342
343 new_image_info.set_channel("test-channel");
344 new_image_info.set_board("test-board");
345 new_image_info.set_version("test-version");
346 new_image_info.set_key("test-key");
347 new_image_info.set_build_channel("test-build-channel");
348 new_image_info.set_build_version("test-build-version");
349
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700350 // Make some changes to the A image.
351 {
352 string a_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800353 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700354
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800355 chromeos::Blob hardtocompress;
Darin Petkov8e447e02013-04-16 16:23:50 +0200356 while (hardtocompress.size() < 3 * kBlockSize) {
357 hardtocompress.insert(hardtocompress.end(),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800358 std::begin(kRandomString), std::end(kRandomString));
Darin Petkov8e447e02013-04-16 16:23:50 +0200359 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700360 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800361 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700362 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200363 hardtocompress.size()));
364
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800365 chromeos::Blob zeros(16 * 1024, 0);
Darin Petkov8a075a72013-04-25 14:46:09 +0200366 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700367 base::WriteFile(base::FilePath(base::StringPrintf(
368 "%s/move-to-sparse", a_mnt.c_str())),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800369 reinterpret_cast<const char*>(zeros.data()),
370 zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200371
372 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700373 WriteSparseFile(base::StringPrintf("%s/move-from-sparse",
374 a_mnt.c_str()), 16 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200375
Alex Vakulenko75039d72014-03-25 12:36:28 -0700376 EXPECT_EQ(0,
Alex Deymo10875d92014-11-10 21:52:57 -0800377 System(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
Alex Deymo1f93d032015-03-10 18:58:32 -0700378 " bs=1 seek=4096 count=1 status=none",
Alex Deymo10875d92014-11-10 21:52:57 -0800379 a_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200380
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700381 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
382 // patch fails to zero out the final block.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800383 chromeos::Blob ones(1024 * 1024, 0xff);
Alex Vakulenko75039d72014-03-25 12:36:28 -0700384 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/ones",
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800385 a_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700386 ones.data(),
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700387 ones.size()));
388 }
389
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700390 if (noop) {
Alex Vakulenko75039d72014-03-25 12:36:28 -0700391 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img),
392 base::FilePath(state->b_img)));
Don Garrett0dd39852013-04-03 16:55:42 -0700393 old_image_info = new_image_info;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700394 } else {
Allie Wood9f6f0a52015-03-30 11:25:47 -0700395 if (minor_version == kSourceMinorPayloadVersion) {
396 // Create a result image with image_size bytes of garbage, followed by
397 // zeroes after the rootfs, like image A and B have.
398 chromeos::Blob ones(state->image_size, 0xff);
399 ones.insert(ones.end(), 1024 * 1024, 0);
400 EXPECT_TRUE(utils::WriteFile(state->result_img.c_str(),
401 ones.data(),
402 ones.size()));
403 EXPECT_EQ(utils::FileSize(state->a_img),
404 utils::FileSize(state->result_img));
405 }
406
Alex Deymo10875d92014-11-10 21:52:57 -0800407 test_utils::CreateExtImageAtPath(state->b_img, nullptr);
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700408 EXPECT_EQ(0, System(base::StringPrintf(
Alex Deymo1f93d032015-03-10 18:58:32 -0700409 "dd if=/dev/zero of=%s seek=%d bs=1 count=1 status=none",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800410 state->b_img.c_str(),
411 state->image_size + 1024 * 1024 - 1)));
412 EXPECT_EQ(state->image_size + 1024 * 1024, utils::FileSize(state->b_img));
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700413
414 // Make some changes to the B image.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700415 string b_mnt;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800416 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700417
Alex Deymo10875d92014-11-10 21:52:57 -0800418 EXPECT_EQ(0, System(base::StringPrintf("cp %s/hello %s/hello2",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700419 b_mnt.c_str(),
420 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800421 EXPECT_EQ(0, System(base::StringPrintf("rm %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700422 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800423 EXPECT_EQ(0, System(base::StringPrintf("mv %s/hello2 %s/hello",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700424 b_mnt.c_str(),
425 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800426 EXPECT_EQ(0, System(base::StringPrintf("echo foo > %s/foo",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700427 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800428 EXPECT_EQ(0, System(base::StringPrintf("touch %s/emptyfile",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700429 b_mnt.c_str()).c_str()));
430 EXPECT_TRUE(WriteSparseFile(base::StringPrintf("%s/fullsparse",
431 b_mnt.c_str()),
432 1024 * 1024));
Darin Petkov8a075a72013-04-25 14:46:09 +0200433
434 EXPECT_TRUE(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700435 WriteSparseFile(base::StringPrintf("%s/move-to-sparse", b_mnt.c_str()),
Darin Petkov8a075a72013-04-25 14:46:09 +0200436 16 * 1024));
437
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800438 chromeos::Blob zeros(16 * 1024, 0);
Darin Petkov8a075a72013-04-25 14:46:09 +0200439 EXPECT_EQ(zeros.size(),
Ben Chan736fcb52014-05-21 18:28:22 -0700440 base::WriteFile(base::FilePath(base::StringPrintf(
441 "%s/move-from-sparse", b_mnt.c_str())),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800442 reinterpret_cast<const char*>(zeros.data()),
443 zeros.size()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200444
Alex Deymo10875d92014-11-10 21:52:57 -0800445 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700446 "of=%s/move-semi-sparse "
Alex Deymo1f93d032015-03-10 18:58:32 -0700447 "bs=1 seek=4096 count=1 status=none",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700448 b_mnt.c_str()).c_str()));
Darin Petkov8a075a72013-04-25 14:46:09 +0200449
Alex Deymo10875d92014-11-10 21:52:57 -0800450 EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700451 "of=%s/partsparse bs=1 "
Alex Deymo1f93d032015-03-10 18:58:32 -0700452 "seek=4096 count=1 status=none",
Alex Vakulenko75039d72014-03-25 12:36:28 -0700453 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800454 EXPECT_EQ(0, System(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
Alex Vakulenko75039d72014-03-25 12:36:28 -0700455 "mv %s/tmp %s/srchardlink1",
456 b_mnt.c_str(),
457 b_mnt.c_str(),
458 b_mnt.c_str(),
459 b_mnt.c_str()).c_str()));
Alex Deymo10875d92014-11-10 21:52:57 -0800460 EXPECT_EQ(0, System(
461 base::StringPrintf("rm %s/boguslink && echo foobar > %s/boguslink",
462 b_mnt.c_str(), b_mnt.c_str()).c_str()));
Darin Petkov8e447e02013-04-16 16:23:50 +0200463
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800464 chromeos::Blob hardtocompress;
Darin Petkov8e447e02013-04-16 16:23:50 +0200465 while (hardtocompress.size() < 3 * kBlockSize) {
466 hardtocompress.insert(hardtocompress.end(),
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800467 std::begin(kRandomString), std::end(kRandomString));
Darin Petkov8e447e02013-04-16 16:23:50 +0200468 }
Alex Vakulenko75039d72014-03-25 12:36:28 -0700469 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700470 b_mnt.c_str()).c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700471 hardtocompress.data(),
Darin Petkov8e447e02013-04-16 16:23:50 +0200472 hardtocompress.size()));
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700473 }
474
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700475 string old_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800476 EXPECT_TRUE(utils::MakeTempFile("old_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800477 &state->old_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700478 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700479
480 string new_kernel;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800481 EXPECT_TRUE(utils::MakeTempFile("new_kernel.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800482 &state->new_kernel,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700483 nullptr));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700484
Allie Wood9f6f0a52015-03-30 11:25:47 -0700485 string result_kernel;
486 EXPECT_TRUE(utils::MakeTempFile("result_kernel.XXXXXX",
487 &state->result_kernel,
488 nullptr));
489
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800490 state->old_kernel_data.resize(kDefaultKernelSize);
491 state->new_kernel_data.resize(state->old_kernel_data.size());
Allie Wood9f6f0a52015-03-30 11:25:47 -0700492 state->result_kernel_data.resize(state->old_kernel_data.size());
Alex Deymo10875d92014-11-10 21:52:57 -0800493 test_utils::FillWithData(&state->old_kernel_data);
494 test_utils::FillWithData(&state->new_kernel_data);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700495 test_utils::FillWithData(&state->result_kernel_data);
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700496
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700497 // change the new kernel data
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800498 std::copy(std::begin(kNewData), std::end(kNewData),
499 state->new_kernel_data.begin());
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700500
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700501 if (noop) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800502 state->old_kernel_data = state->new_kernel_data;
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700503 }
504
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700505 // Write kernels to disk
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800506 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700507 state->old_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800508 state->old_kernel_data.size()));
509 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
Alex Vakulenko75039d72014-03-25 12:36:28 -0700510 state->new_kernel_data.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800511 state->new_kernel_data.size()));
Allie Wood9f6f0a52015-03-30 11:25:47 -0700512 EXPECT_TRUE(utils::WriteFile(state->result_kernel.c_str(),
513 state->result_kernel_data.data(),
514 state->result_kernel_data.size()));
Andrew de los Reyesf4c7ef12010-04-30 10:37:00 -0700515
Gilad Arnolda6742b32014-01-11 00:18:34 -0800516 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX",
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800517 &state->delta_path,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700518 nullptr));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800519 LOG(INFO) << "delta path: " << state->delta_path;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700520 {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800521 const string private_key =
522 signature_test == kSignatureGenerator ? kUnittestPrivateKeyPath : "";
Alex Deymof1cbe172015-03-05 15:58:37 -0800523
524 PayloadGenerationConfig payload_config;
525 payload_config.is_delta = !full_rootfs;
526 payload_config.chunk_size = chunk_size;
Alex Deymo9b244df2015-03-11 21:51:18 -0700527 payload_config.rootfs_partition_size = kRootFSPartitionSize;
Allie Woodfdf00512015-03-02 13:34:55 -0800528 payload_config.minor_version = minor_version;
Alex Deymof1cbe172015-03-05 15:58:37 -0800529 if (!full_rootfs) {
Alex Deymo35589c22015-06-07 17:33:18 +0200530 payload_config.source.rootfs.path = state->a_img;
Alex Deymof1cbe172015-03-05 15:58:37 -0800531 if (!full_kernel)
Alex Deymo35589c22015-06-07 17:33:18 +0200532 payload_config.source.kernel.path = state->old_kernel;
Alex Deymof1cbe172015-03-05 15:58:37 -0800533 payload_config.source.image_info = old_image_info;
534 EXPECT_TRUE(payload_config.source.LoadImageSize());
Alex Deymob42b98d2015-07-06 17:42:38 -0700535 EXPECT_TRUE(payload_config.source.rootfs.OpenFilesystem());
536 EXPECT_TRUE(payload_config.source.kernel.OpenFilesystem());
Alex Deymof1cbe172015-03-05 15:58:37 -0800537 } else {
Allie Woodfdf00512015-03-02 13:34:55 -0800538 if (payload_config.chunk_size == -1)
Gilad Arnold41e34742015-05-11 11:31:50 -0700539 payload_config.chunk_size = kDefaultChunkSize;
Alex Deymof1cbe172015-03-05 15:58:37 -0800540 }
Alex Deymo35589c22015-06-07 17:33:18 +0200541 payload_config.target.rootfs.path = state->b_img;
542 payload_config.target.kernel.path = state->new_kernel;
Alex Deymof1cbe172015-03-05 15:58:37 -0800543 payload_config.target.image_info = new_image_info;
544 EXPECT_TRUE(payload_config.target.LoadImageSize());
Alex Deymob42b98d2015-07-06 17:42:38 -0700545 EXPECT_TRUE(payload_config.target.rootfs.OpenFilesystem());
546 EXPECT_TRUE(payload_config.target.kernel.OpenFilesystem());
Alex Deymof1cbe172015-03-05 15:58:37 -0800547
548 EXPECT_TRUE(payload_config.Validate());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700549 EXPECT_TRUE(
Alex Deymo477aec22015-03-24 23:40:48 -0700550 GenerateUpdatePayloadFile(
Alex Deymof1cbe172015-03-05 15:58:37 -0800551 payload_config,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800552 state->delta_path,
553 private_key,
554 &state->metadata_size));
Darin Petkov9574f7e2011-01-13 10:48:12 -0800555 }
556
Don Garrett2ae37872013-10-25 13:33:20 -0700557 if (signature_test == kSignatureGeneratedPlaceholder ||
558 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Don Garrett2ae37872013-10-25 13:33:20 -0700559 int signature_size = GetSignatureSize(kUnittestPrivateKeyPath);
560 LOG(INFO) << "Inserting placeholder signature.";
561 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
562 &state->metadata_size));
563
564 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
565 signature_size -= 1;
566 LOG(INFO) << "Inserting mismatched placeholder signature.";
567 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
568 &state->metadata_size));
569 return;
570 }
571 }
572
573 if (signature_test == kSignatureGenerated ||
574 signature_test == kSignatureGeneratedPlaceholder ||
575 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800576 // Generate the signed payload and update the metadata size in state to
577 // reflect the new size after adding the signature operation to the
578 // manifest.
Don Garrett2ae37872013-10-25 13:33:20 -0700579 LOG(INFO) << "Signing payload.";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800580 SignGeneratedPayload(state->delta_path, &state->metadata_size);
Darin Petkov52dcaeb2011-01-14 15:33:06 -0800581 } else if (signature_test == kSignatureGeneratedShell ||
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700582 signature_test == kSignatureGeneratedShellBadKey ||
583 signature_test == kSignatureGeneratedShellRotateCl1 ||
584 signature_test == kSignatureGeneratedShellRotateCl2) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800585 SignGeneratedShellPayload(signature_test, state->delta_path);
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700586 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800587}
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700588
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800589static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
590 SignatureTest signature_test, DeltaState* state,
591 bool hash_checks_mandatory,
592 OperationHashTest op_hash_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800593 DeltaPerformer** performer,
594 uint32_t minor_version) {
Darin Petkov36a58222010-10-07 22:00:09 -0700595 // Check the metadata.
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700596 {
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700597 DeltaArchiveManifest manifest;
Alex Deymo923d8fa2014-07-15 17:58:51 -0700598 EXPECT_TRUE(PayloadVerifier::LoadPayload(state->delta_path,
599 &state->delta,
600 &manifest,
601 &state->metadata_size));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800602 LOG(INFO) << "Metadata size: " << state->metadata_size;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700603
Don Garrett0dd39852013-04-03 16:55:42 -0700604
605
Darin Petkovcbfb0172011-01-14 15:24:45 -0800606 if (signature_test == kSignatureNone) {
607 EXPECT_FALSE(manifest.has_signatures_offset());
608 EXPECT_FALSE(manifest.has_signatures_size());
609 } else {
610 EXPECT_TRUE(manifest.has_signatures_offset());
611 EXPECT_TRUE(manifest.has_signatures_size());
612 Signatures sigs_message;
613 EXPECT_TRUE(sigs_message.ParseFromArray(
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800614 &state->delta[state->metadata_size + manifest.signatures_offset()],
Darin Petkovcbfb0172011-01-14 15:24:45 -0800615 manifest.signatures_size()));
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700616 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
617 signature_test == kSignatureGeneratedShellRotateCl2)
618 EXPECT_EQ(2, sigs_message.signatures_size());
619 else
620 EXPECT_EQ(1, sigs_message.signatures_size());
Darin Petkovcbfb0172011-01-14 15:24:45 -0800621 const Signatures_Signature& signature = sigs_message.signatures(0);
622 EXPECT_EQ(1, signature.version());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700623
Darin Petkovcbfb0172011-01-14 15:24:45 -0800624 uint64_t expected_sig_data_length = 0;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700625 vector<string> key_paths{kUnittestPrivateKeyPath};
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700626 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
627 signature_test == kSignatureGeneratedShellRotateCl2) {
628 key_paths.push_back(kUnittestPrivateKey2Path);
629 }
Darin Petkovcbfb0172011-01-14 15:24:45 -0800630 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -0700631 key_paths,
632 &expected_sig_data_length));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800633 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
634 EXPECT_FALSE(signature.data().empty());
635 }
Darin Petkov36a58222010-10-07 22:00:09 -0700636
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700637 if (noop) {
Gilad Arnold063181c2015-02-05 12:24:49 -0800638 EXPECT_EQ(0, manifest.install_operations_size());
Darin Petkov9fa7ec52010-10-18 11:45:23 -0700639 EXPECT_EQ(1, manifest.kernel_install_operations_size());
640 }
641
Darin Petkovd43d6902010-10-14 11:17:50 -0700642 if (full_kernel) {
643 EXPECT_FALSE(manifest.has_old_kernel_info());
644 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800645 EXPECT_EQ(state->old_kernel_data.size(),
646 manifest.old_kernel_info().size());
Darin Petkovd43d6902010-10-14 11:17:50 -0700647 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
648 }
Darin Petkov698d0412010-10-13 10:59:44 -0700649
Don Garrett0dd39852013-04-03 16:55:42 -0700650 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
651 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
652 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
653 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
654 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
655 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
656
657 if (!full_rootfs) {
Don Garrett0dd39852013-04-03 16:55:42 -0700658 if (noop) {
659 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
660 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
661 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
662 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
663 EXPECT_EQ(manifest.old_image_info().build_channel(),
664 "test-build-channel");
665 EXPECT_EQ(manifest.old_image_info().build_version(),
666 "test-build-version");
667 } else {
668 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
669 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
670 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
671 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
672 EXPECT_EQ(manifest.old_image_info().build_channel(),
673 "src-build-channel");
674 EXPECT_EQ(manifest.old_image_info().build_version(),
675 "src-build-version");
676 }
677 }
678
679
Darin Petkov7a22d792010-11-08 14:10:00 -0800680 if (full_rootfs) {
681 EXPECT_FALSE(manifest.has_old_rootfs_info());
Don Garrett0dd39852013-04-03 16:55:42 -0700682 EXPECT_FALSE(manifest.has_old_image_info());
683 EXPECT_TRUE(manifest.has_new_image_info());
Darin Petkov7a22d792010-11-08 14:10:00 -0800684 } else {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800685 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
Darin Petkov7a22d792010-11-08 14:10:00 -0800686 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
687 }
688
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800689 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
690 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
Darin Petkov36a58222010-10-07 22:00:09 -0700691
Darin Petkov36a58222010-10-07 22:00:09 -0700692 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
Darin Petkov36a58222010-10-07 22:00:09 -0700693 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -0700694 }
695
Alex Deymo8427b4a2014-11-05 14:00:32 -0800696 MockPrefs prefs;
Darin Petkov73058b42010-10-06 16:32:19 -0700697 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800698 state->metadata_size)).WillOnce(Return(true));
Darin Petkov73058b42010-10-06 16:32:19 -0700699 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
700 .WillRepeatedly(Return(true));
Darin Petkov9b230572010-10-08 10:20:09 -0700701 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
702 .WillOnce(Return(false));
Darin Petkov73058b42010-10-06 16:32:19 -0700703 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
704 .WillRepeatedly(Return(true));
David Zeuthen41996ad2013-09-24 15:43:24 -0700705 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
706 .WillRepeatedly(Return(true));
Darin Petkov437adc42010-10-07 13:12:24 -0700707 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
Darin Petkov73058b42010-10-06 16:32:19 -0700708 .WillRepeatedly(Return(true));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800709 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Darin Petkovcbfb0172011-01-14 15:24:45 -0800710 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
711 .WillOnce(Return(true));
Darin Petkov4f0a07b2011-05-25 16:47:20 -0700712 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
713 .WillOnce(Return(true));
Darin Petkovcbfb0172011-01-14 15:24:45 -0800714 }
Darin Petkov73058b42010-10-06 16:32:19 -0700715
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700716 // Update the A image in place.
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700717 InstallPlan install_plan;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800718 install_plan.hash_checks_mandatory = hash_checks_mandatory;
719 install_plan.metadata_size = state->metadata_size;
Don Garrettb8dd1d92013-11-22 17:40:02 -0800720 install_plan.is_full_update = full_kernel && full_rootfs;
Allie Woodfdf00512015-03-02 13:34:55 -0800721 install_plan.source_path = state->a_img.c_str();
722 install_plan.kernel_source_path = state->old_kernel.c_str();
Don Garrettb8dd1d92013-11-22 17:40:02 -0800723
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800724 LOG(INFO) << "Setting payload metadata size in Omaha = "
725 << state->metadata_size;
Jay Srinivasanf4318702012-09-24 11:56:24 -0700726 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -0700727 state->delta.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800728 state->metadata_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700729 kUnittestPrivateKeyPath,
Jay Srinivasanf4318702012-09-24 11:56:24 -0700730 &install_plan.metadata_signature));
731 EXPECT_FALSE(install_plan.metadata_signature.empty());
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700732
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800733 *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700734 &state->fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800735 &install_plan);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700736 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800737 (*performer)->set_public_key_path(kUnittestPublicKeyPath);
Allie Woodfdf00512015-03-02 13:34:55 -0800738 DeltaPerformerTest::SetSupportedVersion(*performer, minor_version);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700739
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800740 EXPECT_EQ(state->image_size,
Allie Woodeb9e6d82015-04-17 13:55:30 -0700741 OmahaHashCalculator::RawHashOfFile(
742 state->a_img,
743 state->image_size,
744 &install_plan.source_rootfs_hash));
745 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(
746 state->old_kernel_data,
747 &install_plan.source_kernel_hash));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700748
Allie Wood9f6f0a52015-03-30 11:25:47 -0700749 // With minor version 2, we want the target to be the new image, result_img,
750 // but with version 1, we want to update A in place.
751 if (minor_version == kSourceMinorPayloadVersion) {
752 EXPECT_EQ(0, (*performer)->Open(state->result_img.c_str(), 0, 0));
753 EXPECT_TRUE((*performer)->OpenKernel(state->result_kernel.c_str()));
754 } else {
755 EXPECT_EQ(0, (*performer)->Open(state->a_img.c_str(), 0, 0));
756 EXPECT_TRUE((*performer)->OpenKernel(state->old_kernel.c_str()));
757 }
758
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800759
David Zeuthena99981f2013-04-29 13:42:47 -0700760 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800761 bool continue_writing;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700762 switch (op_hash_test) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800763 case kInvalidOperationData: {
764 // Muck with some random offset post the metadata size so that
765 // some operation hash will result in a mismatch.
766 int some_offset = state->metadata_size + 300;
767 LOG(INFO) << "Tampered value at offset: " << some_offset;
768 state->delta[some_offset]++;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700769 expected_error = ErrorCode::kDownloadOperationHashMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800770 continue_writing = false;
771 break;
772 }
773
774 case kValidOperationData:
775 default:
776 // no change.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700777 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800778 continue_writing = true;
779 break;
780 }
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700781
782 // Write at some number of bytes per operation. Arbitrarily chose 5.
783 const size_t kBytesPerWrite = 5;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800784 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
Alex Deymof329b932014-10-30 01:37:48 -0700785 size_t count = std::min(state->delta.size() - i, kBytesPerWrite);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800786 bool write_succeeded = ((*performer)->Write(&state->delta[i],
787 count,
788 &actual_error));
789 // Normally write_succeeded should be true every time and
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700790 // actual_error should be ErrorCode::kSuccess. If so, continue the loop.
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800791 // But if we seeded an operation hash error above, then write_succeeded
792 // will be false. The failure may happen at any operation n. So, all
793 // Writes until n-1 should succeed and the nth operation will fail with
794 // actual_error. In this case, we should bail out of the loop because
795 // we cannot proceed applying the delta.
796 if (!write_succeeded) {
797 LOG(INFO) << "Write failed. Checking if it failed with expected error";
798 EXPECT_EQ(expected_error, actual_error);
799 if (!continue_writing) {
800 LOG(INFO) << "Cannot continue writing. Bailing out.";
801 break;
802 }
803 }
804
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700805 EXPECT_EQ(ErrorCode::kSuccess, actual_error);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700806 }
807
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800808 // If we had continued all the way through, Close should succeed.
809 // Otherwise, it should fail. Check appropriately.
810 bool close_result = (*performer)->Close();
811 if (continue_writing)
812 EXPECT_EQ(0, close_result);
813 else
814 EXPECT_LE(0, close_result);
815}
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700816
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800817void VerifyPayloadResult(DeltaPerformer* performer,
818 DeltaState* state,
Allie Wood9f6f0a52015-03-30 11:25:47 -0700819 ErrorCode expected_result,
820 uint32_t minor_version) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800821 if (!performer) {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700822 EXPECT_TRUE(!"Skipping payload verification since performer is null.");
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800823 return;
824 }
825
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700826 int expected_times = (expected_result == ErrorCode::kSuccess) ? 1 : 0;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700827 EXPECT_CALL(*(state->fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800828 DownloadComplete()).Times(expected_times);
829
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800830 LOG(INFO) << "Verifying payload for expected result "
831 << expected_result;
832 EXPECT_EQ(expected_result, performer->VerifyPayload(
833 OmahaHashCalculator::OmahaHashOfData(state->delta),
834 state->delta.size()));
835 LOG(INFO) << "Verified payload.";
836
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700837 if (expected_result != ErrorCode::kSuccess) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800838 // no need to verify new partition if VerifyPayload failed.
839 return;
840 }
841
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800842 chromeos::Blob updated_kernel_partition;
Allie Wood9f6f0a52015-03-30 11:25:47 -0700843 if (minor_version == kSourceMinorPayloadVersion) {
844 CompareFilesByBlock(state->result_kernel, state->new_kernel);
845 CompareFilesByBlock(state->result_img, state->b_img);
846 EXPECT_TRUE(utils::ReadFile(state->result_kernel,
847 &updated_kernel_partition));
848 } else {
849 CompareFilesByBlock(state->old_kernel, state->new_kernel);
850 CompareFilesByBlock(state->a_img, state->b_img);
851 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
852 }
853
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800854 ASSERT_GE(updated_kernel_partition.size(), arraysize(kNewData));
855 EXPECT_TRUE(std::equal(std::begin(kNewData), std::end(kNewData),
856 updated_kernel_partition.begin()));
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700857
858 uint64_t new_kernel_size;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800859 chromeos::Blob new_kernel_hash;
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700860 uint64_t new_rootfs_size;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800861 chromeos::Blob new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800862 EXPECT_TRUE(performer->GetNewPartitionInfo(&new_kernel_size,
Don Garrett0dd39852013-04-03 16:55:42 -0700863 &new_kernel_hash,
864 &new_rootfs_size,
865 &new_rootfs_hash));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800866 EXPECT_EQ(kDefaultKernelSize, new_kernel_size);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800867 chromeos::Blob expected_new_kernel_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800868 EXPECT_TRUE(OmahaHashCalculator::RawHashOfData(state->new_kernel_data,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700869 &expected_new_kernel_hash));
870 EXPECT_TRUE(expected_new_kernel_hash == new_kernel_hash);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800871 EXPECT_EQ(state->image_size, new_rootfs_size);
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800872 chromeos::Blob expected_new_rootfs_hash;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800873 EXPECT_EQ(state->image_size,
874 OmahaHashCalculator::RawHashOfFile(state->b_img,
875 state->image_size,
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700876 &expected_new_rootfs_hash));
877 EXPECT_TRUE(expected_new_rootfs_hash == new_rootfs_hash);
878}
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800879
880void VerifyPayload(DeltaPerformer* performer,
881 DeltaState* state,
Allie Wood9f6f0a52015-03-30 11:25:47 -0700882 SignatureTest signature_test,
883 uint32_t minor_version) {
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700884 ErrorCode expected_result = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800885 switch (signature_test) {
886 case kSignatureNone:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700887 expected_result = ErrorCode::kSignedDeltaPayloadExpectedError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800888 break;
889 case kSignatureGeneratedShellBadKey:
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700890 expected_result = ErrorCode::kDownloadPayloadPubKeyVerificationError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800891 break;
892 default: break; // appease gcc
893 }
894
Allie Wood9f6f0a52015-03-30 11:25:47 -0700895 VerifyPayloadResult(performer, state, expected_result, minor_version);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800896}
897
898void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
Darin Petkov8e447e02013-04-16 16:23:50 +0200899 off_t chunk_size,
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800900 SignatureTest signature_test,
Allie Woodfdf00512015-03-02 13:34:55 -0800901 bool hash_checks_mandatory, uint32_t minor_version) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800902 DeltaState state;
Alex Deymo52146ce2014-05-29 11:09:45 -0700903 DeltaPerformer *performer = nullptr;
Darin Petkov8e447e02013-04-16 16:23:50 +0200904 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
Allie Woodfdf00512015-03-02 13:34:55 -0800905 signature_test, &state, minor_version);
Don Garrett0dd39852013-04-03 16:55:42 -0700906
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800907 ScopedPathUnlinker a_img_unlinker(state.a_img);
908 ScopedPathUnlinker b_img_unlinker(state.b_img);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700909 ScopedPathUnlinker new_img_unlinker(state.result_img);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800910 ScopedPathUnlinker delta_unlinker(state.delta_path);
911 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
912 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700913 ScopedPathUnlinker result_kernel_unlinker(state.result_kernel);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800914 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
915 &state, hash_checks_mandatory, kValidOperationData,
Allie Woodfdf00512015-03-02 13:34:55 -0800916 &performer, minor_version);
Allie Wood9f6f0a52015-03-30 11:25:47 -0700917 VerifyPayload(performer, &state, signature_test, minor_version);
Alex Deymo52146ce2014-05-29 11:09:45 -0700918 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800919}
920
921// Calls delta performer's Write method by pretending to pass in bytes from a
922// delta file whose metadata size is actual_metadata_size and tests if all
923// checks are correctly performed if the install plan contains
924// expected_metadata_size and that the result of the parsing are as per
925// hash_checks_mandatory flag.
926void DoMetadataSizeTest(uint64_t expected_metadata_size,
927 uint64_t actual_metadata_size,
928 bool hash_checks_mandatory) {
Alex Deymo8427b4a2014-11-05 14:00:32 -0800929 MockPrefs prefs;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800930 InstallPlan install_plan;
931 install_plan.hash_checks_mandatory = hash_checks_mandatory;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700932 FakeSystemState fake_system_state;
933 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800934 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
935 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
936
937 // Set a valid magic string and version number 1.
938 EXPECT_TRUE(performer.Write("CrAU", 4));
939 uint64_t version = htobe64(1);
940 EXPECT_TRUE(performer.Write(&version, 8));
941
942 install_plan.metadata_size = expected_metadata_size;
David Zeuthena99981f2013-04-29 13:42:47 -0700943 ErrorCode error_code;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800944 // When filling in size in manifest, exclude the size of the 20-byte header.
945 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
946 bool result = performer.Write(&size_in_manifest, 8, &error_code);
947 if (expected_metadata_size == actual_metadata_size ||
948 !hash_checks_mandatory) {
949 EXPECT_TRUE(result);
950 } else {
951 EXPECT_FALSE(result);
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700952 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800953 }
954
955 EXPECT_LT(performer.Close(), 0);
956}
957
958// Generates a valid delta file but tests the delta performer by suppling
959// different metadata signatures as per omaha_metadata_signature flag and
960// sees if the result of the parsing are as per hash_checks_mandatory flag.
961void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
962 SignatureTest signature_test,
963 bool hash_checks_mandatory) {
964 DeltaState state;
965
966 // Using kSignatureNone since it doesn't affect the results of our test.
967 // If we've to use other signature options, then we'd have to get the
968 // metadata size again after adding the signing operation to the manifest.
Allie Woodfdf00512015-03-02 13:34:55 -0800969 GenerateDeltaFile(true, true, false, -1, signature_test, &state,
970 DeltaPerformer::kFullPayloadMinorVersion);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800971
972 ScopedPathUnlinker a_img_unlinker(state.a_img);
973 ScopedPathUnlinker b_img_unlinker(state.b_img);
974 ScopedPathUnlinker delta_unlinker(state.delta_path);
975 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
976 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
977
978 // Loads the payload and parses the manifest.
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800979 chromeos::Blob payload;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800980 EXPECT_TRUE(utils::ReadFile(state.delta_path, &payload));
981 LOG(INFO) << "Payload size: " << payload.size();
982
983 InstallPlan install_plan;
984 install_plan.hash_checks_mandatory = hash_checks_mandatory;
985 install_plan.metadata_size = state.metadata_size;
986
987 DeltaPerformer::MetadataParseResult expected_result, actual_result;
David Zeuthena99981f2013-04-29 13:42:47 -0700988 ErrorCode expected_error, actual_error;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800989
990 // Fill up the metadata signature in install plan according to the test.
991 switch (metadata_signature_test) {
992 case kEmptyMetadataSignature:
993 install_plan.metadata_signature.clear();
994 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700995 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800996 break;
997
998 case kInvalidMetadataSignature:
999 install_plan.metadata_signature = kBogusMetadataSignature1;
1000 expected_result = DeltaPerformer::kMetadataParseError;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001001 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001002 break;
1003
1004 case kValidMetadataSignature:
1005 default:
1006 // Set the install plan's metadata size to be the same as the one
1007 // in the manifest so that we pass the metadata size checks. Only
1008 // then we can get to manifest signature checks.
1009 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
Alex Vakulenko75039d72014-03-25 12:36:28 -07001010 payload.data(),
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001011 state.metadata_size,
1012 kUnittestPrivateKeyPath,
1013 &install_plan.metadata_signature));
1014 EXPECT_FALSE(install_plan.metadata_signature.empty());
1015 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001016 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001017 break;
1018 }
1019
1020 // Ignore the expected result/error if hash checks are not mandatory.
1021 if (!hash_checks_mandatory) {
1022 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001023 expected_error = ErrorCode::kSuccess;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001024 }
1025
1026 // Create the delta performer object.
Alex Deymo8427b4a2014-11-05 14:00:32 -08001027 MockPrefs prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001028 DeltaPerformer delta_performer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001029 &state.fake_system_state,
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001030 &install_plan);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001031
1032 // Use the public key corresponding to the private key used above to
1033 // sign the metadata.
1034 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
1035 delta_performer.set_public_key_path(kUnittestPublicKeyPath);
1036
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001037 // Init actual_error with an invalid value so that we make sure
1038 // ParsePayloadMetadata properly populates it in all cases.
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001039 actual_error = ErrorCode::kUmaReportedMax;
Gilad Arnolddaa27402014-01-23 11:56:17 -08001040 actual_result = delta_performer.ParsePayloadMetadata(payload, &actual_error);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001041
1042 EXPECT_EQ(expected_result, actual_result);
1043 EXPECT_EQ(expected_error, actual_error);
1044
1045 // Check that the parsed metadata size is what's expected. This test
1046 // implicitly confirms that the metadata signature is valid, if required.
Gilad Arnoldfe133932014-01-14 12:25:50 -08001047 EXPECT_EQ(state.metadata_size, delta_performer.GetMetadataSize());
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001048}
1049
1050void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
1051 bool hash_checks_mandatory) {
1052 DeltaState state;
Allie Woodfdf00512015-03-02 13:34:55 -08001053 uint64_t minor_version = DeltaPerformer::kFullPayloadMinorVersion;
1054 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state,
1055 minor_version);
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001056 ScopedPathUnlinker a_img_unlinker(state.a_img);
1057 ScopedPathUnlinker b_img_unlinker(state.b_img);
1058 ScopedPathUnlinker delta_unlinker(state.delta_path);
1059 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
1060 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
Alex Deymo52146ce2014-05-29 11:09:45 -07001061 DeltaPerformer *performer = nullptr;
Allie Woodfdf00512015-03-02 13:34:55 -08001062 ApplyDeltaFile(true, true, false, kSignatureGenerated, &state,
1063 hash_checks_mandatory, op_hash_test, &performer,
1064 minor_version);
Alex Deymo52146ce2014-05-29 11:09:45 -07001065 delete performer;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001066}
1067
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001068TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
Allie Wood56873452015-03-27 17:48:40 -07001069 uint64_t test[] = {1, 1, 4, 2, 0, 1};
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001070 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
1071 const uint64_t block_size = 4096;
Allie Wood56873452015-03-27 17:48:40 -07001072 const uint64_t file_length = 4 * block_size - 13;
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001073
1074 google::protobuf::RepeatedPtrField<Extent> extents;
1075 for (size_t i = 0; i < arraysize(test); i += 2) {
1076 Extent* extent = extents.Add();
1077 extent->set_start_block(test[i]);
1078 extent->set_num_blocks(test[i + 1]);
1079 }
1080
Allie Wood56873452015-03-27 17:48:40 -07001081 string expected_output = "4096:4096,16384:8192,0:4083";
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001082 string actual_output;
1083 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
1084 block_size,
1085 file_length,
1086 &actual_output));
1087 EXPECT_EQ(expected_output, actual_output);
1088}
Darin Petkov68c10d12010-10-14 09:24:37 -07001089
Don Garrettb8dd1d92013-11-22 17:40:02 -08001090TEST(DeltaPerformerTest, ValidateManifestFullGoodTest) {
1091 // The Manifest we are validating.
1092 DeltaArchiveManifest manifest;
1093 manifest.mutable_new_kernel_info();
1094 manifest.mutable_new_rootfs_info();
1095 manifest.set_minor_version(DeltaPerformer::kFullPayloadMinorVersion);
1096
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001097 DeltaPerformerTest::RunManifestValidation(manifest, true,
1098 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001099}
1100
1101TEST(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
1102 // The Manifest we are validating.
1103 DeltaArchiveManifest manifest;
1104 manifest.mutable_old_kernel_info();
1105 manifest.mutable_old_rootfs_info();
1106 manifest.mutable_new_kernel_info();
1107 manifest.mutable_new_rootfs_info();
1108 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1109
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001110 DeltaPerformerTest::RunManifestValidation(manifest, false,
1111 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001112}
1113
1114TEST(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
1115 // The Manifest we are validating.
1116 DeltaArchiveManifest manifest;
1117
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001118 DeltaPerformerTest::RunManifestValidation(manifest, true,
1119 ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001120}
1121
1122TEST(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
1123 // The Manifest we are validating.
1124 DeltaArchiveManifest manifest;
1125
1126 DeltaPerformerTest::RunManifestValidation(
1127 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001128 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001129}
1130
1131TEST(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
1132 // The Manifest we are validating.
1133 DeltaArchiveManifest manifest;
1134 manifest.mutable_old_kernel_info();
1135 manifest.mutable_new_kernel_info();
1136 manifest.mutable_new_rootfs_info();
1137 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1138
1139 DeltaPerformerTest::RunManifestValidation(
1140 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001141 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001142}
1143
1144TEST(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
1145 // The Manifest we are validating.
1146 DeltaArchiveManifest manifest;
1147 manifest.mutable_old_rootfs_info();
1148 manifest.mutable_new_kernel_info();
1149 manifest.mutable_new_rootfs_info();
1150 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
1151
1152 DeltaPerformerTest::RunManifestValidation(
1153 manifest, true,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001154 ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001155}
1156
1157TEST(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
1158 // The Manifest we are validating.
1159 DeltaArchiveManifest manifest;
1160
1161 // Generate a bad version number.
1162 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
1163 10000);
1164
1165 DeltaPerformerTest::RunManifestValidation(
1166 manifest, false,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -07001167 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -08001168}
1169
Darin Petkov68c10d12010-10-14 09:24:37 -07001170TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001171 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001172 false, kInPlaceMinorPayloadVersion);
Darin Petkov8e447e02013-04-16 16:23:50 +02001173}
1174
Don Garrett2ae37872013-10-25 13:33:20 -07001175TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
1176 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
Allie Woodfdf00512015-03-02 13:34:55 -08001177 false, kInPlaceMinorPayloadVersion);
Don Garrett2ae37872013-10-25 13:33:20 -07001178}
1179
1180TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
1181 DeltaState state;
1182 GenerateDeltaFile(false, false, false, -1,
Allie Woodfdf00512015-03-02 13:34:55 -08001183 kSignatureGeneratedPlaceholderMismatch, &state,
1184 kInPlaceMinorPayloadVersion);
Don Garrett2ae37872013-10-25 13:33:20 -07001185}
1186
Darin Petkov8e447e02013-04-16 16:23:50 +02001187TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001188 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001189 false, kInPlaceMinorPayloadVersion);
Darin Petkov68c10d12010-10-14 09:24:37 -07001190}
1191
1192TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001193 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001194 false, kInPlaceMinorPayloadVersion);
Darin Petkov7a22d792010-11-08 14:10:00 -08001195}
1196
1197TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001198 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001199 true, DeltaPerformer::kFullPayloadMinorVersion);
Darin Petkov9fa7ec52010-10-18 11:45:23 -07001200}
1201
1202TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001203 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
Allie Woodfdf00512015-03-02 13:34:55 -08001204 false, kInPlaceMinorPayloadVersion);
Darin Petkov9574f7e2011-01-13 10:48:12 -08001205}
1206
Darin Petkovcbfb0172011-01-14 15:24:45 -08001207TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001208 DoSmallImageTest(false, false, false, -1, kSignatureNone,
Allie Woodfdf00512015-03-02 13:34:55 -08001209 false, kInPlaceMinorPayloadVersion);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001210}
1211
1212TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001213 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
Allie Woodfdf00512015-03-02 13:34:55 -08001214 true, kInPlaceMinorPayloadVersion);
Darin Petkovcbfb0172011-01-14 15:24:45 -08001215}
1216
1217TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001218 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
Allie Woodfdf00512015-03-02 13:34:55 -08001219 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyes27f7d372010-10-07 11:26:07 -07001220}
1221
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001222TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001223 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
Allie Woodfdf00512015-03-02 13:34:55 -08001224 false, kInPlaceMinorPayloadVersion);
Darin Petkov52dcaeb2011-01-14 15:33:06 -08001225}
1226
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001227TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001228 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
Allie Woodfdf00512015-03-02 13:34:55 -08001229 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001230}
1231
1232TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Darin Petkov8e447e02013-04-16 16:23:50 +02001233 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
Allie Woodfdf00512015-03-02 13:34:55 -08001234 false, kInPlaceMinorPayloadVersion);
Andrew de los Reyesc24e3f32011-08-30 15:45:20 -07001235}
1236
Allie Wood9f6f0a52015-03-30 11:25:47 -07001237TEST(DeltaPerformerTest, RunAsRootSmallImageSourceOpsTest) {
1238 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
1239 false, kSourceMinorPayloadVersion);
1240}
1241
Darin Petkov934bb412010-11-18 11:21:35 -08001242TEST(DeltaPerformerTest, BadDeltaMagicTest) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001243 MockPrefs prefs;
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001244 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001245 FakeSystemState fake_system_state;
1246 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Darin Petkov934bb412010-11-18 11:21:35 -08001247 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1248 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
Don Garrette410e0f2011-11-10 15:39:01 -08001249 EXPECT_TRUE(performer.Write("junk", 4));
1250 EXPECT_TRUE(performer.Write("morejunk", 8));
1251 EXPECT_FALSE(performer.Write("morejunk", 8));
Darin Petkov934bb412010-11-18 11:21:35 -08001252 EXPECT_LT(performer.Close(), 0);
1253}
1254
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001255TEST(DeltaPerformerTest, WriteUpdatesPayloadState) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001256 MockPrefs prefs;
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001257 InstallPlan install_plan;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001258 FakeSystemState fake_system_state;
1259 DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001260 EXPECT_EQ(0, performer.Open("/dev/null", 0, 0));
1261 EXPECT_TRUE(performer.OpenKernel("/dev/null"));
1262
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001263 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001264 DownloadProgress(4)).Times(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001265 EXPECT_CALL(*(fake_system_state.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -08001266 DownloadProgress(8)).Times(2);
1267
1268 EXPECT_TRUE(performer.Write("junk", 4));
1269 EXPECT_TRUE(performer.Write("morejunk", 8));
1270 EXPECT_FALSE(performer.Write("morejunk", 8));
1271 EXPECT_LT(performer.Close(), 0);
1272}
1273
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001274TEST(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
1275 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001276}
1277
Jay Srinivasan738fdf32012-12-07 17:40:54 -08001278TEST(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
1279 DoMetadataSizeTest(0, 123456, false);
1280}
1281
1282TEST(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
1283 DoMetadataSizeTest(13000, 140000, true);
1284}
1285
1286TEST(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
1287 DoMetadataSizeTest(40000, 50000, false);
1288}
1289
1290TEST(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
1291 DoMetadataSizeTest(85376, 85376, true);
1292}
1293
1294TEST(DeltaPerformerTest, RunAsRootMandatoryEmptyMetadataSignatureTest) {
1295 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, true);
1296}
1297
1298TEST(DeltaPerformerTest, RunAsRootNonMandatoryEmptyMetadataSignatureTest) {
1299 DoMetadataSignatureTest(kEmptyMetadataSignature, kSignatureGenerated, false);
1300}
1301
1302TEST(DeltaPerformerTest, RunAsRootMandatoryInvalidMetadataSignatureTest) {
1303 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated, true);
1304}
1305
1306TEST(DeltaPerformerTest, RunAsRootNonMandatoryInvalidMetadataSignatureTest) {
1307 DoMetadataSignatureTest(kInvalidMetadataSignature, kSignatureGenerated,
1308 false);
1309}
1310
1311TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature1Test) {
1312 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureNone, true);
1313}
1314
1315TEST(DeltaPerformerTest, RunAsRootMandatoryValidMetadataSignature2Test) {
1316 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, true);
1317}
1318
1319TEST(DeltaPerformerTest, RunAsRootNonMandatoryValidMetadataSignatureTest) {
1320 DoMetadataSignatureTest(kValidMetadataSignature, kSignatureGenerated, false);
1321}
1322
1323TEST(DeltaPerformerTest, RunAsRootMandatoryOperationHashMismatchTest) {
1324 DoOperationHashMismatchTest(kInvalidOperationData, true);
1325}
Jay Srinivasan51dcf262012-09-13 17:24:32 -07001326
David Zeuthene7f89172013-10-31 10:21:04 -07001327TEST(DeltaPerformerTest, UsePublicKeyFromResponse) {
Alex Deymo8427b4a2014-11-05 14:00:32 -08001328 MockPrefs prefs;
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001329 FakeSystemState fake_system_state;
David Zeuthene7f89172013-10-31 10:21:04 -07001330 InstallPlan install_plan;
1331 base::FilePath key_path;
1332
1333 // The result of the GetPublicKeyResponse() method is based on three things
1334 //
1335 // 1. Whether it's an official build; and
1336 // 2. Whether the Public RSA key to be used is in the root filesystem; and
Alex Vakulenko072359c2014-07-18 11:41:07 -07001337 // 3. Whether the response has a public key
David Zeuthene7f89172013-10-31 10:21:04 -07001338 //
1339 // We test all eight combinations to ensure that we only use the
1340 // public key in the response if
1341 //
1342 // a. it's not an official build; and
1343 // b. there is no key in the root filesystem.
1344
1345 DeltaPerformer *performer = new DeltaPerformer(&prefs,
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001346 &fake_system_state,
David Zeuthene7f89172013-10-31 10:21:04 -07001347 &install_plan);
Gilad Arnold5bb4c902014-04-10 12:32:13 -07001348 FakeHardware* fake_hardware = fake_system_state.fake_hardware();
David Zeuthene7f89172013-10-31 10:21:04 -07001349
1350 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -08001351 EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
David Zeuthene7f89172013-10-31 10:21:04 -07001352 &temp_dir));
1353 string non_existing_file = temp_dir + "/non-existing";
1354 string existing_file = temp_dir + "/existing";
Alex Vakulenko75039d72014-03-25 12:36:28 -07001355 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
David Zeuthene7f89172013-10-31 10:21:04 -07001356
1357 // Non-official build, non-existing public-key, key in response -> true
Don Garrett6646b442013-11-13 15:29:11 -08001358 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001359 performer->public_key_path_ = non_existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001360 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001361 EXPECT_TRUE(performer->GetPublicKeyFromResponse(&key_path));
1362 EXPECT_FALSE(key_path.empty());
1363 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
1364 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001365 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001366 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1367
1368 // Non-official build, existing public-key, key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001369 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001370 performer->public_key_path_ = existing_file;
Alex Vakulenkod2779df2014-06-16 13:19:00 -07001371 install_plan.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
David Zeuthene7f89172013-10-31 10:21:04 -07001372 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1373 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001374 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001375 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1376
1377 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001378 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001379 performer->public_key_path_ = non_existing_file;
1380 install_plan.public_key_rsa = "";
1381 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1382 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001383 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001384 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1385
1386 // Non-official build, existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -08001387 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001388 performer->public_key_path_ = existing_file;
1389 install_plan.public_key_rsa = "";
1390 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1391 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -08001392 fake_hardware->SetIsOfficialBuild(true);
David Zeuthene7f89172013-10-31 10:21:04 -07001393 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1394
1395 // Non-official build, non-existing public-key, key in response
1396 // but invalid base64 -> false
Don Garrett6646b442013-11-13 15:29:11 -08001397 fake_hardware->SetIsOfficialBuild(false);
David Zeuthene7f89172013-10-31 10:21:04 -07001398 performer->public_key_path_ = non_existing_file;
1399 install_plan.public_key_rsa = "not-valid-base64";
1400 EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
1401
1402 delete performer;
Alex Deymo10875d92014-11-10 21:52:57 -08001403 EXPECT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
David Zeuthene7f89172013-10-31 10:21:04 -07001404}
1405
Allie Wood78750a42015-02-11 15:42:11 -08001406TEST(DeltaPerformerTest, MinorVersionsMatch) {
1407 // Test that the minor version in update_engine.conf that is installed to
1408 // the image matches the supported delta minor version in the update engine.
1409 uint32_t minor_version;
Alex Deymob42b98d2015-07-06 17:42:38 -07001410 chromeos::KeyValueStore store;
1411 EXPECT_TRUE(store.Load(base::FilePath("update_engine.conf")));
1412 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
1413 EXPECT_EQ(DeltaPerformer::kSupportedMinorPayloadVersion, minor_version);
Allie Wood78750a42015-02-11 15:42:11 -08001414}
1415
Andrew de los Reyes09e56d62010-04-23 13:45:53 -07001416} // namespace chromeos_update_engine