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