1 /*
2 * Copyright (C) 2019 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 <sys/stat.h>
18 #include <sys/types.h>
19 #include <unistd.h>
20
21 #include <android-base/file.h>
22 #include <gtest/gtest.h>
23 #include <openssl/sha.h>
24 #include <sparse/sparse.h>
25
26 #include "reader.h"
27 #include "super_vbmeta_format.h"
28 #include "utility.h"
29 #include "writer.h"
30
31 #define FAKE_DATA_SIZE 40960
32 #define FAKE_PARTITION_SIZE FAKE_DATA_SIZE * 25
33
34 using android::base::Result;
35 using android::fs_mgr::GetFileSize;
36 using android::fs_mgr::ReadVBMetaImage;
37 using SparsePtr = std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)>;
38
GeneratePartitionImage(int fd,const std::string & file_name,const std::string & partition_name)39 void GeneratePartitionImage(int fd, const std::string& file_name,
40 const std::string& partition_name) {
41 std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(FAKE_DATA_SIZE);
42 for (size_t c = 0; c < FAKE_DATA_SIZE; c++) {
43 buffer[c] = uint8_t(c);
44 }
45
46 SparsePtr file(sparse_file_new(512 /* block size */, FAKE_DATA_SIZE), sparse_file_destroy);
47 EXPECT_TRUE(file);
48 EXPECT_EQ(0, sparse_file_add_data(file.get(), buffer.get(), FAKE_DATA_SIZE,
49 0 /* offset in blocks */));
50 EXPECT_EQ(0, sparse_file_write(file.get(), fd, false /* gz */, true /* sparse */,
51 false /* crc */));
52
53 std::stringstream cmd;
54 cmd << "avbtool add_hashtree_footer"
55 << " --image " << file_name << " --partition_name " << partition_name
56 << " --partition_size " << FAKE_PARTITION_SIZE << " --algorithm SHA256_RSA2048"
57 << " --key external/avb/test/data/testkey_rsa2048.pem";
58
59 int rc = system(cmd.str().c_str());
60 EXPECT_TRUE(WIFEXITED(rc));
61 EXPECT_EQ(WEXITSTATUS(rc), 0);
62 }
63
GenerateVBMetaImage(const std::string & vbmeta_file_name,const std::string & include_file_name)64 void GenerateVBMetaImage(const std::string& vbmeta_file_name,
65 const std::string& include_file_name) {
66 std::stringstream cmd;
67 cmd << "avbtool make_vbmeta_image"
68 << " --output " << vbmeta_file_name << " --include_descriptors_from_image "
69 << include_file_name;
70
71 int rc = system(cmd.str().c_str());
72 EXPECT_TRUE(WIFEXITED(rc));
73 EXPECT_EQ(WEXITSTATUS(rc), 0);
74 }
75
ReadVBMetaImageFromFile(const std::string & file)76 std::string ReadVBMetaImageFromFile(const std::string& file) {
77 android::base::unique_fd fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
78 EXPECT_GT(fd, 0);
79 Result<uint64_t> file_size = GetFileSize(fd);
80 EXPECT_RESULT_OK(file_size);
81 std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(VBMETA_IMAGE_MAX_SIZE);
82 EXPECT_TRUE(android::base::ReadFully(fd, buffer.get(), file_size.value()));
83 return std::string(reinterpret_cast<char*>(buffer.get()), VBMETA_IMAGE_MAX_SIZE);
84 }
85
TEST(VBMetaTableTest,VBMetaTableBasic)86 TEST(VBMetaTableTest, VBMetaTableBasic) {
87 TemporaryDir td;
88
89 // Generate Partition Image
90 TemporaryFile system_tf(std::string(td.path));
91 std::string system_path(system_tf.path);
92 GeneratePartitionImage(system_tf.fd, system_path, "system");
93 system_tf.release();
94
95 TemporaryFile vendor_tf(std::string(td.path));
96 std::string vendor_path(vendor_tf.path);
97 GeneratePartitionImage(vendor_tf.fd, vendor_path, "vendor");
98 vendor_tf.release();
99
100 TemporaryFile product_tf(std::string(td.path));
101 std::string product_path(product_tf.path);
102 GeneratePartitionImage(product_tf.fd, product_path, "product");
103 product_tf.release();
104
105 // Generate VBMeta Image
106 std::string vbmeta_system_path(td.path);
107 vbmeta_system_path.append("/vbmeta_system.img");
108 GenerateVBMetaImage(vbmeta_system_path, system_path);
109
110 std::string vbmeta_vendor_path(td.path);
111 vbmeta_vendor_path.append("/vbmeta_vendor.img");
112 GenerateVBMetaImage(vbmeta_vendor_path, vendor_path);
113
114 std::string vbmeta_product_path(td.path);
115 vbmeta_product_path.append("/vbmeta_product.img");
116 GenerateVBMetaImage(vbmeta_product_path, product_path);
117
118 // Generate Super VBMeta Image
119 std::string super_vbmeta_path(td.path);
120 super_vbmeta_path.append("/super_vbmeta.img");
121
122 std::stringstream cmd;
123 cmd << "vbmake"
124 << " --image "
125 << "vbmeta_system"
126 << "=" << vbmeta_system_path << " --image "
127 << "vbmeta_vendor"
128 << "=" << vbmeta_vendor_path << " --image "
129 << "vbmeta_product"
130 << "=" << vbmeta_product_path << " --output=" << super_vbmeta_path;
131
132 int rc = system(cmd.str().c_str());
133 ASSERT_TRUE(WIFEXITED(rc));
134 ASSERT_EQ(WEXITSTATUS(rc), 0);
135
136 android::base::unique_fd fd(open(super_vbmeta_path.c_str(), O_RDONLY | O_CLOEXEC));
137 EXPECT_GT(fd, 0);
138
139 // Check the size of vbmeta table
140 Result<uint64_t> super_vbmeta_size = GetFileSize(fd);
141 EXPECT_RESULT_OK(super_vbmeta_size);
142 EXPECT_EQ(super_vbmeta_size.value(),
143 SUPER_VBMETA_TABLE_MAX_SIZE * 2 + VBMETA_IMAGE_MAX_SIZE * 3);
144
145 // Check Primary vbmeta table is equal to Backup one
146 VBMetaTable table;
147 EXPECT_RESULT_OK(android::fs_mgr::ReadPrimaryVBMetaTable(fd, &table));
148 VBMetaTable table_backup;
149 EXPECT_RESULT_OK(android::fs_mgr::ReadBackupVBMetaTable(fd, &table_backup));
150 EXPECT_EQ(android::fs_mgr::SerializeVBMetaTable(table),
151 android::fs_mgr::SerializeVBMetaTable(table_backup));
152
153 // Check vbmeta table Header Checksum
154 std::string serial_table = android::fs_mgr::SerializeVBMetaTable(table);
155 std::string serial_removed_checksum(serial_table);
156 // Replace checksum 32 bytes (starts at 16th byte) with 0
157 serial_removed_checksum.replace(16, 32, 32, 0);
158 uint8_t test_checksum[32];
159 ::SHA256(reinterpret_cast<const uint8_t*>(serial_removed_checksum.c_str()),
160 table.header.total_size, &test_checksum[0]);
161 EXPECT_EQ(memcmp(table.header.checksum, test_checksum, 32), 0);
162
163 // Check vbmeta table descriptors and vbmeta images
164 EXPECT_EQ(table.descriptors.size(), 3);
165
166 EXPECT_EQ(table.descriptors[0].vbmeta_index, 0);
167 EXPECT_EQ(table.descriptors[0].vbmeta_name_length, 14);
168 EXPECT_EQ(table.descriptors[0].vbmeta_name, "vbmeta_product");
169 Result<std::string> vbmeta_product_content = ReadVBMetaImage(fd, 0);
170 EXPECT_RESULT_OK(vbmeta_product_content);
171 EXPECT_EQ(ReadVBMetaImageFromFile(vbmeta_product_path), vbmeta_product_content.value());
172
173 EXPECT_EQ(table.descriptors[1].vbmeta_index, 1);
174 EXPECT_EQ(table.descriptors[1].vbmeta_name_length, 13);
175 EXPECT_EQ(table.descriptors[1].vbmeta_name, "vbmeta_system");
176 Result<std::string> vbmeta_system_content = ReadVBMetaImage(fd, 1);
177 EXPECT_RESULT_OK(vbmeta_system_content);
178 EXPECT_EQ(ReadVBMetaImageFromFile(vbmeta_system_path), vbmeta_system_content.value());
179
180 EXPECT_EQ(table.descriptors[2].vbmeta_index, 2);
181 EXPECT_EQ(table.descriptors[2].vbmeta_name_length, 13);
182 EXPECT_EQ(table.descriptors[2].vbmeta_name, "vbmeta_vendor");
183 Result<std::string> vbmeta_vendor_content = ReadVBMetaImage(fd, 2);
184 EXPECT_RESULT_OK(vbmeta_vendor_content);
185 EXPECT_EQ(ReadVBMetaImageFromFile(vbmeta_vendor_path), vbmeta_vendor_content.value());
186 }
187
main(int argc,char ** argv)188 int main(int argc, char** argv) {
189 ::testing::InitGoogleTest(&argc, argv);
190 return RUN_ALL_TESTS();
191 }
192