1 //
2 // Copyright (C) 2018 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
17 #include "update_engine/payload_consumer/verity_writer_android.h"
18
19 #include <fcntl.h>
20
21 #include <brillo/secure_blob.h>
22 #include <gtest/gtest.h>
23
24 #include "update_engine/common/test_utils.h"
25 #include "update_engine/common/utils.h"
26 #include "update_engine/payload_consumer/file_descriptor.h"
27
28 namespace chromeos_update_engine {
29
30 class VerityWriterAndroidTest : public ::testing::Test {
31 protected:
SetUp()32 void SetUp() override {
33 partition_.target_path = temp_file_.path();
34 partition_.block_size = 4096;
35 partition_.hash_tree_data_offset = 0;
36 partition_.hash_tree_data_size = 4096;
37 partition_.hash_tree_offset = 4096;
38 partition_.hash_tree_size = 4096;
39 partition_.hash_tree_algorithm = "sha1";
40 partition_.fec_roots = 2;
41 partition_fd_ = std::make_shared<EintrSafeFileDescriptor>();
42 partition_fd_->Open(partition_.target_path.c_str(), O_RDWR);
43 }
44
45 VerityWriterAndroid verity_writer_;
46 InstallPlan::Partition partition_;
47 FileDescriptorPtr partition_fd_;
48 ScopedTempFile temp_file_;
49 };
50
TEST_F(VerityWriterAndroidTest,SimpleTest)51 TEST_F(VerityWriterAndroidTest, SimpleTest) {
52 brillo::Blob part_data(8192);
53 test_utils::WriteFileVector(partition_.target_path, part_data);
54 ASSERT_TRUE(verity_writer_.Init(partition_));
55 ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), 4096));
56 ASSERT_TRUE(verity_writer_.Update(4096, part_data.data() + 4096, 4096));
57 ASSERT_TRUE(verity_writer_.Finalize(partition_fd_, partition_fd_));
58 brillo::Blob actual_part;
59 utils::ReadFile(partition_.target_path, &actual_part);
60 // dd if=/dev/zero bs=4096 count=1 2>/dev/null | sha1sum | xxd -r -p |
61 // hexdump -v -e '/1 "0x%02x, "'
62 brillo::Blob hash = {0x1c, 0xea, 0xf7, 0x3d, 0xf4, 0x0e, 0x53,
63 0x1d, 0xf3, 0xbf, 0xb2, 0x6b, 0x4f, 0xb7,
64 0xcd, 0x95, 0xfb, 0x7b, 0xff, 0x1d};
65 memcpy(part_data.data() + 4096, hash.data(), hash.size());
66 ASSERT_EQ(part_data, actual_part);
67 }
68
TEST_F(VerityWriterAndroidTest,NoOpTest)69 TEST_F(VerityWriterAndroidTest, NoOpTest) {
70 partition_.hash_tree_data_size = 0;
71 partition_.hash_tree_size = 0;
72 brillo::Blob part_data(4096);
73 ASSERT_TRUE(verity_writer_.Init(partition_));
74 ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), part_data.size()));
75 ASSERT_TRUE(verity_writer_.Update(4096, part_data.data(), part_data.size()));
76 ASSERT_TRUE(verity_writer_.Update(8192, part_data.data(), part_data.size()));
77 }
78
TEST_F(VerityWriterAndroidTest,DiscontinuedRead)79 TEST_F(VerityWriterAndroidTest, DiscontinuedRead) {
80 partition_.hash_tree_data_size = 8192;
81 partition_.hash_tree_size = 4096;
82 brillo::Blob part_data(4096);
83 ASSERT_TRUE(verity_writer_.Init(partition_));
84 ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), part_data.size()));
85 ASSERT_FALSE(verity_writer_.Update(8192, part_data.data(), part_data.size()));
86 }
87
TEST_F(VerityWriterAndroidTest,InvalidHashAlgorithmTest)88 TEST_F(VerityWriterAndroidTest, InvalidHashAlgorithmTest) {
89 partition_.hash_tree_algorithm = "sha123";
90 ASSERT_FALSE(verity_writer_.Init(partition_));
91 }
92
TEST_F(VerityWriterAndroidTest,WrongHashTreeSizeTest)93 TEST_F(VerityWriterAndroidTest, WrongHashTreeSizeTest) {
94 partition_.hash_tree_size = 8192;
95 ASSERT_FALSE(verity_writer_.Init(partition_));
96 }
97
TEST_F(VerityWriterAndroidTest,SHA256Test)98 TEST_F(VerityWriterAndroidTest, SHA256Test) {
99 partition_.hash_tree_algorithm = "sha256";
100 brillo::Blob part_data(8192);
101 test_utils::WriteFileVector(partition_.target_path, part_data);
102 ASSERT_TRUE(verity_writer_.Init(partition_));
103 ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), 4096));
104 ASSERT_TRUE(verity_writer_.Update(4096, part_data.data() + 4096, 4096));
105 ASSERT_TRUE(verity_writer_.Finalize(partition_fd_, partition_fd_));
106 brillo::Blob actual_part;
107 utils::ReadFile(partition_.target_path, &actual_part);
108 // dd if=/dev/zero bs=4096 count=1 2>/dev/null | sha256sum | xxd -r -p |
109 // hexdump -v -e '/1 "0x%02x, "'
110 brillo::Blob hash = {0xad, 0x7f, 0xac, 0xb2, 0x58, 0x6f, 0xc6, 0xe9,
111 0x66, 0xc0, 0x04, 0xd7, 0xd1, 0xd1, 0x6b, 0x02,
112 0x4f, 0x58, 0x05, 0xff, 0x7c, 0xb4, 0x7c, 0x7a,
113 0x85, 0xda, 0xbd, 0x8b, 0x48, 0x89, 0x2c, 0xa7};
114 memcpy(part_data.data() + 4096, hash.data(), hash.size());
115 ASSERT_EQ(part_data, actual_part);
116 }
117
TEST_F(VerityWriterAndroidTest,NonZeroOffsetSHA256Test)118 TEST_F(VerityWriterAndroidTest, NonZeroOffsetSHA256Test) {
119 partition_.hash_tree_algorithm = "sha256";
120 partition_.hash_tree_data_offset = 100;
121 partition_.hash_tree_offset =
122 partition_.hash_tree_data_offset + partition_.hash_tree_data_size;
123 brillo::Blob part_data(8192 + partition_.hash_tree_data_offset);
124 test_utils::WriteFileVector(partition_.target_path, part_data);
125 ASSERT_TRUE(verity_writer_.Init(partition_));
126 ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), 4096));
127 ASSERT_TRUE(verity_writer_.Update(4096, part_data.data() + 4096, 4096));
128 ASSERT_TRUE(verity_writer_.Update(
129 8192, part_data.data() + 8192, partition_.hash_tree_data_offset));
130 ASSERT_TRUE(verity_writer_.Finalize(partition_fd_, partition_fd_));
131 brillo::Blob actual_part;
132 utils::ReadFile(partition_.target_path, &actual_part);
133 // dd if=/dev/zero bs=4096 count=1 2>/dev/null | sha256sum | xxd -r -p |
134 // hexdump -v -e '/1 "0x%02x, "'
135 brillo::Blob hash = {0xad, 0x7f, 0xac, 0xb2, 0x58, 0x6f, 0xc6, 0xe9,
136 0x66, 0xc0, 0x04, 0xd7, 0xd1, 0xd1, 0x6b, 0x02,
137 0x4f, 0x58, 0x05, 0xff, 0x7c, 0xb4, 0x7c, 0x7a,
138 0x85, 0xda, 0xbd, 0x8b, 0x48, 0x89, 0x2c, 0xa7};
139 memcpy(
140 part_data.data() + partition_.hash_tree_offset, hash.data(), hash.size());
141 ASSERT_EQ(part_data, actual_part);
142 }
143
TEST_F(VerityWriterAndroidTest,FECTest)144 TEST_F(VerityWriterAndroidTest, FECTest) {
145 partition_.fec_data_offset = 0;
146 partition_.fec_data_size = 4096;
147 partition_.fec_offset = 4096;
148 partition_.fec_size = 2 * 4096;
149 brillo::Blob part_data(3 * 4096, 0x1);
150 test_utils::WriteFileVector(partition_.target_path, part_data);
151 ASSERT_TRUE(verity_writer_.Init(partition_));
152 ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), part_data.size()));
153 ASSERT_TRUE(verity_writer_.Finalize(partition_fd_, partition_fd_));
154 brillo::Blob actual_part;
155 utils::ReadFile(partition_.target_path, &actual_part);
156 // Write FEC data.
157 for (size_t i = 4096; i < part_data.size(); i += 2) {
158 part_data[i] = 0x8e;
159 part_data[i + 1] = 0x8f;
160 }
161 ASSERT_EQ(part_data, actual_part);
162 }
163
164 } // namespace chromeos_update_engine
165