Alex Deymo | aea4c1c | 2015-08-19 20:24:43 -0700 | [diff] [blame] | 1 | // |
| 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 | // |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 16 | |
Alex Deymo | 39910dc | 2015-11-09 17:04:30 -0800 | [diff] [blame] | 17 | #include "update_engine/payload_consumer/delta_performer.h" |
Alex Deymo | 8427b4a | 2014-11-05 14:00:32 -0800 | [diff] [blame] | 18 | |
Alex Deymo | 80f70ff | 2016-02-10 16:08:11 -0800 | [diff] [blame] | 19 | #include <endian.h> |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 20 | #include <inttypes.h> |
Eric Caruso | 4495bfe | 2018-01-23 16:34:20 -0800 | [diff] [blame] | 21 | #include <time.h> |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 22 | |
Sen Jiang | 77ab7bd | 2018-05-22 17:24:23 -0700 | [diff] [blame] | 23 | #include <memory> |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 24 | #include <string> |
| 25 | #include <vector> |
| 26 | |
Allie Wood | 78750a4 | 2015-02-11 15:42:11 -0800 | [diff] [blame] | 27 | #include <base/files/file_path.h> |
Ben Chan | 06c76a4 | 2014-09-05 08:21:06 -0700 | [diff] [blame] | 28 | #include <base/files/file_util.h> |
Sen Jiang | 371615b | 2016-04-13 15:54:29 -0700 | [diff] [blame] | 29 | #include <base/files/scoped_temp_dir.h> |
Alex Deymo | cbf0989 | 2015-09-11 16:13:16 -0700 | [diff] [blame] | 30 | #include <base/strings/string_number_conversions.h> |
Alex Deymo | f1cbe17 | 2015-03-05 15:58:37 -0800 | [diff] [blame] | 31 | #include <base/strings/string_util.h> |
Alex Deymo | 2d621a3 | 2015-10-01 11:09:01 -0700 | [diff] [blame] | 32 | #include <base/strings/stringprintf.h> |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 33 | #include <gmock/gmock.h> |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 34 | #include <google/protobuf/repeated_field.h> |
| 35 | #include <gtest/gtest.h> |
| 36 | |
Alex Deymo | 39910dc | 2015-11-09 17:04:30 -0800 | [diff] [blame] | 37 | #include "update_engine/common/constants.h" |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 38 | #include "update_engine/common/fake_boot_control.h" |
Alex Deymo | 39910dc | 2015-11-09 17:04:30 -0800 | [diff] [blame] | 39 | #include "update_engine/common/fake_hardware.h" |
| 40 | #include "update_engine/common/fake_prefs.h" |
| 41 | #include "update_engine/common/test_utils.h" |
| 42 | #include "update_engine/common/utils.h" |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 43 | #include "update_engine/payload_consumer/fake_file_descriptor.h" |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 44 | #include "update_engine/payload_consumer/mock_download_action.h" |
Alex Deymo | 39910dc | 2015-11-09 17:04:30 -0800 | [diff] [blame] | 45 | #include "update_engine/payload_consumer/payload_constants.h" |
Alex Deymo | 0bc2611 | 2015-10-19 20:54:57 -0700 | [diff] [blame] | 46 | #include "update_engine/payload_generator/bzip.h" |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 47 | #include "update_engine/payload_generator/extent_ranges.h" |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 48 | #include "update_engine/payload_generator/payload_file.h" |
Alex Deymo | 923d8fa | 2014-07-15 17:58:51 -0700 | [diff] [blame] | 49 | #include "update_engine/payload_generator/payload_signer.h" |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 50 | #include "update_engine/update_metadata.pb.h" |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 51 | |
| 52 | namespace chromeos_update_engine { |
| 53 | |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 54 | using std::string; |
| 55 | using std::vector; |
Sen Jiang | 260f03b | 2016-03-21 15:34:58 -0700 | [diff] [blame] | 56 | using test_utils::GetBuildArtifactsPath; |
Alex Deymo | 2d621a3 | 2015-10-01 11:09:01 -0700 | [diff] [blame] | 57 | using test_utils::kRandomString; |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 58 | using test_utils::System; |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 59 | using testing::_; |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 60 | |
Andrew de los Reyes | 932bc4c | 2010-08-23 18:14:09 -0700 | [diff] [blame] | 61 | extern const char* kUnittestPrivateKeyPath; |
Darin Petkov | d7061ab | 2010-10-06 14:37:09 -0700 | [diff] [blame] | 62 | extern const char* kUnittestPublicKeyPath; |
Andrew de los Reyes | 932bc4c | 2010-08-23 18:14:09 -0700 | [diff] [blame] | 63 | |
Sen Jiang | e0d0428 | 2016-03-01 14:22:52 -0800 | [diff] [blame] | 64 | namespace { |
| 65 | |
| 66 | const char kBogusMetadataSignature1[] = |
Gilad Arnold | d1c4d2d | 2014-06-05 14:07:53 -0700 | [diff] [blame] | 67 | "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv" |
| 68 | "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr" |
| 69 | "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS" |
| 70 | "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR" |
| 71 | "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV" |
| 72 | "pLRtClp97kN2+tXGNBQqkA=="; |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 73 | |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 74 | // Different options that determine what we should fill into the |
| 75 | // install_plan.metadata_signature to simulate the contents received in the |
| 76 | // Omaha response. |
| 77 | enum MetadataSignatureTest { |
| 78 | kEmptyMetadataSignature, |
| 79 | kInvalidMetadataSignature, |
| 80 | kValidMetadataSignature, |
| 81 | }; |
| 82 | |
Alex Deymo | 2d621a3 | 2015-10-01 11:09:01 -0700 | [diff] [blame] | 83 | // Compressed data without checksum, generated with: |
Sen Jiang | 5e1af98 | 2018-11-01 15:01:45 -0700 | [diff] [blame] | 84 | // echo -n "a$(head -c 4095 /dev/zero)" | xz -9 --check=none | |
| 85 | // hexdump -v -e '" " 12/1 "0x%02x, " "\n"' |
Alex Deymo | 2d621a3 | 2015-10-01 11:09:01 -0700 | [diff] [blame] | 86 | const uint8_t kXzCompressedData[] = { |
| 87 | 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x00, 0xff, 0x12, 0xd9, 0x41, |
| 88 | 0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc, |
Sen Jiang | 5e1af98 | 2018-11-01 15:01:45 -0700 | [diff] [blame] | 89 | 0xe0, 0x0f, 0xff, 0x00, 0x1b, 0x5d, 0x00, 0x30, 0x80, 0x33, 0xff, 0xdf, |
| 90 | 0xff, 0x51, 0xd6, 0xaf, 0x90, 0x1c, 0x1b, 0x4c, 0xaa, 0x3d, 0x7b, 0x28, |
| 91 | 0xe4, 0x7a, 0x74, 0xbc, 0xe5, 0xa7, 0x33, 0x4e, 0xcf, 0x00, 0x00, 0x00, |
| 92 | 0x00, 0x01, 0x2f, 0x80, 0x20, 0x00, 0x00, 0x00, 0x92, 0x7c, 0x7b, 0x24, |
| 93 | 0xa8, 0x00, 0x0a, 0xfc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x5a, |
Alex Deymo | 2d621a3 | 2015-10-01 11:09:01 -0700 | [diff] [blame] | 94 | }; |
| 95 | |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 96 | // clang-format off |
Amin Hassani | 02855c2 | 2017-09-06 22:34:50 -0700 | [diff] [blame] | 97 | const uint8_t src_deflates[] = { |
| 98 | /* raw 0 */ 0x11, 0x22, |
| 99 | /* deflate 2 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00, |
| 100 | /* raw 9 */ 0x33, |
| 101 | /* deflate 10 */ 0x03, 0x00, |
| 102 | /* raw 12 */ |
| 103 | /* deflate 12 */ 0x63, 0x04, 0x00, |
| 104 | /* raw 15 */ 0x44, 0x55 |
| 105 | }; |
| 106 | |
| 107 | const uint8_t dst_deflates[] = { |
| 108 | /* deflate 0 */ 0x63, 0x64, 0x62, 0x66, 0x61, 0x05, 0x00, |
| 109 | /* raw 7 */ 0x33, 0x66, |
| 110 | /* deflate 9 */ 0x01, 0x05, 0x00, 0xFA, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, |
| 111 | /* deflate 19 */ 0x63, 0x04, 0x00 |
| 112 | }; |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 113 | // clang-format on |
Amin Hassani | 02855c2 | 2017-09-06 22:34:50 -0700 | [diff] [blame] | 114 | |
| 115 | // To generate this patch either: |
| 116 | // - Use puffin/src/patching_unittest.cc:TestPatching |
| 117 | // Or |
| 118 | // - Use the following approach: |
| 119 | // * Make src_deflate a string of hex with only spaces. (e.g. "0XTE 0xST") |
| 120 | // * echo "0XTE 0xST" | xxd -r -p > src.bin |
| 121 | // * Find the location of deflates in src_deflates (in bytes) in the format of |
| 122 | // "offset:length,...". (e.g. "2:7,10:2,12:3") |
| 123 | // * Do previous three steps for dst_deflates. |
| 124 | // * puffin --operation=puffdiff --src_file=src.bin --dst_file=dst.bin \ |
| 125 | // --src_deflates_byte="2:7,10:2,12:3" --dst_deflates_byte="0:7,9:10,19:3" \ |
| 126 | // --patch_file=patch.bin |
| 127 | // * hexdump -ve '" " 12/1 "0x%02x, " "\n"' patch.bin |
| 128 | const uint8_t puffdiff_patch[] = { |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 129 | 0x50, 0x55, 0x46, 0x31, 0x00, 0x00, 0x00, 0x51, 0x08, 0x01, 0x12, 0x27, |
| 130 | 0x0A, 0x04, 0x08, 0x10, 0x10, 0x32, 0x0A, 0x04, 0x08, 0x50, 0x10, 0x0A, |
| 131 | 0x0A, 0x04, 0x08, 0x60, 0x10, 0x12, 0x12, 0x04, 0x08, 0x10, 0x10, 0x58, |
| 132 | 0x12, 0x04, 0x08, 0x78, 0x10, 0x28, 0x12, 0x05, 0x08, 0xA8, 0x01, 0x10, |
| 133 | 0x38, 0x18, 0x1F, 0x1A, 0x24, 0x0A, 0x02, 0x10, 0x32, 0x0A, 0x04, 0x08, |
| 134 | 0x48, 0x10, 0x50, 0x0A, 0x05, 0x08, 0x98, 0x01, 0x10, 0x12, 0x12, 0x02, |
| 135 | 0x10, 0x58, 0x12, 0x04, 0x08, 0x70, 0x10, 0x58, 0x12, 0x05, 0x08, 0xC8, |
| 136 | 0x01, 0x10, 0x38, 0x18, 0x21, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34, |
| 137 | 0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, |
| 138 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 139 | 0x00, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x65, |
| 140 | 0x29, 0x8C, 0x9B, 0x00, 0x00, 0x03, 0x60, 0x40, 0x7A, 0x0E, 0x08, 0x00, |
| 141 | 0x40, 0x00, 0x20, 0x00, 0x21, 0x22, 0x9A, 0x3D, 0x4F, 0x50, 0x40, 0x0C, |
| 142 | 0x3B, 0xC7, 0x9B, 0xB2, 0x21, 0x0E, 0xE9, 0x15, 0x98, 0x7A, 0x7C, 0x5D, |
| 143 | 0xC9, 0x14, 0xE1, 0x42, 0x41, 0x94, 0xA6, 0x32, 0x6C, 0x42, 0x5A, 0x68, |
| 144 | 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xF1, 0x20, 0x5F, 0x0D, 0x00, |
| 145 | 0x00, 0x02, 0x41, 0x15, 0x42, 0x08, 0x20, 0x00, 0x40, 0x00, 0x00, 0x02, |
| 146 | 0x40, 0x00, 0x20, 0x00, 0x22, 0x3D, 0x23, 0x10, 0x86, 0x03, 0x96, 0x54, |
| 147 | 0x11, 0x16, 0x5F, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0xF1, 0x20, 0x5F, |
| 148 | 0x0D, 0x42, 0x5A, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x07, |
| 149 | 0xD4, 0xCB, 0x6E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x00, |
| 150 | 0x21, 0x18, 0x46, 0x82, 0xEE, 0x48, 0xA7, 0x0A, 0x12, 0x00, 0xFA, 0x99, |
| 151 | 0x6D, 0xC0}; |
Amin Hassani | 02855c2 | 2017-09-06 22:34:50 -0700 | [diff] [blame] | 152 | |
Alex Vakulenko | d2779df | 2014-06-16 13:19:00 -0700 | [diff] [blame] | 153 | } // namespace |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 154 | |
Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 155 | class DeltaPerformerTest : public ::testing::Test { |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 156 | protected: |
Alex Deymo | e5e5fe9 | 2015-10-05 09:28:19 -0700 | [diff] [blame] | 157 | void SetUp() override { |
| 158 | install_plan_.source_slot = 0; |
| 159 | install_plan_.target_slot = 1; |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 160 | EXPECT_CALL(mock_delegate_, ShouldCancel(_)) |
| 161 | .WillRepeatedly(testing::Return(false)); |
Alex Deymo | e5e5fe9 | 2015-10-05 09:28:19 -0700 | [diff] [blame] | 162 | } |
Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 163 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 164 | // Test helper placed where it can easily be friended from DeltaPerformer. |
| 165 | void RunManifestValidation(const DeltaArchiveManifest& manifest, |
Sen Jiang | 3e728fe | 2015-11-05 11:37:23 -0800 | [diff] [blame] | 166 | uint64_t major_version, |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 167 | InstallPayloadType payload_type, |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 168 | ErrorCode expected) { |
Sen Jiang | cdd5206 | 2017-05-18 15:33:10 -0700 | [diff] [blame] | 169 | payload_.type = payload_type; |
Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 170 | |
| 171 | // The Manifest we are validating. |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 172 | performer_.manifest_.CopyFrom(manifest); |
Sen Jiang | 3e728fe | 2015-11-05 11:37:23 -0800 | [diff] [blame] | 173 | performer_.major_payload_version_ = major_version; |
Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 174 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 175 | EXPECT_EQ(expected, performer_.ValidateManifest()); |
Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 176 | } |
| 177 | |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 178 | brillo::Blob GeneratePayload(const brillo::Blob& blob_data, |
| 179 | const vector<AnnotatedOperation>& aops, |
Sen Jiang | 889c65d | 2015-11-17 15:04:02 -0800 | [diff] [blame] | 180 | bool sign_payload) { |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 181 | return GeneratePayload(blob_data, |
| 182 | aops, |
| 183 | sign_payload, |
| 184 | kMaxSupportedMajorPayloadVersion, |
| 185 | kMaxSupportedMinorPayloadVersion); |
Sen Jiang | 889c65d | 2015-11-17 15:04:02 -0800 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | brillo::Blob GeneratePayload(const brillo::Blob& blob_data, |
| 189 | const vector<AnnotatedOperation>& aops, |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 190 | bool sign_payload, |
Sen Jiang | 76bfa74 | 2015-10-12 17:13:26 -0700 | [diff] [blame] | 191 | uint64_t major_version, |
| 192 | uint32_t minor_version) { |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 193 | test_utils::ScopedTempFile blob_file("Blob-XXXXXX"); |
| 194 | EXPECT_TRUE(test_utils::WriteFileVector(blob_file.path(), blob_data)); |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 195 | |
| 196 | PayloadGenerationConfig config; |
Alex Deymo | a4073ef | 2016-03-22 23:40:53 -0700 | [diff] [blame] | 197 | config.version.major = major_version; |
| 198 | config.version.minor = minor_version; |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 199 | |
| 200 | PayloadFile payload; |
| 201 | EXPECT_TRUE(payload.Init(config)); |
| 202 | |
Tudor Brindus | dda79e2 | 2018-06-28 18:03:21 -0700 | [diff] [blame] | 203 | PartitionConfig old_part(kPartitionNameRoot); |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 204 | if (minor_version != kFullPayloadMinorVersion) { |
| 205 | // When generating a delta payload we need to include the old partition |
| 206 | // information to mark it as a delta payload. |
| 207 | old_part.path = "/dev/null"; |
| 208 | old_part.size = 0; |
| 209 | } |
Tudor Brindus | dda79e2 | 2018-06-28 18:03:21 -0700 | [diff] [blame] | 210 | PartitionConfig new_part(kPartitionNameRoot); |
Alex Deymo | e5e5fe9 | 2015-10-05 09:28:19 -0700 | [diff] [blame] | 211 | new_part.path = "/dev/zero"; |
| 212 | new_part.size = 1234; |
Sen Jiang | 981eb11 | 2015-08-25 17:03:18 -0700 | [diff] [blame] | 213 | |
| 214 | payload.AddPartition(old_part, new_part, aops); |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 215 | |
Alex Deymo | e5e5fe9 | 2015-10-05 09:28:19 -0700 | [diff] [blame] | 216 | // We include a kernel partition without operations. |
Tudor Brindus | dda79e2 | 2018-06-28 18:03:21 -0700 | [diff] [blame] | 217 | old_part.name = kPartitionNameKernel; |
| 218 | new_part.name = kPartitionNameKernel; |
Alex Deymo | e5e5fe9 | 2015-10-05 09:28:19 -0700 | [diff] [blame] | 219 | new_part.size = 0; |
| 220 | payload.AddPartition(old_part, new_part, {}); |
| 221 | |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 222 | test_utils::ScopedTempFile payload_file("Payload-XXXXXX"); |
Sen Jiang | 260f03b | 2016-03-21 15:34:58 -0700 | [diff] [blame] | 223 | string private_key = |
| 224 | sign_payload ? GetBuildArtifactsPath(kUnittestPrivateKeyPath) : ""; |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 225 | EXPECT_TRUE(payload.WritePayload(payload_file.path(), |
| 226 | blob_file.path(), |
| 227 | private_key, |
| 228 | &payload_.metadata_size)); |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 229 | |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 230 | brillo::Blob payload_data; |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 231 | EXPECT_TRUE(utils::ReadFile(payload_file.path(), &payload_data)); |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 232 | return payload_data; |
| 233 | } |
Allie Wood | fdf0051 | 2015-03-02 13:34:55 -0800 | [diff] [blame] | 234 | |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 235 | brillo::Blob GenerateSourceCopyPayload(const brillo::Blob& copied_data, |
| 236 | bool add_hash) { |
| 237 | PayloadGenerationConfig config; |
| 238 | const uint64_t kDefaultBlockSize = config.block_size; |
| 239 | EXPECT_EQ(0U, copied_data.size() % kDefaultBlockSize); |
| 240 | uint64_t num_blocks = copied_data.size() / kDefaultBlockSize; |
| 241 | AnnotatedOperation aop; |
| 242 | *(aop.op.add_src_extents()) = ExtentForRange(0, num_blocks); |
| 243 | *(aop.op.add_dst_extents()) = ExtentForRange(0, num_blocks); |
| 244 | aop.op.set_type(InstallOperation::SOURCE_COPY); |
| 245 | brillo::Blob src_hash; |
| 246 | EXPECT_TRUE(HashCalculator::RawHashOfData(copied_data, &src_hash)); |
| 247 | if (add_hash) |
| 248 | aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size()); |
| 249 | |
| 250 | return GeneratePayload(brillo::Blob(), {aop}, false); |
| 251 | } |
| 252 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 253 | // Apply |payload_data| on partition specified in |source_path|. |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 254 | // Expect result of performer_.Write() to be |expect_success|. |
| 255 | // Returns the result of the payload application. |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 256 | brillo::Blob ApplyPayload(const brillo::Blob& payload_data, |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 257 | const string& source_path, |
| 258 | bool expect_success) { |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 259 | return ApplyPayloadToData( |
| 260 | payload_data, source_path, brillo::Blob(), expect_success); |
Alex Deymo | 79715ad | 2015-10-02 14:27:53 -0700 | [diff] [blame] | 261 | } |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 262 | |
Alex Deymo | 79715ad | 2015-10-02 14:27:53 -0700 | [diff] [blame] | 263 | // Apply the payload provided in |payload_data| reading from the |source_path| |
| 264 | // file and writing the contents to a new partition. The existing data in the |
| 265 | // new target file are set to |target_data| before applying the payload. |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 266 | // Expect result of performer_.Write() to be |expect_success|. |
Alex Deymo | 79715ad | 2015-10-02 14:27:53 -0700 | [diff] [blame] | 267 | // Returns the result of the payload application. |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 268 | brillo::Blob ApplyPayloadToData(const brillo::Blob& payload_data, |
| 269 | const string& source_path, |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 270 | const brillo::Blob& target_data, |
| 271 | bool expect_success) { |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 272 | test_utils::ScopedTempFile new_part("Partition-XXXXXX"); |
| 273 | EXPECT_TRUE(test_utils::WriteFileVector(new_part.path(), target_data)); |
Alex Deymo | 79715ad | 2015-10-02 14:27:53 -0700 | [diff] [blame] | 274 | |
Alex Deymo | e5e5fe9 | 2015-10-05 09:28:19 -0700 | [diff] [blame] | 275 | // We installed the operations only in the rootfs partition, but the |
| 276 | // delta performer needs to access all the partitions. |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 277 | fake_boot_control_.SetPartitionDevice( |
Sen Jiang | 456853f | 2018-08-13 15:41:43 -0700 | [diff] [blame] | 278 | kPartitionNameRoot, install_plan_.target_slot, new_part.path()); |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 279 | fake_boot_control_.SetPartitionDevice( |
Tudor Brindus | dda79e2 | 2018-06-28 18:03:21 -0700 | [diff] [blame] | 280 | kPartitionNameRoot, install_plan_.source_slot, source_path); |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 281 | fake_boot_control_.SetPartitionDevice( |
Tudor Brindus | dda79e2 | 2018-06-28 18:03:21 -0700 | [diff] [blame] | 282 | kPartitionNameKernel, install_plan_.target_slot, "/dev/null"); |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 283 | fake_boot_control_.SetPartitionDevice( |
Tudor Brindus | dda79e2 | 2018-06-28 18:03:21 -0700 | [diff] [blame] | 284 | kPartitionNameKernel, install_plan_.source_slot, "/dev/null"); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 285 | |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 286 | EXPECT_EQ(expect_success, |
| 287 | performer_.Write(payload_data.data(), payload_data.size())); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 288 | EXPECT_EQ(0, performer_.Close()); |
| 289 | |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 290 | brillo::Blob partition_data; |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 291 | EXPECT_TRUE(utils::ReadFile(new_part.path(), &partition_data)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 292 | return partition_data; |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 293 | } |
| 294 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 295 | // Calls delta performer's Write method by pretending to pass in bytes from a |
| 296 | // delta file whose metadata size is actual_metadata_size and tests if all |
| 297 | // checks are correctly performed if the install plan contains |
| 298 | // expected_metadata_size and that the result of the parsing are as per |
| 299 | // hash_checks_mandatory flag. |
| 300 | void DoMetadataSizeTest(uint64_t expected_metadata_size, |
| 301 | uint64_t actual_metadata_size, |
| 302 | bool hash_checks_mandatory) { |
| 303 | install_plan_.hash_checks_mandatory = hash_checks_mandatory; |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 304 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 305 | // Set a valid magic string and version number 1. |
| 306 | EXPECT_TRUE(performer_.Write("CrAU", 4)); |
| 307 | uint64_t version = htobe64(kChromeOSMajorPayloadVersion); |
| 308 | EXPECT_TRUE(performer_.Write(&version, 8)); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 309 | |
Sen Jiang | 0affc2c | 2017-02-10 15:55:05 -0800 | [diff] [blame] | 310 | payload_.metadata_size = expected_metadata_size; |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 311 | ErrorCode error_code; |
| 312 | // When filling in size in manifest, exclude the size of the 20-byte header. |
| 313 | uint64_t size_in_manifest = htobe64(actual_metadata_size - 20); |
| 314 | bool result = performer_.Write(&size_in_manifest, 8, &error_code); |
| 315 | if (expected_metadata_size == actual_metadata_size || |
| 316 | !hash_checks_mandatory) { |
| 317 | EXPECT_TRUE(result); |
| 318 | } else { |
| 319 | EXPECT_FALSE(result); |
| 320 | EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code); |
| 321 | } |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 322 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 323 | EXPECT_LT(performer_.Close(), 0); |
| 324 | } |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 325 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 326 | // Generates a valid delta file but tests the delta performer by suppling |
| 327 | // different metadata signatures as per metadata_signature_test flag and |
| 328 | // sees if the result of the parsing are as per hash_checks_mandatory flag. |
| 329 | void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test, |
| 330 | bool sign_payload, |
| 331 | bool hash_checks_mandatory) { |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 332 | // Loads the payload and parses the manifest. |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 333 | brillo::Blob payload = GeneratePayload(brillo::Blob(), |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 334 | vector<AnnotatedOperation>(), |
| 335 | sign_payload, |
| 336 | kChromeOSMajorPayloadVersion, |
| 337 | kFullPayloadMinorVersion); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 338 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 339 | LOG(INFO) << "Payload size: " << payload.size(); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 340 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 341 | install_plan_.hash_checks_mandatory = hash_checks_mandatory; |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 342 | |
Sen Jiang | 9c89e84 | 2018-02-02 13:51:21 -0800 | [diff] [blame] | 343 | MetadataParseResult expected_result, actual_result; |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 344 | ErrorCode expected_error, actual_error; |
| 345 | |
| 346 | // Fill up the metadata signature in install plan according to the test. |
| 347 | switch (metadata_signature_test) { |
| 348 | case kEmptyMetadataSignature: |
Sen Jiang | 0affc2c | 2017-02-10 15:55:05 -0800 | [diff] [blame] | 349 | payload_.metadata_signature.clear(); |
Sen Jiang | 9c89e84 | 2018-02-02 13:51:21 -0800 | [diff] [blame] | 350 | expected_result = MetadataParseResult::kError; |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 351 | expected_error = ErrorCode::kDownloadMetadataSignatureMissingError; |
| 352 | break; |
| 353 | |
| 354 | case kInvalidMetadataSignature: |
Sen Jiang | 0affc2c | 2017-02-10 15:55:05 -0800 | [diff] [blame] | 355 | payload_.metadata_signature = kBogusMetadataSignature1; |
Sen Jiang | 9c89e84 | 2018-02-02 13:51:21 -0800 | [diff] [blame] | 356 | expected_result = MetadataParseResult::kError; |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 357 | expected_error = ErrorCode::kDownloadMetadataSignatureMismatch; |
| 358 | break; |
| 359 | |
| 360 | case kValidMetadataSignature: |
| 361 | default: |
| 362 | // Set the install plan's metadata size to be the same as the one |
| 363 | // in the manifest so that we pass the metadata size checks. Only |
| 364 | // then we can get to manifest signature checks. |
| 365 | ASSERT_TRUE(PayloadSigner::GetMetadataSignature( |
| 366 | payload.data(), |
Sen Jiang | 0affc2c | 2017-02-10 15:55:05 -0800 | [diff] [blame] | 367 | payload_.metadata_size, |
Sen Jiang | 260f03b | 2016-03-21 15:34:58 -0700 | [diff] [blame] | 368 | GetBuildArtifactsPath(kUnittestPrivateKeyPath), |
Sen Jiang | 0affc2c | 2017-02-10 15:55:05 -0800 | [diff] [blame] | 369 | &payload_.metadata_signature)); |
| 370 | EXPECT_FALSE(payload_.metadata_signature.empty()); |
Sen Jiang | 9c89e84 | 2018-02-02 13:51:21 -0800 | [diff] [blame] | 371 | expected_result = MetadataParseResult::kSuccess; |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 372 | expected_error = ErrorCode::kSuccess; |
| 373 | break; |
| 374 | } |
| 375 | |
| 376 | // Ignore the expected result/error if hash checks are not mandatory. |
| 377 | if (!hash_checks_mandatory) { |
Sen Jiang | 9c89e84 | 2018-02-02 13:51:21 -0800 | [diff] [blame] | 378 | expected_result = MetadataParseResult::kSuccess; |
Gilad Arnold | d1c4d2d | 2014-06-05 14:07:53 -0700 | [diff] [blame] | 379 | expected_error = ErrorCode::kSuccess; |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 380 | } |
| 381 | |
| 382 | // Use the public key corresponding to the private key used above to |
| 383 | // sign the metadata. |
Sen Jiang | 260f03b | 2016-03-21 15:34:58 -0700 | [diff] [blame] | 384 | string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath); |
| 385 | EXPECT_TRUE(utils::FileExists(public_key_path.c_str())); |
| 386 | performer_.set_public_key_path(public_key_path); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 387 | |
| 388 | // Init actual_error with an invalid value so that we make sure |
| 389 | // ParsePayloadMetadata properly populates it in all cases. |
| 390 | actual_error = ErrorCode::kUmaReportedMax; |
| 391 | actual_result = performer_.ParsePayloadMetadata(payload, &actual_error); |
| 392 | |
| 393 | EXPECT_EQ(expected_result, actual_result); |
| 394 | EXPECT_EQ(expected_error, actual_error); |
| 395 | |
| 396 | // Check that the parsed metadata size is what's expected. This test |
| 397 | // implicitly confirms that the metadata signature is valid, if required. |
Sen Jiang | 9c89e84 | 2018-02-02 13:51:21 -0800 | [diff] [blame] | 398 | EXPECT_EQ(payload_.metadata_size, performer_.metadata_size_); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 399 | } |
| 400 | |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 401 | // Helper function to pretend that the ECC file descriptor was already opened. |
| 402 | // Returns a pointer to the created file descriptor. |
| 403 | FakeFileDescriptor* SetFakeECCFile(size_t size) { |
| 404 | EXPECT_FALSE(performer_.source_ecc_fd_) << "source_ecc_fd_ already open."; |
| 405 | FakeFileDescriptor* ret = new FakeFileDescriptor(); |
| 406 | fake_ecc_fd_.reset(ret); |
| 407 | // Call open to simulate it was already opened. |
| 408 | ret->Open("", 0); |
| 409 | ret->SetFileSize(size); |
| 410 | performer_.source_ecc_fd_ = fake_ecc_fd_; |
| 411 | return ret; |
| 412 | } |
| 413 | |
| 414 | uint64_t GetSourceEccRecoveredFailures() const { |
| 415 | return performer_.source_ecc_recovered_failures_; |
| 416 | } |
| 417 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 418 | FakePrefs prefs_; |
| 419 | InstallPlan install_plan_; |
Sen Jiang | 0affc2c | 2017-02-10 15:55:05 -0800 | [diff] [blame] | 420 | InstallPlan::Payload payload_; |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 421 | FakeBootControl fake_boot_control_; |
| 422 | FakeHardware fake_hardware_; |
| 423 | MockDownloadActionDelegate mock_delegate_; |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 424 | FileDescriptorPtr fake_ecc_fd_; |
Sen Jiang | 0affc2c | 2017-02-10 15:55:05 -0800 | [diff] [blame] | 425 | DeltaPerformer performer_{&prefs_, |
| 426 | &fake_boot_control_, |
| 427 | &fake_hardware_, |
| 428 | &mock_delegate_, |
| 429 | &install_plan_, |
Sen Jiang | 4490696 | 2018-01-08 17:39:04 -0800 | [diff] [blame] | 430 | &payload_, |
Amin Hassani | ed37d68 | 2018-04-06 13:22:00 -0700 | [diff] [blame] | 431 | false /* interactive*/}; |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 432 | }; |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 433 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 434 | TEST_F(DeltaPerformerTest, FullPayloadWriteTest) { |
Sen Jiang | cdd5206 | 2017-05-18 15:33:10 -0700 | [diff] [blame] | 435 | payload_.type = InstallPayloadType::kFull; |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 436 | brillo::Blob expected_data = |
| 437 | brillo::Blob(std::begin(kRandomString), std::end(kRandomString)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 438 | expected_data.resize(4096); // block size |
| 439 | vector<AnnotatedOperation> aops; |
| 440 | AnnotatedOperation aop; |
| 441 | *(aop.op.add_dst_extents()) = ExtentForRange(0, 1); |
| 442 | aop.op.set_data_offset(0); |
| 443 | aop.op.set_data_length(expected_data.size()); |
| 444 | aop.op.set_type(InstallOperation::REPLACE); |
| 445 | aops.push_back(aop); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 446 | |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 447 | brillo::Blob payload_data = GeneratePayload(expected_data, |
| 448 | aops, |
| 449 | false, |
| 450 | kChromeOSMajorPayloadVersion, |
| 451 | kFullPayloadMinorVersion); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 452 | |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 453 | EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true)); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 454 | } |
| 455 | |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 456 | TEST_F(DeltaPerformerTest, ShouldCancelTest) { |
Sen Jiang | cdd5206 | 2017-05-18 15:33:10 -0700 | [diff] [blame] | 457 | payload_.type = InstallPayloadType::kFull; |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 458 | brillo::Blob expected_data = |
| 459 | brillo::Blob(std::begin(kRandomString), std::end(kRandomString)); |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 460 | expected_data.resize(4096); // block size |
| 461 | vector<AnnotatedOperation> aops; |
| 462 | AnnotatedOperation aop; |
| 463 | *(aop.op.add_dst_extents()) = ExtentForRange(0, 1); |
| 464 | aop.op.set_data_offset(0); |
| 465 | aop.op.set_data_length(expected_data.size()); |
| 466 | aop.op.set_type(InstallOperation::REPLACE); |
| 467 | aops.push_back(aop); |
| 468 | |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 469 | brillo::Blob payload_data = GeneratePayload(expected_data, |
| 470 | aops, |
| 471 | false, |
| 472 | kChromeOSMajorPayloadVersion, |
| 473 | kFullPayloadMinorVersion); |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 474 | |
| 475 | testing::Mock::VerifyAndClearExpectations(&mock_delegate_); |
| 476 | EXPECT_CALL(mock_delegate_, ShouldCancel(_)) |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 477 | .WillOnce(testing::DoAll(testing::SetArgPointee<0>(ErrorCode::kError), |
| 478 | testing::Return(true))); |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 479 | |
| 480 | ApplyPayload(payload_data, "/dev/null", false); |
| 481 | } |
| 482 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 483 | TEST_F(DeltaPerformerTest, ReplaceOperationTest) { |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 484 | brillo::Blob expected_data = |
| 485 | brillo::Blob(std::begin(kRandomString), std::end(kRandomString)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 486 | expected_data.resize(4096); // block size |
| 487 | vector<AnnotatedOperation> aops; |
| 488 | AnnotatedOperation aop; |
| 489 | *(aop.op.add_dst_extents()) = ExtentForRange(0, 1); |
| 490 | aop.op.set_data_offset(0); |
| 491 | aop.op.set_data_length(expected_data.size()); |
| 492 | aop.op.set_type(InstallOperation::REPLACE); |
| 493 | aops.push_back(aop); |
| 494 | |
Sen Jiang | 889c65d | 2015-11-17 15:04:02 -0800 | [diff] [blame] | 495 | brillo::Blob payload_data = GeneratePayload(expected_data, aops, false); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 496 | |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 497 | EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 498 | } |
| 499 | |
| 500 | TEST_F(DeltaPerformerTest, ReplaceBzOperationTest) { |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 501 | brillo::Blob expected_data = |
| 502 | brillo::Blob(std::begin(kRandomString), std::end(kRandomString)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 503 | expected_data.resize(4096); // block size |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 504 | brillo::Blob bz_data; |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 505 | EXPECT_TRUE(BzipCompress(expected_data, &bz_data)); |
| 506 | |
| 507 | vector<AnnotatedOperation> aops; |
| 508 | AnnotatedOperation aop; |
| 509 | *(aop.op.add_dst_extents()) = ExtentForRange(0, 1); |
| 510 | aop.op.set_data_offset(0); |
| 511 | aop.op.set_data_length(bz_data.size()); |
| 512 | aop.op.set_type(InstallOperation::REPLACE_BZ); |
| 513 | aops.push_back(aop); |
| 514 | |
Sen Jiang | 889c65d | 2015-11-17 15:04:02 -0800 | [diff] [blame] | 515 | brillo::Blob payload_data = GeneratePayload(bz_data, aops, false); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 516 | |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 517 | EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 518 | } |
| 519 | |
Alex Deymo | 2d621a3 | 2015-10-01 11:09:01 -0700 | [diff] [blame] | 520 | TEST_F(DeltaPerformerTest, ReplaceXzOperationTest) { |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 521 | brillo::Blob xz_data(std::begin(kXzCompressedData), |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 522 | std::end(kXzCompressedData)); |
Sen Jiang | 5e1af98 | 2018-11-01 15:01:45 -0700 | [diff] [blame] | 523 | // The compressed xz data contains a single "a" and padded with zero for the |
| 524 | // rest of the block. |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 525 | brillo::Blob expected_data = brillo::Blob(4096, 0); |
Alex Deymo | 2d621a3 | 2015-10-01 11:09:01 -0700 | [diff] [blame] | 526 | expected_data[0] = 'a'; |
| 527 | |
| 528 | AnnotatedOperation aop; |
| 529 | *(aop.op.add_dst_extents()) = ExtentForRange(0, 1); |
| 530 | aop.op.set_data_offset(0); |
| 531 | aop.op.set_data_length(xz_data.size()); |
| 532 | aop.op.set_type(InstallOperation::REPLACE_XZ); |
| 533 | vector<AnnotatedOperation> aops = {aop}; |
| 534 | |
Sen Jiang | 889c65d | 2015-11-17 15:04:02 -0800 | [diff] [blame] | 535 | brillo::Blob payload_data = GeneratePayload(xz_data, aops, false); |
Alex Deymo | 2d621a3 | 2015-10-01 11:09:01 -0700 | [diff] [blame] | 536 | |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 537 | EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true)); |
Alex Deymo | 2d621a3 | 2015-10-01 11:09:01 -0700 | [diff] [blame] | 538 | } |
| 539 | |
Alex Deymo | 79715ad | 2015-10-02 14:27:53 -0700 | [diff] [blame] | 540 | TEST_F(DeltaPerformerTest, ZeroOperationTest) { |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 541 | brillo::Blob existing_data = brillo::Blob(4096 * 10, 'a'); |
| 542 | brillo::Blob expected_data = existing_data; |
Alex Deymo | 79715ad | 2015-10-02 14:27:53 -0700 | [diff] [blame] | 543 | // Blocks 4, 5 and 7 should have zeros instead of 'a' after the operation is |
| 544 | // applied. |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 545 | std::fill( |
| 546 | expected_data.data() + 4096 * 4, expected_data.data() + 4096 * 6, 0); |
| 547 | std::fill( |
| 548 | expected_data.data() + 4096 * 7, expected_data.data() + 4096 * 8, 0); |
Alex Deymo | 79715ad | 2015-10-02 14:27:53 -0700 | [diff] [blame] | 549 | |
| 550 | AnnotatedOperation aop; |
| 551 | *(aop.op.add_dst_extents()) = ExtentForRange(4, 2); |
| 552 | *(aop.op.add_dst_extents()) = ExtentForRange(7, 1); |
| 553 | aop.op.set_type(InstallOperation::ZERO); |
| 554 | vector<AnnotatedOperation> aops = {aop}; |
| 555 | |
Sen Jiang | 889c65d | 2015-11-17 15:04:02 -0800 | [diff] [blame] | 556 | brillo::Blob payload_data = GeneratePayload(brillo::Blob(), aops, false); |
Alex Deymo | 79715ad | 2015-10-02 14:27:53 -0700 | [diff] [blame] | 557 | |
| 558 | EXPECT_EQ(expected_data, |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 559 | ApplyPayloadToData(payload_data, "/dev/null", existing_data, true)); |
Alex Deymo | 79715ad | 2015-10-02 14:27:53 -0700 | [diff] [blame] | 560 | } |
| 561 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 562 | TEST_F(DeltaPerformerTest, SourceCopyOperationTest) { |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 563 | brillo::Blob expected_data(std::begin(kRandomString), |
| 564 | std::end(kRandomString)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 565 | expected_data.resize(4096); // block size |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 566 | AnnotatedOperation aop; |
| 567 | *(aop.op.add_src_extents()) = ExtentForRange(0, 1); |
| 568 | *(aop.op.add_dst_extents()) = ExtentForRange(0, 1); |
| 569 | aop.op.set_type(InstallOperation::SOURCE_COPY); |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 570 | brillo::Blob src_hash; |
| 571 | EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash)); |
| 572 | aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size()); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 573 | |
Sen Jiang | 889c65d | 2015-11-17 15:04:02 -0800 | [diff] [blame] | 574 | brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false); |
| 575 | |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 576 | test_utils::ScopedTempFile source("Source-XXXXXX"); |
| 577 | EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 578 | |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 579 | EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true)); |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 580 | } |
| 581 | |
Amin Hassani | 02855c2 | 2017-09-06 22:34:50 -0700 | [diff] [blame] | 582 | TEST_F(DeltaPerformerTest, PuffdiffOperationTest) { |
| 583 | AnnotatedOperation aop; |
| 584 | *(aop.op.add_src_extents()) = ExtentForRange(0, 1); |
| 585 | *(aop.op.add_dst_extents()) = ExtentForRange(0, 1); |
| 586 | brillo::Blob puffdiff_payload(std::begin(puffdiff_patch), |
| 587 | std::end(puffdiff_patch)); |
| 588 | aop.op.set_data_offset(0); |
| 589 | aop.op.set_data_length(puffdiff_payload.size()); |
| 590 | aop.op.set_type(InstallOperation::PUFFDIFF); |
| 591 | brillo::Blob src(std::begin(src_deflates), std::end(src_deflates)); |
| 592 | src.resize(4096); // block size |
| 593 | brillo::Blob src_hash; |
| 594 | EXPECT_TRUE(HashCalculator::RawHashOfData(src, &src_hash)); |
| 595 | aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size()); |
| 596 | |
| 597 | brillo::Blob payload_data = GeneratePayload(puffdiff_payload, {aop}, false); |
| 598 | |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 599 | test_utils::ScopedTempFile source("Source-XXXXXX"); |
| 600 | EXPECT_TRUE(test_utils::WriteFileVector(source.path(), src)); |
Amin Hassani | 02855c2 | 2017-09-06 22:34:50 -0700 | [diff] [blame] | 601 | |
| 602 | brillo::Blob dst(std::begin(dst_deflates), std::end(dst_deflates)); |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 603 | EXPECT_EQ(dst, ApplyPayload(payload_data, source.path(), true)); |
Amin Hassani | 02855c2 | 2017-09-06 22:34:50 -0700 | [diff] [blame] | 604 | } |
| 605 | |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 606 | TEST_F(DeltaPerformerTest, SourceHashMismatchTest) { |
| 607 | brillo::Blob expected_data = {'f', 'o', 'o'}; |
| 608 | brillo::Blob actual_data = {'b', 'a', 'r'}; |
| 609 | expected_data.resize(4096); // block size |
| 610 | actual_data.resize(4096); // block size |
| 611 | |
| 612 | AnnotatedOperation aop; |
| 613 | *(aop.op.add_src_extents()) = ExtentForRange(0, 1); |
| 614 | *(aop.op.add_dst_extents()) = ExtentForRange(0, 1); |
| 615 | aop.op.set_type(InstallOperation::SOURCE_COPY); |
| 616 | brillo::Blob src_hash; |
| 617 | EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash)); |
| 618 | aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size()); |
| 619 | |
Sen Jiang | 889c65d | 2015-11-17 15:04:02 -0800 | [diff] [blame] | 620 | brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false); |
| 621 | |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 622 | test_utils::ScopedTempFile source("Source-XXXXXX"); |
| 623 | EXPECT_TRUE(test_utils::WriteFileVector(source.path(), actual_data)); |
Sen Jiang | 2ec4aab | 2015-11-13 15:04:03 -0800 | [diff] [blame] | 624 | |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 625 | EXPECT_EQ(actual_data, ApplyPayload(payload_data, source.path(), false)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 626 | } |
| 627 | |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 628 | // Test that the error-corrected file descriptor is used to read the partition |
| 629 | // since the source partition doesn't match the operation hash. |
Sen Jiang | 77ab7bd | 2018-05-22 17:24:23 -0700 | [diff] [blame] | 630 | TEST_F(DeltaPerformerTest, ErrorCorrectionSourceCopyFallbackTest) { |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 631 | constexpr size_t kCopyOperationSize = 4 * 4096; |
| 632 | test_utils::ScopedTempFile source("Source-XXXXXX"); |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 633 | // Write invalid data to the source image, which doesn't match the expected |
| 634 | // hash. |
| 635 | brillo::Blob invalid_data(kCopyOperationSize, 0x55); |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 636 | EXPECT_TRUE(test_utils::WriteFileVector(source.path(), invalid_data)); |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 637 | |
| 638 | // Setup the fec file descriptor as the fake stream, which matches |
| 639 | // |expected_data|. |
| 640 | FakeFileDescriptor* fake_fec = SetFakeECCFile(kCopyOperationSize); |
| 641 | brillo::Blob expected_data = FakeFileDescriptorData(kCopyOperationSize); |
| 642 | |
| 643 | brillo::Blob payload_data = GenerateSourceCopyPayload(expected_data, true); |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 644 | EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true)); |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 645 | // Verify that the fake_fec was actually used. |
| 646 | EXPECT_EQ(1U, fake_fec->GetReadOps().size()); |
| 647 | EXPECT_EQ(1U, GetSourceEccRecoveredFailures()); |
| 648 | } |
| 649 | |
| 650 | // Test that the error-corrected file descriptor is used to read a partition |
| 651 | // when no hash is available for SOURCE_COPY but it falls back to the normal |
| 652 | // file descriptor when the size of the error corrected one is too small. |
Sen Jiang | 77ab7bd | 2018-05-22 17:24:23 -0700 | [diff] [blame] | 653 | TEST_F(DeltaPerformerTest, ErrorCorrectionSourceCopyWhenNoHashFallbackTest) { |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 654 | constexpr size_t kCopyOperationSize = 4 * 4096; |
| 655 | test_utils::ScopedTempFile source("Source-XXXXXX"); |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 656 | // Setup the source path with the right expected data. |
| 657 | brillo::Blob expected_data = FakeFileDescriptorData(kCopyOperationSize); |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 658 | EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data)); |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 659 | |
| 660 | // Setup the fec file descriptor as the fake stream, with smaller data than |
| 661 | // the expected. |
| 662 | FakeFileDescriptor* fake_fec = SetFakeECCFile(kCopyOperationSize / 2); |
| 663 | |
| 664 | // The payload operation doesn't include an operation hash. |
| 665 | brillo::Blob payload_data = GenerateSourceCopyPayload(expected_data, false); |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 666 | EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true)); |
Alex Deymo | 51c264e | 2016-11-04 15:49:53 -0700 | [diff] [blame] | 667 | // Verify that the fake_fec was attempted to be used. Since the file |
| 668 | // descriptor is shorter it can actually do more than one read to realize it |
| 669 | // reached the EOF. |
| 670 | EXPECT_LE(1U, fake_fec->GetReadOps().size()); |
| 671 | // This fallback doesn't count as an error-corrected operation since the |
| 672 | // operation hash was not available. |
| 673 | EXPECT_EQ(0U, GetSourceEccRecoveredFailures()); |
| 674 | } |
| 675 | |
Sen Jiang | 77ab7bd | 2018-05-22 17:24:23 -0700 | [diff] [blame] | 676 | TEST_F(DeltaPerformerTest, ChooseSourceFDTest) { |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 677 | constexpr size_t kSourceSize = 4 * 4096; |
| 678 | test_utils::ScopedTempFile source("Source-XXXXXX"); |
Sen Jiang | 77ab7bd | 2018-05-22 17:24:23 -0700 | [diff] [blame] | 679 | // Write invalid data to the source image, which doesn't match the expected |
| 680 | // hash. |
| 681 | brillo::Blob invalid_data(kSourceSize, 0x55); |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 682 | EXPECT_TRUE(test_utils::WriteFileVector(source.path(), invalid_data)); |
Sen Jiang | 77ab7bd | 2018-05-22 17:24:23 -0700 | [diff] [blame] | 683 | |
| 684 | performer_.source_fd_ = std::make_shared<EintrSafeFileDescriptor>(); |
Sen Jiang | 0779a15 | 2018-07-02 17:34:56 -0700 | [diff] [blame] | 685 | performer_.source_fd_->Open(source.path().c_str(), O_RDONLY); |
Sen Jiang | 77ab7bd | 2018-05-22 17:24:23 -0700 | [diff] [blame] | 686 | performer_.block_size_ = 4096; |
| 687 | |
| 688 | // Setup the fec file descriptor as the fake stream, which matches |
| 689 | // |expected_data|. |
| 690 | FakeFileDescriptor* fake_fec = SetFakeECCFile(kSourceSize); |
| 691 | brillo::Blob expected_data = FakeFileDescriptorData(kSourceSize); |
| 692 | |
| 693 | InstallOperation op; |
| 694 | *(op.add_src_extents()) = ExtentForRange(0, kSourceSize / 4096); |
| 695 | brillo::Blob src_hash; |
| 696 | EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash)); |
| 697 | op.set_src_sha256_hash(src_hash.data(), src_hash.size()); |
| 698 | |
| 699 | ErrorCode error = ErrorCode::kSuccess; |
| 700 | EXPECT_EQ(performer_.source_ecc_fd_, performer_.ChooseSourceFD(op, &error)); |
| 701 | EXPECT_EQ(ErrorCode::kSuccess, error); |
| 702 | // Verify that the fake_fec was actually used. |
| 703 | EXPECT_EQ(1U, fake_fec->GetReadOps().size()); |
| 704 | EXPECT_EQ(1U, GetSourceEccRecoveredFailures()); |
| 705 | } |
| 706 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 707 | TEST_F(DeltaPerformerTest, ExtentsToByteStringTest) { |
Allie Wood | 5687345 | 2015-03-27 17:48:40 -0700 | [diff] [blame] | 708 | uint64_t test[] = {1, 1, 4, 2, 0, 1}; |
Alex Vakulenko | 0103c36 | 2016-01-20 07:56:15 -0800 | [diff] [blame] | 709 | static_assert(arraysize(test) % 2 == 0, "Array size uneven"); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 710 | const uint64_t block_size = 4096; |
Allie Wood | 5687345 | 2015-03-27 17:48:40 -0700 | [diff] [blame] | 711 | const uint64_t file_length = 4 * block_size - 13; |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 712 | |
| 713 | google::protobuf::RepeatedPtrField<Extent> extents; |
| 714 | for (size_t i = 0; i < arraysize(test); i += 2) { |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 715 | *(extents.Add()) = ExtentForRange(test[i], test[i + 1]); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 716 | } |
| 717 | |
Allie Wood | 5687345 | 2015-03-27 17:48:40 -0700 | [diff] [blame] | 718 | string expected_output = "4096:4096,16384:8192,0:4083"; |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 719 | string actual_output; |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 720 | EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString( |
| 721 | extents, block_size, file_length, &actual_output)); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 722 | EXPECT_EQ(expected_output, actual_output); |
| 723 | } |
Darin Petkov | 68c10d1 | 2010-10-14 09:24:37 -0700 | [diff] [blame] | 724 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 725 | TEST_F(DeltaPerformerTest, ValidateManifestFullGoodTest) { |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 726 | // The Manifest we are validating. |
| 727 | DeltaArchiveManifest manifest; |
| 728 | manifest.mutable_new_kernel_info(); |
| 729 | manifest.mutable_new_rootfs_info(); |
Alex Deymo | cbf0989 | 2015-09-11 16:13:16 -0700 | [diff] [blame] | 730 | manifest.set_minor_version(kFullPayloadMinorVersion); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 731 | |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 732 | RunManifestValidation(manifest, |
| 733 | kChromeOSMajorPayloadVersion, |
| 734 | InstallPayloadType::kFull, |
Sen Jiang | 3e728fe | 2015-11-05 11:37:23 -0800 | [diff] [blame] | 735 | ErrorCode::kSuccess); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 736 | } |
| 737 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 738 | TEST_F(DeltaPerformerTest, ValidateManifestDeltaGoodTest) { |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 739 | // The Manifest we are validating. |
| 740 | DeltaArchiveManifest manifest; |
| 741 | manifest.mutable_old_kernel_info(); |
| 742 | manifest.mutable_old_rootfs_info(); |
| 743 | manifest.mutable_new_kernel_info(); |
| 744 | manifest.mutable_new_rootfs_info(); |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 745 | manifest.set_minor_version(kMaxSupportedMinorPayloadVersion); |
| 746 | |
| 747 | RunManifestValidation(manifest, |
| 748 | kChromeOSMajorPayloadVersion, |
| 749 | InstallPayloadType::kDelta, |
| 750 | ErrorCode::kSuccess); |
| 751 | } |
| 752 | |
| 753 | TEST_F(DeltaPerformerTest, ValidateManifestDeltaMinGoodTest) { |
| 754 | // The Manifest we are validating. |
| 755 | DeltaArchiveManifest manifest; |
| 756 | manifest.mutable_old_kernel_info(); |
| 757 | manifest.mutable_old_rootfs_info(); |
| 758 | manifest.mutable_new_kernel_info(); |
| 759 | manifest.mutable_new_rootfs_info(); |
| 760 | manifest.set_minor_version(kMinSupportedMinorPayloadVersion); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 761 | |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 762 | RunManifestValidation(manifest, |
| 763 | kChromeOSMajorPayloadVersion, |
| 764 | InstallPayloadType::kDelta, |
Sen Jiang | 3e728fe | 2015-11-05 11:37:23 -0800 | [diff] [blame] | 765 | ErrorCode::kSuccess); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 766 | } |
| 767 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 768 | TEST_F(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) { |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 769 | // The Manifest we are validating. |
| 770 | DeltaArchiveManifest manifest; |
| 771 | |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 772 | RunManifestValidation(manifest, |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 773 | kMaxSupportedMajorPayloadVersion, |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 774 | InstallPayloadType::kFull, |
| 775 | ErrorCode::kSuccess); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 776 | } |
| 777 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 778 | TEST_F(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) { |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 779 | // The Manifest we are validating. |
| 780 | DeltaArchiveManifest manifest; |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 781 | // Add an empty old_rootfs_info() to trick the DeltaPerformer into think that |
| 782 | // this is a delta payload manifest with a missing minor version. |
| 783 | manifest.mutable_old_rootfs_info(); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 784 | |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 785 | RunManifestValidation(manifest, |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 786 | kMaxSupportedMajorPayloadVersion, |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 787 | InstallPayloadType::kDelta, |
| 788 | ErrorCode::kUnsupportedMinorPayloadVersion); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 789 | } |
| 790 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 791 | TEST_F(DeltaPerformerTest, ValidateManifestFullOldKernelTest) { |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 792 | // The Manifest we are validating. |
| 793 | DeltaArchiveManifest manifest; |
| 794 | manifest.mutable_old_kernel_info(); |
| 795 | manifest.mutable_new_kernel_info(); |
| 796 | manifest.mutable_new_rootfs_info(); |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 797 | manifest.set_minor_version(kMaxSupportedMinorPayloadVersion); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 798 | |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 799 | RunManifestValidation(manifest, |
| 800 | kChromeOSMajorPayloadVersion, |
| 801 | InstallPayloadType::kFull, |
Sen Jiang | 3e728fe | 2015-11-05 11:37:23 -0800 | [diff] [blame] | 802 | ErrorCode::kPayloadMismatchedType); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 803 | } |
| 804 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 805 | TEST_F(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) { |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 806 | // The Manifest we are validating. |
| 807 | DeltaArchiveManifest manifest; |
| 808 | manifest.mutable_old_rootfs_info(); |
| 809 | manifest.mutable_new_kernel_info(); |
| 810 | manifest.mutable_new_rootfs_info(); |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 811 | manifest.set_minor_version(kMaxSupportedMinorPayloadVersion); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 812 | |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 813 | RunManifestValidation(manifest, |
| 814 | kChromeOSMajorPayloadVersion, |
| 815 | InstallPayloadType::kFull, |
Sen Jiang | 3e728fe | 2015-11-05 11:37:23 -0800 | [diff] [blame] | 816 | ErrorCode::kPayloadMismatchedType); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 817 | } |
| 818 | |
Sen Jiang | c8f6b7a | 2015-10-21 11:09:59 -0700 | [diff] [blame] | 819 | TEST_F(DeltaPerformerTest, ValidateManifestFullPartitionUpdateTest) { |
| 820 | // The Manifest we are validating. |
| 821 | DeltaArchiveManifest manifest; |
| 822 | PartitionUpdate* partition = manifest.add_partitions(); |
| 823 | partition->mutable_old_partition_info(); |
| 824 | partition->mutable_new_partition_info(); |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 825 | manifest.set_minor_version(kMaxSupportedMinorPayloadVersion); |
Sen Jiang | c8f6b7a | 2015-10-21 11:09:59 -0700 | [diff] [blame] | 826 | |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 827 | RunManifestValidation(manifest, |
| 828 | kBrilloMajorPayloadVersion, |
| 829 | InstallPayloadType::kFull, |
Sen Jiang | 3e728fe | 2015-11-05 11:37:23 -0800 | [diff] [blame] | 830 | ErrorCode::kPayloadMismatchedType); |
Sen Jiang | c8f6b7a | 2015-10-21 11:09:59 -0700 | [diff] [blame] | 831 | } |
| 832 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 833 | TEST_F(DeltaPerformerTest, ValidateManifestBadMinorVersion) { |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 834 | // The Manifest we are validating. |
| 835 | DeltaArchiveManifest manifest; |
| 836 | |
| 837 | // Generate a bad version number. |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 838 | manifest.set_minor_version(kMaxSupportedMinorPayloadVersion + 10000); |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 839 | // Mark the manifest as a delta payload by setting old_rootfs_info. |
| 840 | manifest.mutable_old_rootfs_info(); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 841 | |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 842 | RunManifestValidation(manifest, |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 843 | kMaxSupportedMajorPayloadVersion, |
Alex Deymo | 64d9878 | 2016-02-05 18:03:48 -0800 | [diff] [blame] | 844 | InstallPayloadType::kDelta, |
| 845 | ErrorCode::kUnsupportedMinorPayloadVersion); |
Don Garrett | b8dd1d9 | 2013-11-22 17:40:02 -0800 | [diff] [blame] | 846 | } |
| 847 | |
Sen Jiang | 5011df6 | 2017-06-28 17:13:19 -0700 | [diff] [blame] | 848 | TEST_F(DeltaPerformerTest, ValidateManifestDowngrade) { |
| 849 | // The Manifest we are validating. |
| 850 | DeltaArchiveManifest manifest; |
| 851 | |
| 852 | manifest.set_minor_version(kFullPayloadMinorVersion); |
| 853 | manifest.set_max_timestamp(1); |
| 854 | fake_hardware_.SetBuildTimestamp(2); |
| 855 | |
| 856 | RunManifestValidation(manifest, |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 857 | kMaxSupportedMajorPayloadVersion, |
Sen Jiang | 5011df6 | 2017-06-28 17:13:19 -0700 | [diff] [blame] | 858 | InstallPayloadType::kFull, |
| 859 | ErrorCode::kPayloadTimestampError); |
| 860 | } |
| 861 | |
Sen Jiang | b8060e4 | 2015-09-24 17:30:50 -0700 | [diff] [blame] | 862 | TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeTest) { |
Eric Caruso | 4495bfe | 2018-01-23 16:34:20 -0800 | [diff] [blame] | 863 | unsigned int seed = time(nullptr); |
Sen Jiang | b8060e4 | 2015-09-24 17:30:50 -0700 | [diff] [blame] | 864 | EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic))); |
| 865 | |
| 866 | uint64_t major_version = htobe64(kBrilloMajorPayloadVersion); |
| 867 | EXPECT_TRUE(performer_.Write(&major_version, 8)); |
| 868 | |
Eric Caruso | 4495bfe | 2018-01-23 16:34:20 -0800 | [diff] [blame] | 869 | uint64_t manifest_size = rand_r(&seed) % 256; |
Sen Jiang | b8060e4 | 2015-09-24 17:30:50 -0700 | [diff] [blame] | 870 | uint64_t manifest_size_be = htobe64(manifest_size); |
| 871 | EXPECT_TRUE(performer_.Write(&manifest_size_be, 8)); |
| 872 | |
Eric Caruso | 4495bfe | 2018-01-23 16:34:20 -0800 | [diff] [blame] | 873 | uint32_t metadata_signature_size = rand_r(&seed) % 256; |
Sen Jiang | b8060e4 | 2015-09-24 17:30:50 -0700 | [diff] [blame] | 874 | uint32_t metadata_signature_size_be = htobe32(metadata_signature_size); |
| 875 | EXPECT_TRUE(performer_.Write(&metadata_signature_size_be, 4)); |
| 876 | |
| 877 | EXPECT_LT(performer_.Close(), 0); |
| 878 | |
| 879 | EXPECT_TRUE(performer_.IsHeaderParsed()); |
Sen Jiang | 9c89e84 | 2018-02-02 13:51:21 -0800 | [diff] [blame] | 880 | EXPECT_EQ(kBrilloMajorPayloadVersion, performer_.major_payload_version_); |
| 881 | EXPECT_EQ(24 + manifest_size, performer_.metadata_size_); // 4 + 8 + 8 + 4 |
Sen Jiang | 76bfa74 | 2015-10-12 17:13:26 -0700 | [diff] [blame] | 882 | EXPECT_EQ(metadata_signature_size, performer_.metadata_signature_size_); |
| 883 | } |
| 884 | |
Sen Jiang | 9c89e84 | 2018-02-02 13:51:21 -0800 | [diff] [blame] | 885 | TEST_F(DeltaPerformerTest, BrilloParsePayloadMetadataTest) { |
Amin Hassani | 008c458 | 2019-01-13 16:22:47 -0800 | [diff] [blame^] | 886 | brillo::Blob payload_data = GeneratePayload( |
| 887 | {}, {}, true, kBrilloMajorPayloadVersion, kSourceMinorPayloadVersion); |
Sen Jiang | 76bfa74 | 2015-10-12 17:13:26 -0700 | [diff] [blame] | 888 | install_plan_.hash_checks_mandatory = true; |
Sen Jiang | 260f03b | 2016-03-21 15:34:58 -0700 | [diff] [blame] | 889 | performer_.set_public_key_path(GetBuildArtifactsPath(kUnittestPublicKeyPath)); |
Sen Jiang | 9c89e84 | 2018-02-02 13:51:21 -0800 | [diff] [blame] | 890 | ErrorCode error; |
| 891 | EXPECT_EQ(MetadataParseResult::kSuccess, |
| 892 | performer_.ParsePayloadMetadata(payload_data, &error)); |
| 893 | EXPECT_EQ(ErrorCode::kSuccess, error); |
Sen Jiang | b8060e4 | 2015-09-24 17:30:50 -0700 | [diff] [blame] | 894 | } |
| 895 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 896 | TEST_F(DeltaPerformerTest, BadDeltaMagicTest) { |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 897 | EXPECT_TRUE(performer_.Write("junk", 4)); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 898 | EXPECT_FALSE(performer_.Write("morejunk", 8)); |
| 899 | EXPECT_LT(performer_.Close(), 0); |
Darin Petkov | 934bb41 | 2010-11-18 11:21:35 -0800 | [diff] [blame] | 900 | } |
| 901 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 902 | TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) { |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 903 | DoMetadataSizeTest(0, 75456, true); |
Jay Srinivasan | 51dcf26 | 2012-09-13 17:24:32 -0700 | [diff] [blame] | 904 | } |
| 905 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 906 | TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) { |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 907 | DoMetadataSizeTest(0, 123456, false); |
| 908 | } |
| 909 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 910 | TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) { |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 911 | DoMetadataSizeTest(13000, 140000, true); |
| 912 | } |
| 913 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 914 | TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) { |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 915 | DoMetadataSizeTest(40000, 50000, false); |
| 916 | } |
| 917 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 918 | TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) { |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 919 | DoMetadataSizeTest(85376, 85376, true); |
| 920 | } |
| 921 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 922 | TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) { |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 923 | DoMetadataSignatureTest(kEmptyMetadataSignature, true, true); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 924 | } |
| 925 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 926 | TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) { |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 927 | DoMetadataSignatureTest(kEmptyMetadataSignature, true, false); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 928 | } |
| 929 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 930 | TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) { |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 931 | DoMetadataSignatureTest(kInvalidMetadataSignature, true, true); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 932 | } |
| 933 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 934 | TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) { |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 935 | DoMetadataSignatureTest(kInvalidMetadataSignature, true, false); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 936 | } |
| 937 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 938 | TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) { |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 939 | DoMetadataSignatureTest(kValidMetadataSignature, false, true); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 940 | } |
| 941 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 942 | TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) { |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 943 | DoMetadataSignatureTest(kValidMetadataSignature, true, true); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 944 | } |
| 945 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 946 | TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) { |
Sen Jiang | d78b389 | 2015-09-25 15:19:31 -0700 | [diff] [blame] | 947 | DoMetadataSignatureTest(kValidMetadataSignature, true, false); |
Jay Srinivasan | 738fdf3 | 2012-12-07 17:40:54 -0800 | [diff] [blame] | 948 | } |
| 949 | |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 950 | TEST_F(DeltaPerformerTest, UsePublicKeyFromResponse) { |
David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 951 | // The result of the GetPublicKeyResponse() method is based on three things |
| 952 | // |
| 953 | // 1. Whether it's an official build; and |
| 954 | // 2. Whether the Public RSA key to be used is in the root filesystem; and |
Alex Vakulenko | 072359c | 2014-07-18 11:41:07 -0700 | [diff] [blame] | 955 | // 3. Whether the response has a public key |
David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 956 | // |
| 957 | // We test all eight combinations to ensure that we only use the |
| 958 | // public key in the response if |
| 959 | // |
| 960 | // a. it's not an official build; and |
| 961 | // b. there is no key in the root filesystem. |
| 962 | |
Sen Jiang | 371615b | 2016-04-13 15:54:29 -0700 | [diff] [blame] | 963 | base::ScopedTempDir temp_dir; |
| 964 | ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
Jay Civelli | a78ddf8 | 2017-03-30 11:02:03 -0700 | [diff] [blame] | 965 | string non_existing_file = temp_dir.GetPath().Append("non-existing").value(); |
| 966 | string existing_file = temp_dir.GetPath().Append("existing").value(); |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 967 | constexpr char kExistingKey[] = "Existing"; |
| 968 | ASSERT_TRUE(test_utils::WriteFileString(existing_file, kExistingKey)); |
David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 969 | |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 970 | // Non-official build, non-existing public-key, key in response -> |
| 971 | // kResponseKey |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 972 | fake_hardware_.SetIsOfficialBuild(false); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 973 | performer_.public_key_path_ = non_existing_file; |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 974 | // This is the result of 'echo -n "Response" | base64' and is not meant to be |
| 975 | // a valid public key, but it is valid base-64. |
| 976 | constexpr char kResponseKey[] = "Response"; |
| 977 | constexpr char kBase64ResponseKey[] = "UmVzcG9uc2U="; |
| 978 | install_plan_.public_key_rsa = kBase64ResponseKey; |
| 979 | string public_key; |
| 980 | EXPECT_TRUE(performer_.GetPublicKey(&public_key)); |
| 981 | EXPECT_EQ(public_key, kResponseKey); |
| 982 | // Same with official build -> no key |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 983 | fake_hardware_.SetIsOfficialBuild(true); |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 984 | EXPECT_TRUE(performer_.GetPublicKey(&public_key)); |
| 985 | EXPECT_TRUE(public_key.empty()); |
David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 986 | |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 987 | // Non-official build, existing public-key, key in response -> kExistingKey |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 988 | fake_hardware_.SetIsOfficialBuild(false); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 989 | performer_.public_key_path_ = existing_file; |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 990 | install_plan_.public_key_rsa = kBase64ResponseKey; |
| 991 | EXPECT_TRUE(performer_.GetPublicKey(&public_key)); |
| 992 | EXPECT_EQ(public_key, kExistingKey); |
| 993 | // Same with official build -> kExistingKey |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 994 | fake_hardware_.SetIsOfficialBuild(true); |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 995 | EXPECT_TRUE(performer_.GetPublicKey(&public_key)); |
| 996 | EXPECT_EQ(public_key, kExistingKey); |
David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 997 | |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 998 | // Non-official build, non-existing public-key, no key in response -> no key |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 999 | fake_hardware_.SetIsOfficialBuild(false); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 1000 | performer_.public_key_path_ = non_existing_file; |
| 1001 | install_plan_.public_key_rsa = ""; |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 1002 | EXPECT_TRUE(performer_.GetPublicKey(&public_key)); |
| 1003 | EXPECT_TRUE(public_key.empty()); |
| 1004 | // Same with official build -> no key |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 1005 | fake_hardware_.SetIsOfficialBuild(true); |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 1006 | EXPECT_TRUE(performer_.GetPublicKey(&public_key)); |
| 1007 | EXPECT_TRUE(public_key.empty()); |
David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 1008 | |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 1009 | // Non-official build, existing public-key, no key in response -> kExistingKey |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 1010 | fake_hardware_.SetIsOfficialBuild(false); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 1011 | performer_.public_key_path_ = existing_file; |
| 1012 | install_plan_.public_key_rsa = ""; |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 1013 | EXPECT_TRUE(performer_.GetPublicKey(&public_key)); |
| 1014 | EXPECT_EQ(public_key, kExistingKey); |
| 1015 | // Same with official build -> kExistingKey |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 1016 | fake_hardware_.SetIsOfficialBuild(true); |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 1017 | EXPECT_TRUE(performer_.GetPublicKey(&public_key)); |
| 1018 | EXPECT_EQ(public_key, kExistingKey); |
David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 1019 | |
| 1020 | // Non-official build, non-existing public-key, key in response |
| 1021 | // but invalid base64 -> false |
Alex Deymo | 542c19b | 2015-12-03 07:43:31 -0300 | [diff] [blame] | 1022 | fake_hardware_.SetIsOfficialBuild(false); |
Sen Jiang | 2d528b4 | 2015-09-25 11:18:12 -0700 | [diff] [blame] | 1023 | performer_.public_key_path_ = non_existing_file; |
| 1024 | install_plan_.public_key_rsa = "not-valid-base64"; |
Sen Jiang | 08c6da1 | 2019-01-07 18:28:56 -0800 | [diff] [blame] | 1025 | EXPECT_FALSE(performer_.GetPublicKey(&public_key)); |
David Zeuthen | e7f8917 | 2013-10-31 10:21:04 -0700 | [diff] [blame] | 1026 | } |
| 1027 | |
Alex Deymo | cbf0989 | 2015-09-11 16:13:16 -0700 | [diff] [blame] | 1028 | TEST_F(DeltaPerformerTest, ConfVersionsMatch) { |
| 1029 | // Test that the versions in update_engine.conf that is installed to the |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 1030 | // image match the maximum supported delta versions in the update engine. |
Allie Wood | 78750a4 | 2015-02-11 15:42:11 -0800 | [diff] [blame] | 1031 | uint32_t minor_version; |
Alex Vakulenko | 3f39d5c | 2015-10-13 09:27:13 -0700 | [diff] [blame] | 1032 | brillo::KeyValueStore store; |
Sen Jiang | ee63c6e | 2016-03-30 14:01:02 -0700 | [diff] [blame] | 1033 | EXPECT_TRUE(store.Load(GetBuildArtifactsPath().Append("update_engine.conf"))); |
Alex Deymo | b42b98d | 2015-07-06 17:42:38 -0700 | [diff] [blame] | 1034 | EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version)); |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 1035 | EXPECT_EQ(kMaxSupportedMinorPayloadVersion, minor_version); |
Alex Deymo | cbf0989 | 2015-09-11 16:13:16 -0700 | [diff] [blame] | 1036 | |
| 1037 | string major_version_str; |
| 1038 | uint64_t major_version; |
| 1039 | EXPECT_TRUE(store.GetString("PAYLOAD_MAJOR_VERSION", &major_version_str)); |
| 1040 | EXPECT_TRUE(base::StringToUint64(major_version_str, &major_version)); |
Sen Jiang | f123663 | 2018-05-11 16:03:23 -0700 | [diff] [blame] | 1041 | EXPECT_EQ(kMaxSupportedMajorPayloadVersion, major_version); |
Allie Wood | 78750a4 | 2015-02-11 15:42:11 -0800 | [diff] [blame] | 1042 | } |
| 1043 | |
Andrew de los Reyes | 09e56d6 | 2010-04-23 13:45:53 -0700 | [diff] [blame] | 1044 | } // namespace chromeos_update_engine |