blob: 0a594037cd4cdb11c50385fd104c0744cc42c123 [file] [log] [blame]
Tao Bao83b07802017-04-26 14:30:56 -07001/*
2 * Copyright (C) 2017 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
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070017#include <update_verifier/update_verifier.h>
18
Tianjie Xu9eed65e2018-09-14 12:52:02 -070019#include <functional>
Tao Bao83b07802017-04-26 14:30:56 -070020#include <string>
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070021#include <unordered_map>
22#include <vector>
Tao Bao83b07802017-04-26 14:30:56 -070023
24#include <android-base/file.h>
Tao Bao1cc03512018-04-18 17:10:49 -070025#include <android-base/properties.h>
26#include <android-base/strings.h>
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070027#include <google/protobuf/repeated_field.h>
Tao Bao83b07802017-04-26 14:30:56 -070028#include <gtest/gtest.h>
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070029
30#include "care_map.pb.h"
Tao Bao83b07802017-04-26 14:30:56 -070031
Tianjie Xu446b64b2018-09-19 15:45:28 -070032using namespace std::string_literals;
33
Tao Bao83b07802017-04-26 14:30:56 -070034class UpdateVerifierTest : public ::testing::Test {
35 protected:
36 void SetUp() override {
Tao Bao1cc03512018-04-18 17:10:49 -070037 std::string verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
38 verity_supported = android::base::EqualsIgnoreCase(verity_mode, "enforcing");
Tianjie Xu446b64b2018-09-19 15:45:28 -070039
Tianjie Xu9eed65e2018-09-14 12:52:02 -070040 care_map_prefix_ = care_map_dir_.path + "/care_map"s;
Tianjie Xu446b64b2018-09-19 15:45:28 -070041 care_map_pb_ = care_map_dir_.path + "/care_map.pb"s;
42 care_map_txt_ = care_map_dir_.path + "/care_map.txt"s;
Tianjie Xu9eed65e2018-09-14 12:52:02 -070043 // Overrides the the care_map_prefix.
44 verifier_.set_care_map_prefix(care_map_prefix_);
45
46 property_id_ = "ro.build.fingerprint";
47 fingerprint_ = android::base::GetProperty(property_id_, "");
48 // Overrides the property_reader if we cannot read the given property on the device.
49 if (fingerprint_.empty()) {
50 fingerprint_ = "mock_fingerprint";
51 verifier_.set_property_reader([](const std::string& /* id */) { return "mock_fingerprint"; });
52 }
Tianjie Xu446b64b2018-09-19 15:45:28 -070053 }
54
55 void TearDown() override {
56 unlink(care_map_pb_.c_str());
57 unlink(care_map_txt_.c_str());
Tao Bao83b07802017-04-26 14:30:56 -070058 }
59
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070060 // Returns a serialized string of the proto3 message according to the given partition info.
61 std::string ConstructProto(
62 std::vector<std::unordered_map<std::string, std::string>>& partitions) {
Tianjie Xu446b64b2018-09-19 15:45:28 -070063 recovery_update_verifier::CareMap result;
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070064 for (const auto& partition : partitions) {
Tianjie Xu446b64b2018-09-19 15:45:28 -070065 recovery_update_verifier::CareMap::PartitionInfo info;
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070066 if (partition.find("name") != partition.end()) {
67 info.set_name(partition.at("name"));
68 }
69 if (partition.find("ranges") != partition.end()) {
70 info.set_ranges(partition.at("ranges"));
71 }
Tianjie Xu9eed65e2018-09-14 12:52:02 -070072 if (partition.find("id") != partition.end()) {
73 info.set_id(partition.at("id"));
74 }
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070075 if (partition.find("fingerprint") != partition.end()) {
76 info.set_fingerprint(partition.at("fingerprint"));
77 }
78
79 *result.add_partitions() = info;
80 }
81
82 return result.SerializeAsString();
83 }
84
Tao Bao83b07802017-04-26 14:30:56 -070085 bool verity_supported;
Tianjie Xu446b64b2018-09-19 15:45:28 -070086 UpdateVerifier verifier_;
87
88 TemporaryDir care_map_dir_;
Tianjie Xu9eed65e2018-09-14 12:52:02 -070089 std::string care_map_prefix_;
Tianjie Xu446b64b2018-09-19 15:45:28 -070090 std::string care_map_pb_;
91 std::string care_map_txt_;
Tianjie Xu9eed65e2018-09-14 12:52:02 -070092
93 std::string property_id_;
94 std::string fingerprint_;
Tao Bao83b07802017-04-26 14:30:56 -070095};
96
97TEST_F(UpdateVerifierTest, verify_image_no_care_map) {
Tianjie Xu9eed65e2018-09-14 12:52:02 -070098 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -070099}
100
101TEST_F(UpdateVerifierTest, verify_image_smoke) {
102 // This test relies on dm-verity support.
103 if (!verity_supported) {
104 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
105 return;
106 }
107
Tao Bao83b07802017-04-26 14:30:56 -0700108 std::string content = "system\n2,0,1";
Tianjie Xu446b64b2018-09-19 15:45:28 -0700109 ASSERT_TRUE(android::base::WriteStringToFile(content, care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700110 ASSERT_TRUE(verifier_.ParseCareMap());
Tianjie Xu446b64b2018-09-19 15:45:28 -0700111 ASSERT_TRUE(verifier_.VerifyPartitions());
Tao Bao83b07802017-04-26 14:30:56 -0700112
113 // Leading and trailing newlines should be accepted.
Tianjie Xu446b64b2018-09-19 15:45:28 -0700114 ASSERT_TRUE(android::base::WriteStringToFile("\n" + content + "\n\n", care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700115 ASSERT_TRUE(verifier_.ParseCareMap());
Tianjie Xu446b64b2018-09-19 15:45:28 -0700116 ASSERT_TRUE(verifier_.VerifyPartitions());
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700117}
118
119TEST_F(UpdateVerifierTest, verify_image_empty_care_map) {
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700120 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -0700121}
122
123TEST_F(UpdateVerifierTest, verify_image_wrong_lines) {
Tao Baoec2e8c62018-03-22 16:07:00 -0700124 // The care map file can have only 2 / 4 / 6 lines.
Tianjie Xu446b64b2018-09-19 15:45:28 -0700125 ASSERT_TRUE(android::base::WriteStringToFile("line1", care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700126 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -0700127
Tianjie Xu446b64b2018-09-19 15:45:28 -0700128 ASSERT_TRUE(android::base::WriteStringToFile("line1\nline2\nline3", care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700129 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -0700130}
131
132TEST_F(UpdateVerifierTest, verify_image_malformed_care_map) {
133 // This test relies on dm-verity support.
134 if (!verity_supported) {
135 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
136 return;
137 }
138
Tao Bao83b07802017-04-26 14:30:56 -0700139 std::string content = "system\n2,1,0";
Tianjie Xu446b64b2018-09-19 15:45:28 -0700140 ASSERT_TRUE(android::base::WriteStringToFile(content, care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700141 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -0700142}
Tao Baoc3196132017-07-24 09:22:39 -0700143
144TEST_F(UpdateVerifierTest, verify_image_legacy_care_map) {
145 // This test relies on dm-verity support.
146 if (!verity_supported) {
147 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
148 return;
149 }
150
Tao Baoc3196132017-07-24 09:22:39 -0700151 std::string content = "/dev/block/bootdevice/by-name/system\n2,1,0";
Tianjie Xu446b64b2018-09-19 15:45:28 -0700152 ASSERT_TRUE(android::base::WriteStringToFile(content, care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700153 ASSERT_FALSE(verifier_.ParseCareMap());
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700154}
155
156TEST_F(UpdateVerifierTest, verify_image_protobuf_care_map_smoke) {
157 // This test relies on dm-verity support.
158 if (!verity_supported) {
159 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
160 return;
161 }
162
163 std::vector<std::unordered_map<std::string, std::string>> partitions = {
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700164 {
165 { "name", "system" },
166 { "ranges", "2,0,1" },
167 { "id", property_id_ },
168 { "fingerprint", fingerprint_ },
169 },
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700170 };
171
172 std::string proto = ConstructProto(partitions);
Tianjie Xu446b64b2018-09-19 15:45:28 -0700173 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700174 ASSERT_TRUE(verifier_.ParseCareMap());
Tianjie Xu446b64b2018-09-19 15:45:28 -0700175 ASSERT_TRUE(verifier_.VerifyPartitions());
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700176}
177
178TEST_F(UpdateVerifierTest, verify_image_protobuf_care_map_missing_name) {
179 // This test relies on dm-verity support.
180 if (!verity_supported) {
181 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
182 return;
183 }
184
185 std::vector<std::unordered_map<std::string, std::string>> partitions = {
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700186 {
187 { "ranges", "2,0,1" },
188 { "id", property_id_ },
189 { "fingerprint", fingerprint_ },
190 },
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700191 };
192
193 std::string proto = ConstructProto(partitions);
Tianjie Xu446b64b2018-09-19 15:45:28 -0700194 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700195 ASSERT_FALSE(verifier_.ParseCareMap());
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700196}
197
198TEST_F(UpdateVerifierTest, verify_image_protobuf_care_map_bad_ranges) {
199 // This test relies on dm-verity support.
200 if (!verity_supported) {
201 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
202 return;
203 }
204
205 std::vector<std::unordered_map<std::string, std::string>> partitions = {
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700206 {
207 { "name", "system" },
208 { "ranges", "3,0,1" },
209 { "id", property_id_ },
210 { "fingerprint", fingerprint_ },
211 },
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700212 };
213
214 std::string proto = ConstructProto(partitions);
Tianjie Xu446b64b2018-09-19 15:45:28 -0700215 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700216 ASSERT_FALSE(verifier_.ParseCareMap());
217}
218
219TEST_F(UpdateVerifierTest, verify_image_protobuf_empty_fingerprint) {
220 // This test relies on dm-verity support.
221 if (!verity_supported) {
222 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
223 return;
224 }
225
226 std::vector<std::unordered_map<std::string, std::string>> partitions = {
227 {
228 { "name", "system" },
229 { "ranges", "2,0,1" },
230 },
231 };
232
233 std::string proto = ConstructProto(partitions);
234 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
235 ASSERT_FALSE(verifier_.ParseCareMap());
236}
237
238TEST_F(UpdateVerifierTest, verify_image_protobuf_fingerprint_mismatch) {
239 // This test relies on dm-verity support.
240 if (!verity_supported) {
241 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
242 return;
243 }
244
245 std::vector<std::unordered_map<std::string, std::string>> partitions = {
246 {
247 { "name", "system" },
248 { "ranges", "2,0,1" },
249 { "id", property_id_ },
250 { "fingerprint", "unsupported_fingerprint" },
251 },
252 };
253
254 std::string proto = ConstructProto(partitions);
255 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
256 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Baoc3196132017-07-24 09:22:39 -0700257}