• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(
58       verity_writer_.Finalize(partition_fd_.get(), partition_fd_.get()));
59   brillo::Blob actual_part;
60   utils::ReadFile(partition_.target_path, &actual_part);
61   // dd if=/dev/zero bs=4096 count=1 2>/dev/null | sha1sum | xxd -r -p |
62   //     hexdump -v -e '/1 "0x%02x, "'
63   brillo::Blob hash = {0x1c, 0xea, 0xf7, 0x3d, 0xf4, 0x0e, 0x53,
64                        0x1d, 0xf3, 0xbf, 0xb2, 0x6b, 0x4f, 0xb7,
65                        0xcd, 0x95, 0xfb, 0x7b, 0xff, 0x1d};
66   memcpy(part_data.data() + 4096, hash.data(), hash.size());
67   ASSERT_EQ(part_data, actual_part);
68 }
69 
TEST_F(VerityWriterAndroidTest,NoOpTest)70 TEST_F(VerityWriterAndroidTest, NoOpTest) {
71   partition_.hash_tree_data_size = 0;
72   partition_.hash_tree_size = 0;
73   brillo::Blob part_data(4096);
74   ASSERT_TRUE(verity_writer_.Init(partition_));
75   ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), part_data.size()));
76   ASSERT_TRUE(verity_writer_.Update(4096, part_data.data(), part_data.size()));
77   ASSERT_TRUE(verity_writer_.Update(8192, part_data.data(), part_data.size()));
78 }
79 
TEST_F(VerityWriterAndroidTest,DiscontinuedRead)80 TEST_F(VerityWriterAndroidTest, DiscontinuedRead) {
81   partition_.hash_tree_data_size = 8192;
82   partition_.hash_tree_size = 4096;
83   brillo::Blob part_data(4096);
84   ASSERT_TRUE(verity_writer_.Init(partition_));
85   ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), part_data.size()));
86   ASSERT_FALSE(verity_writer_.Update(8192, part_data.data(), part_data.size()));
87 }
88 
TEST_F(VerityWriterAndroidTest,InvalidHashAlgorithmTest)89 TEST_F(VerityWriterAndroidTest, InvalidHashAlgorithmTest) {
90   partition_.hash_tree_algorithm = "sha123";
91   ASSERT_FALSE(verity_writer_.Init(partition_));
92 }
93 
TEST_F(VerityWriterAndroidTest,WrongHashTreeSizeTest)94 TEST_F(VerityWriterAndroidTest, WrongHashTreeSizeTest) {
95   partition_.hash_tree_size = 8192;
96   ASSERT_FALSE(verity_writer_.Init(partition_));
97 }
98 
TEST_F(VerityWriterAndroidTest,SHA256Test)99 TEST_F(VerityWriterAndroidTest, SHA256Test) {
100   partition_.hash_tree_algorithm = "sha256";
101   brillo::Blob part_data(8192);
102   test_utils::WriteFileVector(partition_.target_path, part_data);
103   ASSERT_TRUE(verity_writer_.Init(partition_));
104   ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), 4096));
105   ASSERT_TRUE(verity_writer_.Update(4096, part_data.data() + 4096, 4096));
106   ASSERT_TRUE(
107       verity_writer_.Finalize(partition_fd_.get(), partition_fd_.get()));
108   brillo::Blob actual_part;
109   utils::ReadFile(partition_.target_path, &actual_part);
110   // dd if=/dev/zero bs=4096 count=1 2>/dev/null | sha256sum | xxd -r -p |
111   //     hexdump -v -e '/1 "0x%02x, "'
112   brillo::Blob hash = {0xad, 0x7f, 0xac, 0xb2, 0x58, 0x6f, 0xc6, 0xe9,
113                        0x66, 0xc0, 0x04, 0xd7, 0xd1, 0xd1, 0x6b, 0x02,
114                        0x4f, 0x58, 0x05, 0xff, 0x7c, 0xb4, 0x7c, 0x7a,
115                        0x85, 0xda, 0xbd, 0x8b, 0x48, 0x89, 0x2c, 0xa7};
116   memcpy(part_data.data() + 4096, hash.data(), hash.size());
117   ASSERT_EQ(part_data, actual_part);
118 }
119 
TEST_F(VerityWriterAndroidTest,NonZeroOffsetSHA256Test)120 TEST_F(VerityWriterAndroidTest, NonZeroOffsetSHA256Test) {
121   partition_.hash_tree_algorithm = "sha256";
122   partition_.hash_tree_data_offset = 100;
123   partition_.hash_tree_offset =
124       partition_.hash_tree_data_offset + partition_.hash_tree_data_size;
125   brillo::Blob part_data(8192 + partition_.hash_tree_data_offset);
126   test_utils::WriteFileVector(partition_.target_path, part_data);
127   ASSERT_TRUE(verity_writer_.Init(partition_));
128   ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), 4096));
129   ASSERT_TRUE(verity_writer_.Update(4096, part_data.data() + 4096, 4096));
130   ASSERT_TRUE(verity_writer_.Update(
131       8192, part_data.data() + 8192, partition_.hash_tree_data_offset));
132   ASSERT_TRUE(
133       verity_writer_.Finalize(partition_fd_.get(), partition_fd_.get()));
134   brillo::Blob actual_part;
135   utils::ReadFile(partition_.target_path, &actual_part);
136   // dd if=/dev/zero bs=4096 count=1 2>/dev/null | sha256sum | xxd -r -p |
137   //     hexdump -v -e '/1 "0x%02x, "'
138   brillo::Blob hash = {0xad, 0x7f, 0xac, 0xb2, 0x58, 0x6f, 0xc6, 0xe9,
139                        0x66, 0xc0, 0x04, 0xd7, 0xd1, 0xd1, 0x6b, 0x02,
140                        0x4f, 0x58, 0x05, 0xff, 0x7c, 0xb4, 0x7c, 0x7a,
141                        0x85, 0xda, 0xbd, 0x8b, 0x48, 0x89, 0x2c, 0xa7};
142   memcpy(
143       part_data.data() + partition_.hash_tree_offset, hash.data(), hash.size());
144   ASSERT_EQ(part_data, actual_part);
145 }
146 
TEST_F(VerityWriterAndroidTest,FECTest)147 TEST_F(VerityWriterAndroidTest, FECTest) {
148   partition_.fec_data_offset = 0;
149   partition_.fec_data_size = 4096;
150   partition_.fec_offset = 4096;
151   partition_.fec_size = 2 * 4096;
152   brillo::Blob part_data(3 * 4096, 0x1);
153   test_utils::WriteFileVector(partition_.target_path, part_data);
154   ASSERT_TRUE(verity_writer_.Init(partition_));
155   ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), part_data.size()));
156   ASSERT_TRUE(
157       verity_writer_.Finalize(partition_fd_.get(), partition_fd_.get()));
158   brillo::Blob actual_part;
159   utils::ReadFile(partition_.target_path, &actual_part);
160   // Write FEC data.
161   for (size_t i = 4096; i < part_data.size(); i += 2) {
162     part_data[i] = 0x8e;
163     part_data[i + 1] = 0x8f;
164   }
165   ASSERT_EQ(part_data, actual_part);
166 }
167 
TEST_F(VerityWriterAndroidTest,HashTreeDisabled)168 TEST_F(VerityWriterAndroidTest, HashTreeDisabled) {
169   partition_.hash_tree_size = 0;
170   partition_.hash_tree_data_size = 0;
171   partition_.hash_tree_offset = 0;
172   partition_.hash_tree_data_offset = 0;
173 
174   partition_.fec_data_offset = 0;
175   partition_.fec_data_size = 4096;
176   partition_.fec_offset = 4096;
177   partition_.fec_size = 2 * 4096;
178   brillo::Blob part_data(3 * 4096, 0x1);
179   test_utils::WriteFileVector(partition_.target_path, part_data);
180   ASSERT_TRUE(verity_writer_.Init(partition_));
181   ASSERT_TRUE(verity_writer_.Update(0, part_data.data(), part_data.size()));
182   ASSERT_TRUE(
183       verity_writer_.Finalize(partition_fd_.get(), partition_fd_.get()));
184 }
185 
186 }  // namespace chromeos_update_engine
187