blob: 2420c27fe7bfffc57d534a1a90f4b9fe70a97757 [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>
Tao Bao83b07802017-04-26 14:30:56 -070027#include <android-base/test_utils.h>
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070028#include <google/protobuf/repeated_field.h>
Tao Bao83b07802017-04-26 14:30:56 -070029#include <gtest/gtest.h>
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070030
31#include "care_map.pb.h"
Tao Bao83b07802017-04-26 14:30:56 -070032
Tianjie Xu446b64b2018-09-19 15:45:28 -070033using namespace std::string_literals;
34
Tao Bao83b07802017-04-26 14:30:56 -070035class UpdateVerifierTest : public ::testing::Test {
36 protected:
37 void SetUp() override {
Tao Bao1cc03512018-04-18 17:10:49 -070038 std::string verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
39 verity_supported = android::base::EqualsIgnoreCase(verity_mode, "enforcing");
Tianjie Xu446b64b2018-09-19 15:45:28 -070040
Tianjie Xu9eed65e2018-09-14 12:52:02 -070041 care_map_prefix_ = care_map_dir_.path + "/care_map"s;
Tianjie Xu446b64b2018-09-19 15:45:28 -070042 care_map_pb_ = care_map_dir_.path + "/care_map.pb"s;
43 care_map_txt_ = care_map_dir_.path + "/care_map.txt"s;
Tianjie Xu9eed65e2018-09-14 12:52:02 -070044 // Overrides the the care_map_prefix.
45 verifier_.set_care_map_prefix(care_map_prefix_);
46
47 property_id_ = "ro.build.fingerprint";
48 fingerprint_ = android::base::GetProperty(property_id_, "");
49 // Overrides the property_reader if we cannot read the given property on the device.
50 if (fingerprint_.empty()) {
51 fingerprint_ = "mock_fingerprint";
52 verifier_.set_property_reader([](const std::string& /* id */) { return "mock_fingerprint"; });
53 }
Tianjie Xu446b64b2018-09-19 15:45:28 -070054 }
55
56 void TearDown() override {
57 unlink(care_map_pb_.c_str());
58 unlink(care_map_txt_.c_str());
Tao Bao83b07802017-04-26 14:30:56 -070059 }
60
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070061 // Returns a serialized string of the proto3 message according to the given partition info.
62 std::string ConstructProto(
63 std::vector<std::unordered_map<std::string, std::string>>& partitions) {
Tianjie Xu446b64b2018-09-19 15:45:28 -070064 recovery_update_verifier::CareMap result;
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070065 for (const auto& partition : partitions) {
Tianjie Xu446b64b2018-09-19 15:45:28 -070066 recovery_update_verifier::CareMap::PartitionInfo info;
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070067 if (partition.find("name") != partition.end()) {
68 info.set_name(partition.at("name"));
69 }
70 if (partition.find("ranges") != partition.end()) {
71 info.set_ranges(partition.at("ranges"));
72 }
Tianjie Xu9eed65e2018-09-14 12:52:02 -070073 if (partition.find("id") != partition.end()) {
74 info.set_id(partition.at("id"));
75 }
Tianjie Xu4d9e62d2018-05-11 10:41:44 -070076 if (partition.find("fingerprint") != partition.end()) {
77 info.set_fingerprint(partition.at("fingerprint"));
78 }
79
80 *result.add_partitions() = info;
81 }
82
83 return result.SerializeAsString();
84 }
85
Tao Bao83b07802017-04-26 14:30:56 -070086 bool verity_supported;
Tianjie Xu446b64b2018-09-19 15:45:28 -070087 UpdateVerifier verifier_;
88
89 TemporaryDir care_map_dir_;
Tianjie Xu9eed65e2018-09-14 12:52:02 -070090 std::string care_map_prefix_;
Tianjie Xu446b64b2018-09-19 15:45:28 -070091 std::string care_map_pb_;
92 std::string care_map_txt_;
Tianjie Xu9eed65e2018-09-14 12:52:02 -070093
94 std::string property_id_;
95 std::string fingerprint_;
Tao Bao83b07802017-04-26 14:30:56 -070096};
97
98TEST_F(UpdateVerifierTest, verify_image_no_care_map) {
Tianjie Xu9eed65e2018-09-14 12:52:02 -070099 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -0700100}
101
102TEST_F(UpdateVerifierTest, verify_image_smoke) {
103 // This test relies on dm-verity support.
104 if (!verity_supported) {
105 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
106 return;
107 }
108
Tao Bao83b07802017-04-26 14:30:56 -0700109 std::string content = "system\n2,0,1";
Tianjie Xu446b64b2018-09-19 15:45:28 -0700110 ASSERT_TRUE(android::base::WriteStringToFile(content, care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700111 ASSERT_TRUE(verifier_.ParseCareMap());
Tianjie Xu446b64b2018-09-19 15:45:28 -0700112 ASSERT_TRUE(verifier_.VerifyPartitions());
Tao Bao83b07802017-04-26 14:30:56 -0700113
114 // Leading and trailing newlines should be accepted.
Tianjie Xu446b64b2018-09-19 15:45:28 -0700115 ASSERT_TRUE(android::base::WriteStringToFile("\n" + content + "\n\n", care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700116 ASSERT_TRUE(verifier_.ParseCareMap());
Tianjie Xu446b64b2018-09-19 15:45:28 -0700117 ASSERT_TRUE(verifier_.VerifyPartitions());
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700118}
119
120TEST_F(UpdateVerifierTest, verify_image_empty_care_map) {
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700121 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -0700122}
123
124TEST_F(UpdateVerifierTest, verify_image_wrong_lines) {
Tao Baoec2e8c62018-03-22 16:07:00 -0700125 // The care map file can have only 2 / 4 / 6 lines.
Tianjie Xu446b64b2018-09-19 15:45:28 -0700126 ASSERT_TRUE(android::base::WriteStringToFile("line1", care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700127 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -0700128
Tianjie Xu446b64b2018-09-19 15:45:28 -0700129 ASSERT_TRUE(android::base::WriteStringToFile("line1\nline2\nline3", care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700130 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -0700131}
132
133TEST_F(UpdateVerifierTest, verify_image_malformed_care_map) {
134 // This test relies on dm-verity support.
135 if (!verity_supported) {
136 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
137 return;
138 }
139
Tao Bao83b07802017-04-26 14:30:56 -0700140 std::string content = "system\n2,1,0";
Tianjie Xu446b64b2018-09-19 15:45:28 -0700141 ASSERT_TRUE(android::base::WriteStringToFile(content, care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700142 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Bao83b07802017-04-26 14:30:56 -0700143}
Tao Baoc3196132017-07-24 09:22:39 -0700144
145TEST_F(UpdateVerifierTest, verify_image_legacy_care_map) {
146 // This test relies on dm-verity support.
147 if (!verity_supported) {
148 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
149 return;
150 }
151
Tao Baoc3196132017-07-24 09:22:39 -0700152 std::string content = "/dev/block/bootdevice/by-name/system\n2,1,0";
Tianjie Xu446b64b2018-09-19 15:45:28 -0700153 ASSERT_TRUE(android::base::WriteStringToFile(content, care_map_txt_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700154 ASSERT_FALSE(verifier_.ParseCareMap());
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700155}
156
157TEST_F(UpdateVerifierTest, verify_image_protobuf_care_map_smoke) {
158 // This test relies on dm-verity support.
159 if (!verity_supported) {
160 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
161 return;
162 }
163
164 std::vector<std::unordered_map<std::string, std::string>> partitions = {
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700165 {
166 { "name", "system" },
167 { "ranges", "2,0,1" },
168 { "id", property_id_ },
169 { "fingerprint", fingerprint_ },
170 },
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700171 };
172
173 std::string proto = ConstructProto(partitions);
Tianjie Xu446b64b2018-09-19 15:45:28 -0700174 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700175 ASSERT_TRUE(verifier_.ParseCareMap());
Tianjie Xu446b64b2018-09-19 15:45:28 -0700176 ASSERT_TRUE(verifier_.VerifyPartitions());
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700177}
178
179TEST_F(UpdateVerifierTest, verify_image_protobuf_care_map_missing_name) {
180 // This test relies on dm-verity support.
181 if (!verity_supported) {
182 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
183 return;
184 }
185
186 std::vector<std::unordered_map<std::string, std::string>> partitions = {
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700187 {
188 { "ranges", "2,0,1" },
189 { "id", property_id_ },
190 { "fingerprint", fingerprint_ },
191 },
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700192 };
193
194 std::string proto = ConstructProto(partitions);
Tianjie Xu446b64b2018-09-19 15:45:28 -0700195 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700196 ASSERT_FALSE(verifier_.ParseCareMap());
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700197}
198
199TEST_F(UpdateVerifierTest, verify_image_protobuf_care_map_bad_ranges) {
200 // This test relies on dm-verity support.
201 if (!verity_supported) {
202 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
203 return;
204 }
205
206 std::vector<std::unordered_map<std::string, std::string>> partitions = {
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700207 {
208 { "name", "system" },
209 { "ranges", "3,0,1" },
210 { "id", property_id_ },
211 { "fingerprint", fingerprint_ },
212 },
Tianjie Xu4d9e62d2018-05-11 10:41:44 -0700213 };
214
215 std::string proto = ConstructProto(partitions);
Tianjie Xu446b64b2018-09-19 15:45:28 -0700216 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
Tianjie Xu9eed65e2018-09-14 12:52:02 -0700217 ASSERT_FALSE(verifier_.ParseCareMap());
218}
219
220TEST_F(UpdateVerifierTest, verify_image_protobuf_empty_fingerprint) {
221 // This test relies on dm-verity support.
222 if (!verity_supported) {
223 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
224 return;
225 }
226
227 std::vector<std::unordered_map<std::string, std::string>> partitions = {
228 {
229 { "name", "system" },
230 { "ranges", "2,0,1" },
231 },
232 };
233
234 std::string proto = ConstructProto(partitions);
235 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
236 ASSERT_FALSE(verifier_.ParseCareMap());
237}
238
239TEST_F(UpdateVerifierTest, verify_image_protobuf_fingerprint_mismatch) {
240 // This test relies on dm-verity support.
241 if (!verity_supported) {
242 GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
243 return;
244 }
245
246 std::vector<std::unordered_map<std::string, std::string>> partitions = {
247 {
248 { "name", "system" },
249 { "ranges", "2,0,1" },
250 { "id", property_id_ },
251 { "fingerprint", "unsupported_fingerprint" },
252 },
253 };
254
255 std::string proto = ConstructProto(partitions);
256 ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
257 ASSERT_FALSE(verifier_.ParseCareMap());
Tao Baoc3196132017-07-24 09:22:39 -0700258}