blob: 0912764fa95035a30bc42057c47e8b91d7f7bcab [file] [log] [blame]
Sen Jianga4365d62015-09-25 10:52:25 -07001//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/payload_consumer/delta_performer.h"
Sen Jianga4365d62015-09-25 10:52:25 -070018
19#include <inttypes.h>
20#include <sys/mount.h>
21
22#include <algorithm>
23#include <string>
24#include <vector>
25
26#include <base/files/file_path.h>
27#include <base/files/file_util.h>
Sen Jianga4365d62015-09-25 10:52:25 -070028#include <base/strings/string_util.h>
Alex Deymoe5e5fe92015-10-05 09:28:19 -070029#include <base/strings/stringprintf.h>
Sen Jianga4365d62015-09-25 10:52:25 -070030#include <google/protobuf/repeated_field.h>
31#include <gtest/gtest.h>
Sen Jiang8de733a2016-03-25 13:57:49 -070032#include <openssl/pem.h>
Sen Jianga4365d62015-09-25 10:52:25 -070033
Alex Deymo39910dc2015-11-09 17:04:30 -080034#include "update_engine/common/constants.h"
Alex Deymo542c19b2015-12-03 07:43:31 -030035#include "update_engine/common/fake_boot_control.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080036#include "update_engine/common/fake_hardware.h"
37#include "update_engine/common/mock_prefs.h"
38#include "update_engine/common/test_utils.h"
39#include "update_engine/common/utils.h"
Alex Deymo542c19b2015-12-03 07:43:31 -030040#include "update_engine/payload_consumer/mock_download_action.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080041#include "update_engine/payload_consumer/payload_constants.h"
Sen Jiang44ac3ea2018-10-18 15:10:20 -070042#include "update_engine/payload_consumer/payload_metadata.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080043#include "update_engine/payload_consumer/payload_verifier.h"
Sen Jianga4365d62015-09-25 10:52:25 -070044#include "update_engine/payload_generator/delta_diff_generator.h"
45#include "update_engine/payload_generator/payload_signer.h"
Sen Jianga4365d62015-09-25 10:52:25 -070046#include "update_engine/update_metadata.pb.h"
Sen Jianga4365d62015-09-25 10:52:25 -070047
48namespace chromeos_update_engine {
49
50using std::string;
51using std::vector;
Sen Jiang260f03b2016-03-21 15:34:58 -070052using test_utils::GetBuildArtifactsPath;
Sen Jianga4365d62015-09-25 10:52:25 -070053using test_utils::ScopedLoopMounter;
54using test_utils::System;
Alex Deymoe5e5fe92015-10-05 09:28:19 -070055using test_utils::kRandomString;
56using testing::Return;
57using testing::_;
Sen Jianga4365d62015-09-25 10:52:25 -070058
59extern const char* kUnittestPrivateKeyPath;
60extern const char* kUnittestPublicKeyPath;
61extern const char* kUnittestPrivateKey2Path;
62extern const char* kUnittestPublicKey2Path;
63
Alex Deymo80f70ff2016-02-10 16:08:11 -080064static const uint32_t kDefaultKernelSize = 4096; // Something small for a test
Sen Jianga4365d62015-09-25 10:52:25 -070065static const uint8_t kNewData[] = {'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
66 'n', 'e', 'w', ' ', 'd', 'a', 't', 'a', '.'};
67
68namespace {
69struct DeltaState {
70 string a_img;
71 string b_img;
72 string result_img;
73 size_t image_size;
74
75 string delta_path;
76 uint64_t metadata_size;
77
78 string old_kernel;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070079 brillo::Blob old_kernel_data;
Sen Jianga4365d62015-09-25 10:52:25 -070080
81 string new_kernel;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070082 brillo::Blob new_kernel_data;
Sen Jianga4365d62015-09-25 10:52:25 -070083
84 string result_kernel;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070085 brillo::Blob result_kernel_data;
Sen Jianga4365d62015-09-25 10:52:25 -070086 size_t kernel_size;
87
Alex Deymoe5e5fe92015-10-05 09:28:19 -070088 // The InstallPlan referenced by the DeltaPerformer. This needs to outlive
89 // the DeltaPerformer.
90 InstallPlan install_plan;
91
Sen Jianga4365d62015-09-25 10:52:25 -070092 // The in-memory copy of delta file.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070093 brillo::Blob delta;
Sen Jianga4365d62015-09-25 10:52:25 -070094
Alex Deymo542c19b2015-12-03 07:43:31 -030095 // Mock and fake instances used by the delta performer.
96 FakeBootControl fake_boot_control_;
97 FakeHardware fake_hardware_;
98 MockDownloadActionDelegate mock_delegate_;
Sen Jianga4365d62015-09-25 10:52:25 -070099};
100
101enum SignatureTest {
102 kSignatureNone, // No payload signing.
103 kSignatureGenerator, // Sign the payload at generation time.
104 kSignatureGenerated, // Sign the payload after it's generated.
105 kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
106 kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
107 kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
108 kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
109 kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
110 kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
111};
112
113enum OperationHashTest {
114 kInvalidOperationData,
115 kValidOperationData,
116};
117
118} // namespace
119
Sen Jiangdcaf7972018-05-11 16:03:23 -0700120class DeltaPerformerIntegrationTest : public ::testing::Test {};
Sen Jianga4365d62015-09-25 10:52:25 -0700121
122static void CompareFilesByBlock(const string& a_file, const string& b_file,
123 size_t image_size) {
Alex Deymo80f70ff2016-02-10 16:08:11 -0800124 EXPECT_EQ(0U, image_size % kBlockSize);
Sen Jianga4365d62015-09-25 10:52:25 -0700125
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700126 brillo::Blob a_data, b_data;
Sen Jianga4365d62015-09-25 10:52:25 -0700127 EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
128 EXPECT_TRUE(utils::ReadFile(b_file, &b_data)) << "file failed: " << b_file;
129
130 EXPECT_GE(a_data.size(), image_size);
131 EXPECT_GE(b_data.size(), image_size);
132 for (size_t i = 0; i < image_size; i += kBlockSize) {
Alex Deymo80f70ff2016-02-10 16:08:11 -0800133 EXPECT_EQ(0U, i % kBlockSize);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700134 brillo::Blob a_sub(&a_data[i], &a_data[i + kBlockSize]);
135 brillo::Blob b_sub(&b_data[i], &b_data[i + kBlockSize]);
Sen Jianga4365d62015-09-25 10:52:25 -0700136 EXPECT_TRUE(a_sub == b_sub) << "Block " << (i/kBlockSize) << " differs";
137 }
138 if (::testing::Test::HasNonfatalFailure()) {
139 LOG(INFO) << "Compared filesystems with size " << image_size
140 << ", partition A " << a_file << " size: " << a_data.size()
141 << ", partition B " << b_file << " size: " << b_data.size();
142 }
143}
144
145static bool WriteSparseFile(const string& path, off_t size) {
146 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
147 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
148 ScopedFdCloser fd_closer(&fd);
149 off_t rc = lseek(fd, size + 1, SEEK_SET);
150 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1));
151 int return_code = ftruncate(fd, size);
152 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0);
153 return true;
154}
155
Sen Jiang990c27b2016-03-15 17:09:21 -0700156static bool WriteByteAtOffset(const string& path, off_t offset) {
157 int fd = open(path.c_str(), O_CREAT | O_WRONLY, 0644);
158 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
159 ScopedFdCloser fd_closer(&fd);
160 EXPECT_TRUE(utils::PWriteAll(fd, "\0", 1, offset));
161 return true;
162}
163
Sen Jianga4365d62015-09-25 10:52:25 -0700164static size_t GetSignatureSize(const string& private_key_path) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700165 const brillo::Blob data(1, 'x');
166 brillo::Blob hash;
Alex Deymo39910dc2015-11-09 17:04:30 -0800167 EXPECT_TRUE(HashCalculator::RawHashOfData(data, &hash));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700168 brillo::Blob signature;
Sen Jianga4365d62015-09-25 10:52:25 -0700169 EXPECT_TRUE(PayloadSigner::SignHash(hash,
170 private_key_path,
171 &signature));
172 return signature.size();
173}
174
175static bool InsertSignaturePlaceholder(int signature_size,
176 const string& payload_path,
177 uint64_t* out_metadata_size) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700178 vector<brillo::Blob> signatures;
179 signatures.push_back(brillo::Blob(signature_size, 0));
Sen Jianga4365d62015-09-25 10:52:25 -0700180
181 return PayloadSigner::AddSignatureToPayload(
182 payload_path,
183 signatures,
Sen Jiang644f6182015-10-06 16:45:57 -0700184 {},
Sen Jianga4365d62015-09-25 10:52:25 -0700185 payload_path,
186 out_metadata_size);
187}
188
189static void SignGeneratedPayload(const string& payload_path,
190 uint64_t* out_metadata_size) {
Sen Jiang260f03b2016-03-21 15:34:58 -0700191 string private_key_path = GetBuildArtifactsPath(kUnittestPrivateKeyPath);
192 int signature_size = GetSignatureSize(private_key_path);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700193 brillo::Blob hash;
Sen Jianga4365d62015-09-25 10:52:25 -0700194 ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
Sen Jiang260f03b2016-03-21 15:34:58 -0700195 payload_path, {signature_size}, &hash, nullptr));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700196 brillo::Blob signature;
Sen Jiang260f03b2016-03-21 15:34:58 -0700197 ASSERT_TRUE(PayloadSigner::SignHash(hash, private_key_path, &signature));
Sen Jianga4365d62015-09-25 10:52:25 -0700198 ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
Sen Jiang260f03b2016-03-21 15:34:58 -0700199 payload_path, {signature}, {}, payload_path, out_metadata_size));
Sen Jiangaef1c6f2015-10-07 10:05:32 -0700200 EXPECT_TRUE(PayloadSigner::VerifySignedPayload(
Sen Jiang260f03b2016-03-21 15:34:58 -0700201 payload_path, GetBuildArtifactsPath(kUnittestPublicKeyPath)));
Sen Jianga4365d62015-09-25 10:52:25 -0700202}
203
204static void SignGeneratedShellPayload(SignatureTest signature_test,
205 const string& payload_path) {
Sen Jiang260f03b2016-03-21 15:34:58 -0700206 string private_key_path = GetBuildArtifactsPath(kUnittestPrivateKeyPath);
Sen Jianga4365d62015-09-25 10:52:25 -0700207 if (signature_test == kSignatureGeneratedShellBadKey) {
208 ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX",
209 &private_key_path,
210 nullptr));
211 } else {
212 ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
213 signature_test == kSignatureGeneratedShellRotateCl1 ||
214 signature_test == kSignatureGeneratedShellRotateCl2);
215 }
216 ScopedPathUnlinker key_unlinker(private_key_path);
217 key_unlinker.set_should_remove(signature_test ==
218 kSignatureGeneratedShellBadKey);
219 // Generates a new private key that will not match the public key.
220 if (signature_test == kSignatureGeneratedShellBadKey) {
221 LOG(INFO) << "Generating a mismatched private key.";
Sen Jiang8de733a2016-03-25 13:57:49 -0700222 // The code below executes the equivalent of:
223 // openssl genrsa -out <private_key_path> 2048
224 RSA* rsa = RSA_new();
225 BIGNUM* e = BN_new();
226 EXPECT_EQ(1, BN_set_word(e, RSA_F4));
227 EXPECT_EQ(1, RSA_generate_key_ex(rsa, 2048, e, nullptr));
228 BN_free(e);
229 FILE* fprikey = fopen(private_key_path.c_str(), "w");
230 EXPECT_NE(nullptr, fprikey);
231 EXPECT_EQ(1,
232 PEM_write_RSAPrivateKey(
233 fprikey, rsa, nullptr, nullptr, 0, nullptr, nullptr));
234 fclose(fprikey);
235 RSA_free(rsa);
Sen Jianga4365d62015-09-25 10:52:25 -0700236 }
237 int signature_size = GetSignatureSize(private_key_path);
Sen Jiang0779a152018-07-02 17:34:56 -0700238 test_utils::ScopedTempFile hash_file("hash.XXXXXX");
Sen Jianga4365d62015-09-25 10:52:25 -0700239 string signature_size_string;
240 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
241 signature_test == kSignatureGeneratedShellRotateCl2)
242 signature_size_string = base::StringPrintf("%d:%d",
243 signature_size, signature_size);
244 else
245 signature_size_string = base::StringPrintf("%d", signature_size);
Sen Jiang5a216c12016-03-30 13:08:24 -0700246 string delta_generator_path = GetBuildArtifactsPath("delta_generator");
Sen Jianga4365d62015-09-25 10:52:25 -0700247 ASSERT_EQ(0,
248 System(base::StringPrintf(
Sen Jiang5a216c12016-03-30 13:08:24 -0700249 "%s -in_file=%s -signature_size=%s -out_hash_file=%s",
250 delta_generator_path.c_str(),
Sen Jianga4365d62015-09-25 10:52:25 -0700251 payload_path.c_str(),
252 signature_size_string.c_str(),
Sen Jiang0779a152018-07-02 17:34:56 -0700253 hash_file.path().c_str())));
Sen Jianga4365d62015-09-25 10:52:25 -0700254
Sen Jiang8de733a2016-03-25 13:57:49 -0700255 // Sign the hash
256 brillo::Blob hash, signature;
Sen Jiang0779a152018-07-02 17:34:56 -0700257 ASSERT_TRUE(utils::ReadFile(hash_file.path(), &hash));
Sen Jiang8de733a2016-03-25 13:57:49 -0700258 ASSERT_TRUE(PayloadSigner::SignHash(hash, private_key_path, &signature));
Sen Jianga4365d62015-09-25 10:52:25 -0700259
Sen Jiang0779a152018-07-02 17:34:56 -0700260 test_utils::ScopedTempFile sig_file("signature.XXXXXX");
261 ASSERT_TRUE(test_utils::WriteFileVector(sig_file.path(), signature));
262 string sig_files = sig_file.path();
Sen Jiang8de733a2016-03-25 13:57:49 -0700263
Sen Jiang0779a152018-07-02 17:34:56 -0700264 test_utils::ScopedTempFile sig_file2("signature.XXXXXX");
Sen Jianga4365d62015-09-25 10:52:25 -0700265 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
266 signature_test == kSignatureGeneratedShellRotateCl2) {
Sen Jiang8de733a2016-03-25 13:57:49 -0700267 ASSERT_TRUE(PayloadSigner::SignHash(
268 hash, GetBuildArtifactsPath(kUnittestPrivateKey2Path), &signature));
Sen Jiang0779a152018-07-02 17:34:56 -0700269 ASSERT_TRUE(test_utils::WriteFileVector(sig_file2.path(), signature));
Sen Jianga4365d62015-09-25 10:52:25 -0700270 // Append second sig file to first path
Sen Jiang0779a152018-07-02 17:34:56 -0700271 sig_files += ":" + sig_file2.path();
Sen Jianga4365d62015-09-25 10:52:25 -0700272 }
273
274 ASSERT_EQ(0,
275 System(base::StringPrintf(
Amin Hassanib4778292018-05-21 11:48:15 -0700276 "%s -in_file=%s -payload_signature_file=%s -out_file=%s",
Sen Jiang5a216c12016-03-30 13:08:24 -0700277 delta_generator_path.c_str(),
Sen Jianga4365d62015-09-25 10:52:25 -0700278 payload_path.c_str(),
Sen Jiang0779a152018-07-02 17:34:56 -0700279 sig_files.c_str(),
Sen Jianga4365d62015-09-25 10:52:25 -0700280 payload_path.c_str())));
Sen Jiang260f03b2016-03-21 15:34:58 -0700281 int verify_result = System(base::StringPrintf(
Sen Jiang5a216c12016-03-30 13:08:24 -0700282 "%s -in_file=%s -public_key=%s -public_key_version=%d",
283 delta_generator_path.c_str(),
Sen Jiang260f03b2016-03-21 15:34:58 -0700284 payload_path.c_str(),
285 (signature_test == kSignatureGeneratedShellRotateCl2
286 ? GetBuildArtifactsPath(kUnittestPublicKey2Path)
287 : GetBuildArtifactsPath(kUnittestPublicKeyPath))
288 .c_str(),
289 signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
Sen Jianga4365d62015-09-25 10:52:25 -0700290 if (signature_test == kSignatureGeneratedShellBadKey) {
291 ASSERT_NE(0, verify_result);
292 } else {
293 ASSERT_EQ(0, verify_result);
294 }
295}
296
297static void GenerateDeltaFile(bool full_kernel,
298 bool full_rootfs,
299 bool noop,
300 ssize_t chunk_size,
301 SignatureTest signature_test,
302 DeltaState *state,
303 uint32_t minor_version) {
304 EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
305 EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
306
307 // result_img is used in minor version 2. Instead of applying the update
308 // in-place on A, we apply it to a new image, result_img.
309 EXPECT_TRUE(
310 utils::MakeTempFile("result_img.XXXXXX", &state->result_img, nullptr));
Sen Jiang990c27b2016-03-15 17:09:21 -0700311
Sen Jiang260f03b2016-03-21 15:34:58 -0700312 EXPECT_TRUE(
313 base::CopyFile(GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"),
314 base::FilePath(state->a_img)));
Sen Jianga4365d62015-09-25 10:52:25 -0700315
316 state->image_size = utils::FileSize(state->a_img);
317
Sen Jianga4365d62015-09-25 10:52:25 -0700318 // Create ImageInfo A & B
319 ImageInfo old_image_info;
320 ImageInfo new_image_info;
321
322 if (!full_rootfs) {
323 old_image_info.set_channel("src-channel");
324 old_image_info.set_board("src-board");
325 old_image_info.set_version("src-version");
326 old_image_info.set_key("src-key");
327 old_image_info.set_build_channel("src-build-channel");
328 old_image_info.set_build_version("src-build-version");
329 }
330
331 new_image_info.set_channel("test-channel");
332 new_image_info.set_board("test-board");
333 new_image_info.set_version("test-version");
334 new_image_info.set_key("test-key");
335 new_image_info.set_build_channel("test-build-channel");
336 new_image_info.set_build_version("test-build-version");
337
338 // Make some changes to the A image.
339 {
340 string a_mnt;
341 ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
342
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700343 brillo::Blob hardtocompress;
Sen Jianga4365d62015-09-25 10:52:25 -0700344 while (hardtocompress.size() < 3 * kBlockSize) {
345 hardtocompress.insert(hardtocompress.end(),
346 std::begin(kRandomString), std::end(kRandomString));
347 }
348 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
349 a_mnt.c_str()).c_str(),
350 hardtocompress.data(),
351 hardtocompress.size()));
352
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700353 brillo::Blob zeros(16 * 1024, 0);
Alex Deymo80f70ff2016-02-10 16:08:11 -0800354 EXPECT_EQ(static_cast<int>(zeros.size()),
Sen Jianga4365d62015-09-25 10:52:25 -0700355 base::WriteFile(base::FilePath(base::StringPrintf(
356 "%s/move-to-sparse", a_mnt.c_str())),
357 reinterpret_cast<const char*>(zeros.data()),
358 zeros.size()));
359
360 EXPECT_TRUE(
361 WriteSparseFile(base::StringPrintf("%s/move-from-sparse",
362 a_mnt.c_str()), 16 * 1024));
363
Sen Jiang990c27b2016-03-15 17:09:21 -0700364 EXPECT_TRUE(WriteByteAtOffset(
365 base::StringPrintf("%s/move-semi-sparse", a_mnt.c_str()), 4096));
Sen Jianga4365d62015-09-25 10:52:25 -0700366
367 // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
368 // patch fails to zero out the final block.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700369 brillo::Blob ones(1024 * 1024, 0xff);
Sen Jianga4365d62015-09-25 10:52:25 -0700370 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/ones",
371 a_mnt.c_str()).c_str(),
372 ones.data(),
373 ones.size()));
374 }
375
376 if (noop) {
377 EXPECT_TRUE(base::CopyFile(base::FilePath(state->a_img),
378 base::FilePath(state->b_img)));
379 old_image_info = new_image_info;
380 } else {
381 if (minor_version == kSourceMinorPayloadVersion) {
Sen Jiangf2af4c62015-09-30 16:38:09 -0700382 // Create a result image with image_size bytes of garbage.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700383 brillo::Blob ones(state->image_size, 0xff);
Sen Jianga4365d62015-09-25 10:52:25 -0700384 EXPECT_TRUE(utils::WriteFile(state->result_img.c_str(),
385 ones.data(),
386 ones.size()));
387 EXPECT_EQ(utils::FileSize(state->a_img),
388 utils::FileSize(state->result_img));
389 }
390
Sen Jiang260f03b2016-03-21 15:34:58 -0700391 EXPECT_TRUE(
392 base::CopyFile(GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"),
393 base::FilePath(state->b_img)));
Sen Jianga4365d62015-09-25 10:52:25 -0700394
395 // Make some changes to the B image.
396 string b_mnt;
397 ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
Sen Jiang990c27b2016-03-15 17:09:21 -0700398 base::FilePath mnt_path(b_mnt);
Sen Jianga4365d62015-09-25 10:52:25 -0700399
Sen Jiang990c27b2016-03-15 17:09:21 -0700400 EXPECT_TRUE(base::CopyFile(mnt_path.Append("regular-small"),
401 mnt_path.Append("regular-small2")));
402 EXPECT_TRUE(base::DeleteFile(mnt_path.Append("regular-small"), false));
403 EXPECT_TRUE(base::Move(mnt_path.Append("regular-small2"),
404 mnt_path.Append("regular-small")));
405 EXPECT_TRUE(
406 test_utils::WriteFileString(mnt_path.Append("foo").value(), "foo"));
407 EXPECT_EQ(0, base::WriteFile(mnt_path.Append("emptyfile"), "", 0));
Sen Jianga4365d62015-09-25 10:52:25 -0700408
409 EXPECT_TRUE(
Sen Jiang990c27b2016-03-15 17:09:21 -0700410 WriteSparseFile(mnt_path.Append("fullsparse").value(), 1024 * 1024));
411 EXPECT_TRUE(
412 WriteSparseFile(mnt_path.Append("move-to-sparse").value(), 16 * 1024));
Sen Jianga4365d62015-09-25 10:52:25 -0700413
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700414 brillo::Blob zeros(16 * 1024, 0);
Alex Deymo80f70ff2016-02-10 16:08:11 -0800415 EXPECT_EQ(static_cast<int>(zeros.size()),
Sen Jiang990c27b2016-03-15 17:09:21 -0700416 base::WriteFile(mnt_path.Append("move-from-sparse"),
Sen Jianga4365d62015-09-25 10:52:25 -0700417 reinterpret_cast<const char*>(zeros.data()),
418 zeros.size()));
419
Sen Jiang990c27b2016-03-15 17:09:21 -0700420 EXPECT_TRUE(
421 WriteByteAtOffset(mnt_path.Append("move-semi-sparse").value(), 4096));
422 EXPECT_TRUE(WriteByteAtOffset(mnt_path.Append("partsparse").value(), 4096));
Sen Jianga4365d62015-09-25 10:52:25 -0700423
Sen Jiang990c27b2016-03-15 17:09:21 -0700424 EXPECT_TRUE(
425 base::CopyFile(mnt_path.Append("regular-16k"), mnt_path.Append("tmp")));
426 EXPECT_TRUE(base::Move(mnt_path.Append("tmp"),
427 mnt_path.Append("link-hard-regular-16k")));
428
429 EXPECT_TRUE(base::DeleteFile(mnt_path.Append("link-short_symlink"), false));
430 EXPECT_TRUE(test_utils::WriteFileString(
431 mnt_path.Append("link-short_symlink").value(), "foobar"));
Sen Jianga4365d62015-09-25 10:52:25 -0700432
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700433 brillo::Blob hardtocompress;
Sen Jianga4365d62015-09-25 10:52:25 -0700434 while (hardtocompress.size() < 3 * kBlockSize) {
435 hardtocompress.insert(hardtocompress.end(),
436 std::begin(kRandomString), std::end(kRandomString));
437 }
438 EXPECT_TRUE(utils::WriteFile(base::StringPrintf("%s/hardtocompress",
439 b_mnt.c_str()).c_str(),
440 hardtocompress.data(),
441 hardtocompress.size()));
442 }
443
444 string old_kernel;
445 EXPECT_TRUE(utils::MakeTempFile("old_kernel.XXXXXX",
446 &state->old_kernel,
447 nullptr));
448
449 string new_kernel;
450 EXPECT_TRUE(utils::MakeTempFile("new_kernel.XXXXXX",
451 &state->new_kernel,
452 nullptr));
453
454 string result_kernel;
455 EXPECT_TRUE(utils::MakeTempFile("result_kernel.XXXXXX",
456 &state->result_kernel,
457 nullptr));
458
459 state->kernel_size = kDefaultKernelSize;
460 state->old_kernel_data.resize(kDefaultKernelSize);
461 state->new_kernel_data.resize(state->old_kernel_data.size());
462 state->result_kernel_data.resize(state->old_kernel_data.size());
463 test_utils::FillWithData(&state->old_kernel_data);
464 test_utils::FillWithData(&state->new_kernel_data);
465 test_utils::FillWithData(&state->result_kernel_data);
466
467 // change the new kernel data
468 std::copy(std::begin(kNewData), std::end(kNewData),
469 state->new_kernel_data.begin());
470
471 if (noop) {
472 state->old_kernel_data = state->new_kernel_data;
473 }
474
475 // Write kernels to disk
476 EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
477 state->old_kernel_data.data(),
478 state->old_kernel_data.size()));
479 EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
480 state->new_kernel_data.data(),
481 state->new_kernel_data.size()));
482 EXPECT_TRUE(utils::WriteFile(state->result_kernel.c_str(),
483 state->result_kernel_data.data(),
484 state->result_kernel_data.size()));
485
486 EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX",
487 &state->delta_path,
488 nullptr));
489 LOG(INFO) << "delta path: " << state->delta_path;
490 {
491 const string private_key =
Sen Jiang260f03b2016-03-21 15:34:58 -0700492 signature_test == kSignatureGenerator
493 ? GetBuildArtifactsPath(kUnittestPrivateKeyPath)
494 : "";
Sen Jianga4365d62015-09-25 10:52:25 -0700495
496 PayloadGenerationConfig payload_config;
497 payload_config.is_delta = !full_rootfs;
498 payload_config.hard_chunk_size = chunk_size;
499 payload_config.rootfs_partition_size = kRootFSPartitionSize;
Alex Deymoa4073ef2016-03-22 23:40:53 -0700500 payload_config.version.major = kChromeOSMajorPayloadVersion;
501 payload_config.version.minor = minor_version;
Sen Jianga4365d62015-09-25 10:52:25 -0700502 if (!full_rootfs) {
Tudor Brindusdda79e22018-06-28 18:03:21 -0700503 payload_config.source.partitions.emplace_back(kPartitionNameRoot);
504 payload_config.source.partitions.emplace_back(kPartitionNameKernel);
Sen Jiang981eb112015-08-25 17:03:18 -0700505 payload_config.source.partitions.front().path = state->a_img;
Sen Jianga4365d62015-09-25 10:52:25 -0700506 if (!full_kernel)
Sen Jiang981eb112015-08-25 17:03:18 -0700507 payload_config.source.partitions.back().path = state->old_kernel;
Sen Jianga4365d62015-09-25 10:52:25 -0700508 payload_config.source.image_info = old_image_info;
509 EXPECT_TRUE(payload_config.source.LoadImageSize());
Sen Jiang981eb112015-08-25 17:03:18 -0700510 for (PartitionConfig& part : payload_config.source.partitions)
511 EXPECT_TRUE(part.OpenFilesystem());
Sen Jianga4365d62015-09-25 10:52:25 -0700512 } else {
513 if (payload_config.hard_chunk_size == -1)
514 // Use 1 MiB chunk size for the full unittests.
515 payload_config.hard_chunk_size = 1024 * 1024;
516 }
Tudor Brindusdda79e22018-06-28 18:03:21 -0700517 payload_config.target.partitions.emplace_back(kPartitionNameRoot);
Sen Jiang981eb112015-08-25 17:03:18 -0700518 payload_config.target.partitions.back().path = state->b_img;
Tudor Brindusdda79e22018-06-28 18:03:21 -0700519 payload_config.target.partitions.emplace_back(kPartitionNameKernel);
Sen Jiang981eb112015-08-25 17:03:18 -0700520 payload_config.target.partitions.back().path = state->new_kernel;
Sen Jianga4365d62015-09-25 10:52:25 -0700521 payload_config.target.image_info = new_image_info;
522 EXPECT_TRUE(payload_config.target.LoadImageSize());
Sen Jiang981eb112015-08-25 17:03:18 -0700523 for (PartitionConfig& part : payload_config.target.partitions)
524 EXPECT_TRUE(part.OpenFilesystem());
Sen Jianga4365d62015-09-25 10:52:25 -0700525
526 EXPECT_TRUE(payload_config.Validate());
527 EXPECT_TRUE(
528 GenerateUpdatePayloadFile(
529 payload_config,
530 state->delta_path,
531 private_key,
532 &state->metadata_size));
533 }
Sen Jiangf2af4c62015-09-30 16:38:09 -0700534 // Extend the "partitions" holding the file system a bit.
535 EXPECT_EQ(0, HANDLE_EINTR(truncate(state->a_img.c_str(),
536 state->image_size + 1024 * 1024)));
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800537 EXPECT_EQ(static_cast<off_t>(state->image_size + 1024 * 1024),
538 utils::FileSize(state->a_img));
Sen Jiangf2af4c62015-09-30 16:38:09 -0700539 EXPECT_EQ(0, HANDLE_EINTR(truncate(state->b_img.c_str(),
540 state->image_size + 1024 * 1024)));
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800541 EXPECT_EQ(static_cast<off_t>(state->image_size + 1024 * 1024),
542 utils::FileSize(state->b_img));
Sen Jianga4365d62015-09-25 10:52:25 -0700543
544 if (signature_test == kSignatureGeneratedPlaceholder ||
545 signature_test == kSignatureGeneratedPlaceholderMismatch) {
Sen Jiang260f03b2016-03-21 15:34:58 -0700546 int signature_size =
547 GetSignatureSize(GetBuildArtifactsPath(kUnittestPrivateKeyPath));
Sen Jianga4365d62015-09-25 10:52:25 -0700548 LOG(INFO) << "Inserting placeholder signature.";
549 ASSERT_TRUE(InsertSignaturePlaceholder(signature_size, state->delta_path,
550 &state->metadata_size));
551
552 if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
553 signature_size -= 1;
554 LOG(INFO) << "Inserting mismatched placeholder signature.";
555 ASSERT_FALSE(InsertSignaturePlaceholder(signature_size, state->delta_path,
556 &state->metadata_size));
557 return;
558 }
559 }
560
561 if (signature_test == kSignatureGenerated ||
562 signature_test == kSignatureGeneratedPlaceholder ||
563 signature_test == kSignatureGeneratedPlaceholderMismatch) {
564 // Generate the signed payload and update the metadata size in state to
565 // reflect the new size after adding the signature operation to the
566 // manifest.
567 LOG(INFO) << "Signing payload.";
568 SignGeneratedPayload(state->delta_path, &state->metadata_size);
569 } else if (signature_test == kSignatureGeneratedShell ||
570 signature_test == kSignatureGeneratedShellBadKey ||
571 signature_test == kSignatureGeneratedShellRotateCl1 ||
572 signature_test == kSignatureGeneratedShellRotateCl2) {
573 SignGeneratedShellPayload(signature_test, state->delta_path);
574 }
575}
576
577static void ApplyDeltaFile(bool full_kernel, bool full_rootfs, bool noop,
578 SignatureTest signature_test, DeltaState* state,
579 bool hash_checks_mandatory,
580 OperationHashTest op_hash_test,
581 DeltaPerformer** performer,
582 uint32_t minor_version) {
583 // Check the metadata.
584 {
Alex Deymo98e691c2016-02-04 21:05:45 -0800585 EXPECT_TRUE(utils::ReadFile(state->delta_path, &state->delta));
Sen Jiang44ac3ea2018-10-18 15:10:20 -0700586 PayloadMetadata payload_metadata;
587 EXPECT_TRUE(payload_metadata.ParsePayloadHeader(state->delta));
588 state->metadata_size = payload_metadata.GetMetadataSize();
589 LOG(INFO) << "Metadata size: " << state->metadata_size;
Sen Jianga4365d62015-09-25 10:52:25 -0700590
Sen Jiang44ac3ea2018-10-18 15:10:20 -0700591 DeltaArchiveManifest manifest;
592 EXPECT_TRUE(payload_metadata.GetManifest(state->delta, &manifest));
Sen Jianga4365d62015-09-25 10:52:25 -0700593 if (signature_test == kSignatureNone) {
594 EXPECT_FALSE(manifest.has_signatures_offset());
595 EXPECT_FALSE(manifest.has_signatures_size());
596 } else {
597 EXPECT_TRUE(manifest.has_signatures_offset());
598 EXPECT_TRUE(manifest.has_signatures_size());
599 Signatures sigs_message;
600 EXPECT_TRUE(sigs_message.ParseFromArray(
601 &state->delta[state->metadata_size + manifest.signatures_offset()],
602 manifest.signatures_size()));
603 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
604 signature_test == kSignatureGeneratedShellRotateCl2)
605 EXPECT_EQ(2, sigs_message.signatures_size());
606 else
607 EXPECT_EQ(1, sigs_message.signatures_size());
608 const Signatures_Signature& signature = sigs_message.signatures(0);
Alex Deymo80f70ff2016-02-10 16:08:11 -0800609 EXPECT_EQ(1U, signature.version());
Sen Jianga4365d62015-09-25 10:52:25 -0700610
611 uint64_t expected_sig_data_length = 0;
Sen Jiang260f03b2016-03-21 15:34:58 -0700612 vector<string> key_paths{GetBuildArtifactsPath(kUnittestPrivateKeyPath)};
Sen Jianga4365d62015-09-25 10:52:25 -0700613 if (signature_test == kSignatureGeneratedShellRotateCl1 ||
614 signature_test == kSignatureGeneratedShellRotateCl2) {
Sen Jiang260f03b2016-03-21 15:34:58 -0700615 key_paths.push_back(GetBuildArtifactsPath(kUnittestPrivateKey2Path));
Sen Jianga4365d62015-09-25 10:52:25 -0700616 }
617 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
618 key_paths,
619 &expected_sig_data_length));
620 EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
621 EXPECT_FALSE(signature.data().empty());
622 }
623
624 if (noop) {
625 EXPECT_EQ(0, manifest.install_operations_size());
626 EXPECT_EQ(1, manifest.kernel_install_operations_size());
627 }
628
629 if (full_kernel) {
630 EXPECT_FALSE(manifest.has_old_kernel_info());
631 } else {
632 EXPECT_EQ(state->old_kernel_data.size(),
633 manifest.old_kernel_info().size());
634 EXPECT_FALSE(manifest.old_kernel_info().hash().empty());
635 }
636
637 EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
638 EXPECT_EQ(manifest.new_image_info().board(), "test-board");
639 EXPECT_EQ(manifest.new_image_info().version(), "test-version");
640 EXPECT_EQ(manifest.new_image_info().key(), "test-key");
641 EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
642 EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
643
644 if (!full_rootfs) {
645 if (noop) {
646 EXPECT_EQ(manifest.old_image_info().channel(), "test-channel");
647 EXPECT_EQ(manifest.old_image_info().board(), "test-board");
648 EXPECT_EQ(manifest.old_image_info().version(), "test-version");
649 EXPECT_EQ(manifest.old_image_info().key(), "test-key");
650 EXPECT_EQ(manifest.old_image_info().build_channel(),
651 "test-build-channel");
652 EXPECT_EQ(manifest.old_image_info().build_version(),
653 "test-build-version");
654 } else {
655 EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
656 EXPECT_EQ(manifest.old_image_info().board(), "src-board");
657 EXPECT_EQ(manifest.old_image_info().version(), "src-version");
658 EXPECT_EQ(manifest.old_image_info().key(), "src-key");
659 EXPECT_EQ(manifest.old_image_info().build_channel(),
660 "src-build-channel");
661 EXPECT_EQ(manifest.old_image_info().build_version(),
662 "src-build-version");
663 }
664 }
665
666
667 if (full_rootfs) {
668 EXPECT_FALSE(manifest.has_old_rootfs_info());
669 EXPECT_FALSE(manifest.has_old_image_info());
670 EXPECT_TRUE(manifest.has_new_image_info());
671 } else {
672 EXPECT_EQ(state->image_size, manifest.old_rootfs_info().size());
673 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty());
674 }
675
676 EXPECT_EQ(state->new_kernel_data.size(), manifest.new_kernel_info().size());
677 EXPECT_EQ(state->image_size, manifest.new_rootfs_info().size());
678
679 EXPECT_FALSE(manifest.new_kernel_info().hash().empty());
680 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty());
681 }
682
683 MockPrefs prefs;
684 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
685 state->metadata_size)).WillOnce(Return(true));
Alex Deymof25eb492016-02-26 00:20:08 -0800686 EXPECT_CALL(prefs, SetInt64(kPrefsManifestSignatureSize, 0))
687 .WillOnce(Return(true));
Sen Jianga4365d62015-09-25 10:52:25 -0700688 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
689 .WillRepeatedly(Return(true));
690 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _))
691 .WillOnce(Return(false));
692 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
693 .WillRepeatedly(Return(true));
694 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataLength, _))
695 .WillRepeatedly(Return(true));
696 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSHA256Context, _))
697 .WillRepeatedly(Return(true));
Sen Jiang35f358b2015-11-05 10:46:32 -0800698 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
699 .WillRepeatedly(Return(true));
Tao Bao3406c772019-01-02 15:34:35 -0800700 EXPECT_CALL(prefs, SetBoolean(kPrefsDynamicPartitionMetadataUpdated, _))
Yifan Hong28e89702018-12-05 03:28:47 +0000701 .WillRepeatedly(Return(true));
Sen Jianga4365d62015-09-25 10:52:25 -0700702 if (op_hash_test == kValidOperationData && signature_test != kSignatureNone) {
Sen Jianga4365d62015-09-25 10:52:25 -0700703 EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
704 .WillOnce(Return(true));
705 }
706
Alex Deymo542c19b2015-12-03 07:43:31 -0300707 EXPECT_CALL(state->mock_delegate_, ShouldCancel(_))
708 .WillRepeatedly(Return(false));
709
Sen Jianga4365d62015-09-25 10:52:25 -0700710 // Update the A image in place.
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700711 InstallPlan* install_plan = &state->install_plan;
712 install_plan->hash_checks_mandatory = hash_checks_mandatory;
Sen Jiangcdd52062017-05-18 15:33:10 -0700713 install_plan->payloads = {{.metadata_size = state->metadata_size,
714 .type = (full_kernel && full_rootfs)
715 ? InstallPayloadType::kFull
716 : InstallPayloadType::kDelta}};
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700717 install_plan->source_slot = 0;
718 install_plan->target_slot = 1;
719
720 InstallPlan::Partition root_part;
Tudor Brindusdda79e22018-06-28 18:03:21 -0700721 root_part.name = kPartitionNameRoot;
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700722
723 InstallPlan::Partition kernel_part;
Tudor Brindusdda79e22018-06-28 18:03:21 -0700724 kernel_part.name = kPartitionNameKernel;
Sen Jianga4365d62015-09-25 10:52:25 -0700725
726 LOG(INFO) << "Setting payload metadata size in Omaha = "
727 << state->metadata_size;
728 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
729 state->delta.data(),
730 state->metadata_size,
Sen Jiang260f03b2016-03-21 15:34:58 -0700731 GetBuildArtifactsPath(kUnittestPrivateKeyPath),
Sen Jiang0affc2c2017-02-10 15:55:05 -0800732 &install_plan->payloads[0].metadata_signature));
733 EXPECT_FALSE(install_plan->payloads[0].metadata_signature.empty());
Sen Jianga4365d62015-09-25 10:52:25 -0700734
735 *performer = new DeltaPerformer(&prefs,
Alex Deymo542c19b2015-12-03 07:43:31 -0300736 &state->fake_boot_control_,
737 &state->fake_hardware_,
738 &state->mock_delegate_,
Sen Jiang0affc2c2017-02-10 15:55:05 -0800739 install_plan,
Sen Jiang18414082018-01-11 14:50:36 -0800740 &install_plan->payloads[0],
Amin Hassanied37d682018-04-06 13:22:00 -0700741 false /* interactive */);
Sen Jiang260f03b2016-03-21 15:34:58 -0700742 string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath);
743 EXPECT_TRUE(utils::FileExists(public_key_path.c_str()));
744 (*performer)->set_public_key_path(public_key_path);
Sen Jianga4365d62015-09-25 10:52:25 -0700745
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800746 EXPECT_EQ(static_cast<off_t>(state->image_size),
Alex Deymo39910dc2015-11-09 17:04:30 -0800747 HashCalculator::RawHashOfFile(
Sen Jianga4365d62015-09-25 10:52:25 -0700748 state->a_img,
749 state->image_size,
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700750 &root_part.source_hash));
Alex Deymo39910dc2015-11-09 17:04:30 -0800751 EXPECT_TRUE(HashCalculator::RawHashOfData(
Sen Jianga4365d62015-09-25 10:52:25 -0700752 state->old_kernel_data,
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700753 &kernel_part.source_hash));
754
Sen Jiangd2ff2a02017-04-06 14:53:31 -0700755 // The partitions should be empty before DeltaPerformer.
756 install_plan->partitions.clear();
Sen Jianga4365d62015-09-25 10:52:25 -0700757
758 // With minor version 2, we want the target to be the new image, result_img,
759 // but with version 1, we want to update A in place.
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700760 string target_root, target_kernel;
Sen Jianga4365d62015-09-25 10:52:25 -0700761 if (minor_version == kSourceMinorPayloadVersion) {
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700762 target_root = state->result_img;
763 target_kernel = state->result_kernel;
Sen Jianga4365d62015-09-25 10:52:25 -0700764 } else {
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700765 target_root = state->a_img;
766 target_kernel = state->old_kernel;
Sen Jianga4365d62015-09-25 10:52:25 -0700767 }
768
Alex Deymo542c19b2015-12-03 07:43:31 -0300769 state->fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700770 kPartitionNameRoot, install_plan->source_slot, state->a_img);
Alex Deymo542c19b2015-12-03 07:43:31 -0300771 state->fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700772 kPartitionNameKernel, install_plan->source_slot, state->old_kernel);
Alex Deymo542c19b2015-12-03 07:43:31 -0300773 state->fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700774 kPartitionNameRoot, install_plan->target_slot, target_root);
Alex Deymo542c19b2015-12-03 07:43:31 -0300775 state->fake_boot_control_.SetPartitionDevice(
Tudor Brindusdda79e22018-06-28 18:03:21 -0700776 kPartitionNameKernel, install_plan->target_slot, target_kernel);
Sen Jianga4365d62015-09-25 10:52:25 -0700777
778 ErrorCode expected_error, actual_error;
779 bool continue_writing;
780 switch (op_hash_test) {
781 case kInvalidOperationData: {
782 // Muck with some random offset post the metadata size so that
783 // some operation hash will result in a mismatch.
784 int some_offset = state->metadata_size + 300;
785 LOG(INFO) << "Tampered value at offset: " << some_offset;
786 state->delta[some_offset]++;
787 expected_error = ErrorCode::kDownloadOperationHashMismatch;
788 continue_writing = false;
789 break;
790 }
791
792 case kValidOperationData:
793 default:
794 // no change.
795 expected_error = ErrorCode::kSuccess;
796 continue_writing = true;
797 break;
798 }
799
800 // Write at some number of bytes per operation. Arbitrarily chose 5.
801 const size_t kBytesPerWrite = 5;
802 for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
803 size_t count = std::min(state->delta.size() - i, kBytesPerWrite);
804 bool write_succeeded = ((*performer)->Write(&state->delta[i],
805 count,
806 &actual_error));
807 // Normally write_succeeded should be true every time and
808 // actual_error should be ErrorCode::kSuccess. If so, continue the loop.
809 // But if we seeded an operation hash error above, then write_succeeded
810 // will be false. The failure may happen at any operation n. So, all
811 // Writes until n-1 should succeed and the nth operation will fail with
812 // actual_error. In this case, we should bail out of the loop because
813 // we cannot proceed applying the delta.
814 if (!write_succeeded) {
815 LOG(INFO) << "Write failed. Checking if it failed with expected error";
816 EXPECT_EQ(expected_error, actual_error);
817 if (!continue_writing) {
818 LOG(INFO) << "Cannot continue writing. Bailing out.";
819 break;
820 }
821 }
822
823 EXPECT_EQ(ErrorCode::kSuccess, actual_error);
824 }
825
826 // If we had continued all the way through, Close should succeed.
827 // Otherwise, it should fail. Check appropriately.
828 bool close_result = (*performer)->Close();
829 if (continue_writing)
830 EXPECT_EQ(0, close_result);
831 else
832 EXPECT_LE(0, close_result);
833}
834
835void VerifyPayloadResult(DeltaPerformer* performer,
836 DeltaState* state,
837 ErrorCode expected_result,
838 uint32_t minor_version) {
839 if (!performer) {
840 EXPECT_TRUE(!"Skipping payload verification since performer is null.");
841 return;
842 }
843
Sen Jiang2703ef42017-03-16 13:36:21 -0700844 LOG(INFO) << "Verifying payload for expected result " << expected_result;
845 brillo::Blob expected_hash;
846 HashCalculator::RawHashOfData(state->delta, &expected_hash);
847 EXPECT_EQ(expected_result,
848 performer->VerifyPayload(expected_hash, state->delta.size()));
Sen Jianga4365d62015-09-25 10:52:25 -0700849 LOG(INFO) << "Verified payload.";
850
851 if (expected_result != ErrorCode::kSuccess) {
852 // no need to verify new partition if VerifyPayload failed.
853 return;
854 }
855
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700856 brillo::Blob updated_kernel_partition;
Sen Jianga4365d62015-09-25 10:52:25 -0700857 if (minor_version == kSourceMinorPayloadVersion) {
858 CompareFilesByBlock(state->result_kernel, state->new_kernel,
859 state->kernel_size);
860 CompareFilesByBlock(state->result_img, state->b_img,
861 state->image_size);
862 EXPECT_TRUE(utils::ReadFile(state->result_kernel,
863 &updated_kernel_partition));
864 } else {
865 CompareFilesByBlock(state->old_kernel, state->new_kernel,
866 state->kernel_size);
867 CompareFilesByBlock(state->a_img, state->b_img,
868 state->image_size);
869 EXPECT_TRUE(utils::ReadFile(state->old_kernel, &updated_kernel_partition));
870 }
871
872 ASSERT_GE(updated_kernel_partition.size(), arraysize(kNewData));
873 EXPECT_TRUE(std::equal(std::begin(kNewData), std::end(kNewData),
874 updated_kernel_partition.begin()));
875
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700876 const auto& partitions = state->install_plan.partitions;
Alex Deymo80f70ff2016-02-10 16:08:11 -0800877 EXPECT_EQ(2U, partitions.size());
Tudor Brindusdda79e22018-06-28 18:03:21 -0700878 EXPECT_EQ(kPartitionNameRoot, partitions[0].name);
879 EXPECT_EQ(kPartitionNameKernel, partitions[1].name);
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700880
881 EXPECT_EQ(kDefaultKernelSize, partitions[1].target_size);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700882 brillo::Blob expected_new_kernel_hash;
Alex Deymo39910dc2015-11-09 17:04:30 -0800883 EXPECT_TRUE(HashCalculator::RawHashOfData(state->new_kernel_data,
884 &expected_new_kernel_hash));
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700885 EXPECT_EQ(expected_new_kernel_hash, partitions[1].target_hash);
886
887 EXPECT_EQ(state->image_size, partitions[0].target_size);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700888 brillo::Blob expected_new_rootfs_hash;
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800889 EXPECT_EQ(static_cast<off_t>(state->image_size),
Alex Deymo39910dc2015-11-09 17:04:30 -0800890 HashCalculator::RawHashOfFile(state->b_img,
891 state->image_size,
892 &expected_new_rootfs_hash));
Alex Deymoe5e5fe92015-10-05 09:28:19 -0700893 EXPECT_EQ(expected_new_rootfs_hash, partitions[0].target_hash);
Sen Jianga4365d62015-09-25 10:52:25 -0700894}
895
896void VerifyPayload(DeltaPerformer* performer,
897 DeltaState* state,
898 SignatureTest signature_test,
899 uint32_t minor_version) {
900 ErrorCode expected_result = ErrorCode::kSuccess;
901 switch (signature_test) {
902 case kSignatureNone:
903 expected_result = ErrorCode::kSignedDeltaPayloadExpectedError;
904 break;
905 case kSignatureGeneratedShellBadKey:
906 expected_result = ErrorCode::kDownloadPayloadPubKeyVerificationError;
907 break;
908 default: break; // appease gcc
909 }
910
911 VerifyPayloadResult(performer, state, expected_result, minor_version);
912}
913
914void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
915 ssize_t chunk_size,
916 SignatureTest signature_test,
917 bool hash_checks_mandatory, uint32_t minor_version) {
918 DeltaState state;
919 DeltaPerformer *performer = nullptr;
920 GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
921 signature_test, &state, minor_version);
922
923 ScopedPathUnlinker a_img_unlinker(state.a_img);
924 ScopedPathUnlinker b_img_unlinker(state.b_img);
925 ScopedPathUnlinker new_img_unlinker(state.result_img);
926 ScopedPathUnlinker delta_unlinker(state.delta_path);
927 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
928 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
929 ScopedPathUnlinker result_kernel_unlinker(state.result_kernel);
930 ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
931 &state, hash_checks_mandatory, kValidOperationData,
932 &performer, minor_version);
933 VerifyPayload(performer, &state, signature_test, minor_version);
934 delete performer;
935}
936
937void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
938 bool hash_checks_mandatory) {
939 DeltaState state;
Alex Deymocbf09892015-09-11 16:13:16 -0700940 uint64_t minor_version = kFullPayloadMinorVersion;
Sen Jianga4365d62015-09-25 10:52:25 -0700941 GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state,
942 minor_version);
943 ScopedPathUnlinker a_img_unlinker(state.a_img);
944 ScopedPathUnlinker b_img_unlinker(state.b_img);
945 ScopedPathUnlinker delta_unlinker(state.delta_path);
946 ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
947 ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
948 DeltaPerformer *performer = nullptr;
949 ApplyDeltaFile(true, true, false, kSignatureGenerated, &state,
950 hash_checks_mandatory, op_hash_test, &performer,
951 minor_version);
952 delete performer;
953}
954
955
956TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageTest) {
957 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
958 false, kInPlaceMinorPayloadVersion);
959}
960
Sen Jiang7ebfccf2018-03-15 13:55:55 -0700961TEST(DeltaPerformerIntegrationTest,
962 RunAsRootSmallImageSignaturePlaceholderTest) {
Sen Jianga4365d62015-09-25 10:52:25 -0700963 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
964 false, kInPlaceMinorPayloadVersion);
965}
966
Sen Jiang7ebfccf2018-03-15 13:55:55 -0700967TEST(DeltaPerformerIntegrationTest,
968 RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
Sen Jianga4365d62015-09-25 10:52:25 -0700969 DeltaState state;
970 GenerateDeltaFile(false, false, false, -1,
971 kSignatureGeneratedPlaceholderMismatch, &state,
972 kInPlaceMinorPayloadVersion);
973}
974
975TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageChunksTest) {
976 DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
977 false, kInPlaceMinorPayloadVersion);
978}
979
980TEST(DeltaPerformerIntegrationTest, RunAsRootFullKernelSmallImageTest) {
981 DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
982 false, kInPlaceMinorPayloadVersion);
983}
984
985TEST(DeltaPerformerIntegrationTest, RunAsRootFullSmallImageTest) {
986 DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
Alex Deymocbf09892015-09-11 16:13:16 -0700987 true, kFullPayloadMinorVersion);
Sen Jianga4365d62015-09-25 10:52:25 -0700988}
989
990TEST(DeltaPerformerIntegrationTest, RunAsRootNoopSmallImageTest) {
991 DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
992 false, kInPlaceMinorPayloadVersion);
993}
994
995TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageSignNoneTest) {
996 DoSmallImageTest(false, false, false, -1, kSignatureNone,
997 false, kInPlaceMinorPayloadVersion);
998}
999
1000TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageSignGeneratedTest) {
1001 DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
1002 true, kInPlaceMinorPayloadVersion);
1003}
1004
1005TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageSignGeneratedShellTest) {
1006 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
1007 false, kInPlaceMinorPayloadVersion);
1008}
1009
Sen Jiang7ebfccf2018-03-15 13:55:55 -07001010TEST(DeltaPerformerIntegrationTest,
1011 RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
Sen Jianga4365d62015-09-25 10:52:25 -07001012 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
1013 false, kInPlaceMinorPayloadVersion);
1014}
1015
Sen Jiang7ebfccf2018-03-15 13:55:55 -07001016TEST(DeltaPerformerIntegrationTest,
1017 RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
Sen Jianga4365d62015-09-25 10:52:25 -07001018 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
1019 false, kInPlaceMinorPayloadVersion);
1020}
1021
Sen Jiang7ebfccf2018-03-15 13:55:55 -07001022TEST(DeltaPerformerIntegrationTest,
1023 RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
Sen Jianga4365d62015-09-25 10:52:25 -07001024 DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
1025 false, kInPlaceMinorPayloadVersion);
1026}
1027
1028TEST(DeltaPerformerIntegrationTest, RunAsRootSmallImageSourceOpsTest) {
1029 DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
1030 false, kSourceMinorPayloadVersion);
1031}
1032
Sen Jiang7ebfccf2018-03-15 13:55:55 -07001033TEST(DeltaPerformerIntegrationTest,
1034 RunAsRootMandatoryOperationHashMismatchTest) {
Sen Jianga4365d62015-09-25 10:52:25 -07001035 DoOperationHashMismatchTest(kInvalidOperationData, true);
1036}
1037
1038} // namespace chromeos_update_engine