1*e7c364b6SAndroid Build Coastguard Worker /*
2*e7c364b6SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*e7c364b6SAndroid Build Coastguard Worker *
4*e7c364b6SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e7c364b6SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e7c364b6SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e7c364b6SAndroid Build Coastguard Worker *
8*e7c364b6SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e7c364b6SAndroid Build Coastguard Worker *
10*e7c364b6SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e7c364b6SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e7c364b6SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7c364b6SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e7c364b6SAndroid Build Coastguard Worker * limitations under the License.
15*e7c364b6SAndroid Build Coastguard Worker */
16*e7c364b6SAndroid Build Coastguard Worker
17*e7c364b6SAndroid Build Coastguard Worker #include <update_verifier/update_verifier.h>
18*e7c364b6SAndroid Build Coastguard Worker
19*e7c364b6SAndroid Build Coastguard Worker #include <functional>
20*e7c364b6SAndroid Build Coastguard Worker #include <string>
21*e7c364b6SAndroid Build Coastguard Worker #include <unordered_map>
22*e7c364b6SAndroid Build Coastguard Worker #include <vector>
23*e7c364b6SAndroid Build Coastguard Worker
24*e7c364b6SAndroid Build Coastguard Worker #include <android-base/file.h>
25*e7c364b6SAndroid Build Coastguard Worker #include <android-base/properties.h>
26*e7c364b6SAndroid Build Coastguard Worker #include <android-base/strings.h>
27*e7c364b6SAndroid Build Coastguard Worker #include <google/protobuf/repeated_field.h>
28*e7c364b6SAndroid Build Coastguard Worker #include <gtest/gtest.h>
29*e7c364b6SAndroid Build Coastguard Worker
30*e7c364b6SAndroid Build Coastguard Worker #include "care_map.pb.h"
31*e7c364b6SAndroid Build Coastguard Worker
32*e7c364b6SAndroid Build Coastguard Worker using namespace std::string_literals;
33*e7c364b6SAndroid Build Coastguard Worker
34*e7c364b6SAndroid Build Coastguard Worker class UpdateVerifierTest : public ::testing::Test {
35*e7c364b6SAndroid Build Coastguard Worker protected:
SetUp()36*e7c364b6SAndroid Build Coastguard Worker void SetUp() override {
37*e7c364b6SAndroid Build Coastguard Worker std::string verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
38*e7c364b6SAndroid Build Coastguard Worker verity_supported = android::base::EqualsIgnoreCase(verity_mode, "enforcing");
39*e7c364b6SAndroid Build Coastguard Worker
40*e7c364b6SAndroid Build Coastguard Worker care_map_prefix_ = care_map_dir_.path + "/care_map"s;
41*e7c364b6SAndroid Build Coastguard Worker care_map_pb_ = care_map_dir_.path + "/care_map.pb"s;
42*e7c364b6SAndroid Build Coastguard Worker care_map_txt_ = care_map_dir_.path + "/care_map.txt"s;
43*e7c364b6SAndroid Build Coastguard Worker // Overrides the the care_map_prefix.
44*e7c364b6SAndroid Build Coastguard Worker verifier_.set_care_map_prefix(care_map_prefix_);
45*e7c364b6SAndroid Build Coastguard Worker
46*e7c364b6SAndroid Build Coastguard Worker property_id_ = "ro.build.fingerprint";
47*e7c364b6SAndroid Build Coastguard Worker fingerprint_ = android::base::GetProperty(property_id_, "");
48*e7c364b6SAndroid Build Coastguard Worker // Overrides the property_reader if we cannot read the given property on the device.
49*e7c364b6SAndroid Build Coastguard Worker if (fingerprint_.empty()) {
50*e7c364b6SAndroid Build Coastguard Worker fingerprint_ = "mock_fingerprint";
51*e7c364b6SAndroid Build Coastguard Worker verifier_.set_property_reader([](const std::string& /* id */) { return "mock_fingerprint"; });
52*e7c364b6SAndroid Build Coastguard Worker }
53*e7c364b6SAndroid Build Coastguard Worker }
54*e7c364b6SAndroid Build Coastguard Worker
TearDown()55*e7c364b6SAndroid Build Coastguard Worker void TearDown() override {
56*e7c364b6SAndroid Build Coastguard Worker unlink(care_map_pb_.c_str());
57*e7c364b6SAndroid Build Coastguard Worker unlink(care_map_txt_.c_str());
58*e7c364b6SAndroid Build Coastguard Worker }
59*e7c364b6SAndroid Build Coastguard Worker
60*e7c364b6SAndroid Build Coastguard Worker // Returns a serialized string of the proto3 message according to the given partition info.
ConstructProto(std::vector<std::unordered_map<std::string,std::string>> & partitions)61*e7c364b6SAndroid Build Coastguard Worker std::string ConstructProto(
62*e7c364b6SAndroid Build Coastguard Worker std::vector<std::unordered_map<std::string, std::string>>& partitions) {
63*e7c364b6SAndroid Build Coastguard Worker recovery_update_verifier::CareMap result;
64*e7c364b6SAndroid Build Coastguard Worker for (const auto& partition : partitions) {
65*e7c364b6SAndroid Build Coastguard Worker recovery_update_verifier::CareMap::PartitionInfo info;
66*e7c364b6SAndroid Build Coastguard Worker if (partition.find("name") != partition.end()) {
67*e7c364b6SAndroid Build Coastguard Worker info.set_name(partition.at("name"));
68*e7c364b6SAndroid Build Coastguard Worker }
69*e7c364b6SAndroid Build Coastguard Worker if (partition.find("ranges") != partition.end()) {
70*e7c364b6SAndroid Build Coastguard Worker info.set_ranges(partition.at("ranges"));
71*e7c364b6SAndroid Build Coastguard Worker }
72*e7c364b6SAndroid Build Coastguard Worker if (partition.find("id") != partition.end()) {
73*e7c364b6SAndroid Build Coastguard Worker info.set_id(partition.at("id"));
74*e7c364b6SAndroid Build Coastguard Worker }
75*e7c364b6SAndroid Build Coastguard Worker if (partition.find("fingerprint") != partition.end()) {
76*e7c364b6SAndroid Build Coastguard Worker info.set_fingerprint(partition.at("fingerprint"));
77*e7c364b6SAndroid Build Coastguard Worker }
78*e7c364b6SAndroid Build Coastguard Worker
79*e7c364b6SAndroid Build Coastguard Worker *result.add_partitions() = info;
80*e7c364b6SAndroid Build Coastguard Worker }
81*e7c364b6SAndroid Build Coastguard Worker
82*e7c364b6SAndroid Build Coastguard Worker return result.SerializeAsString();
83*e7c364b6SAndroid Build Coastguard Worker }
84*e7c364b6SAndroid Build Coastguard Worker
85*e7c364b6SAndroid Build Coastguard Worker bool verity_supported;
86*e7c364b6SAndroid Build Coastguard Worker UpdateVerifier verifier_;
87*e7c364b6SAndroid Build Coastguard Worker
88*e7c364b6SAndroid Build Coastguard Worker TemporaryDir care_map_dir_;
89*e7c364b6SAndroid Build Coastguard Worker std::string care_map_prefix_;
90*e7c364b6SAndroid Build Coastguard Worker std::string care_map_pb_;
91*e7c364b6SAndroid Build Coastguard Worker std::string care_map_txt_;
92*e7c364b6SAndroid Build Coastguard Worker
93*e7c364b6SAndroid Build Coastguard Worker std::string property_id_;
94*e7c364b6SAndroid Build Coastguard Worker std::string fingerprint_;
95*e7c364b6SAndroid Build Coastguard Worker };
96*e7c364b6SAndroid Build Coastguard Worker
TEST_F(UpdateVerifierTest,verify_image_no_care_map)97*e7c364b6SAndroid Build Coastguard Worker TEST_F(UpdateVerifierTest, verify_image_no_care_map) {
98*e7c364b6SAndroid Build Coastguard Worker ASSERT_FALSE(verifier_.ParseCareMap());
99*e7c364b6SAndroid Build Coastguard Worker }
100*e7c364b6SAndroid Build Coastguard Worker
TEST_F(UpdateVerifierTest,verify_image_text_format)101*e7c364b6SAndroid Build Coastguard Worker TEST_F(UpdateVerifierTest, verify_image_text_format) {
102*e7c364b6SAndroid Build Coastguard Worker // This test relies on dm-verity support.
103*e7c364b6SAndroid Build Coastguard Worker if (!verity_supported) {
104*e7c364b6SAndroid Build Coastguard Worker GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
105*e7c364b6SAndroid Build Coastguard Worker return;
106*e7c364b6SAndroid Build Coastguard Worker }
107*e7c364b6SAndroid Build Coastguard Worker
108*e7c364b6SAndroid Build Coastguard Worker std::string content = "system\n2,0,1";
109*e7c364b6SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteStringToFile(content, care_map_txt_));
110*e7c364b6SAndroid Build Coastguard Worker // CareMap in text format is no longer supported.
111*e7c364b6SAndroid Build Coastguard Worker ASSERT_FALSE(verifier_.ParseCareMap());
112*e7c364b6SAndroid Build Coastguard Worker }
113*e7c364b6SAndroid Build Coastguard Worker
TEST_F(UpdateVerifierTest,verify_image_empty_care_map)114*e7c364b6SAndroid Build Coastguard Worker TEST_F(UpdateVerifierTest, verify_image_empty_care_map) {
115*e7c364b6SAndroid Build Coastguard Worker ASSERT_FALSE(verifier_.ParseCareMap());
116*e7c364b6SAndroid Build Coastguard Worker }
117*e7c364b6SAndroid Build Coastguard Worker
TEST_F(UpdateVerifierTest,verify_image_protobuf_care_map_smoke)118*e7c364b6SAndroid Build Coastguard Worker TEST_F(UpdateVerifierTest, verify_image_protobuf_care_map_smoke) {
119*e7c364b6SAndroid Build Coastguard Worker // This test relies on dm-verity support.
120*e7c364b6SAndroid Build Coastguard Worker if (!verity_supported) {
121*e7c364b6SAndroid Build Coastguard Worker GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
122*e7c364b6SAndroid Build Coastguard Worker return;
123*e7c364b6SAndroid Build Coastguard Worker }
124*e7c364b6SAndroid Build Coastguard Worker
125*e7c364b6SAndroid Build Coastguard Worker std::vector<std::unordered_map<std::string, std::string>> partitions = {
126*e7c364b6SAndroid Build Coastguard Worker {
127*e7c364b6SAndroid Build Coastguard Worker { "name", "system" },
128*e7c364b6SAndroid Build Coastguard Worker { "ranges", "2,0,1" },
129*e7c364b6SAndroid Build Coastguard Worker { "id", property_id_ },
130*e7c364b6SAndroid Build Coastguard Worker { "fingerprint", fingerprint_ },
131*e7c364b6SAndroid Build Coastguard Worker },
132*e7c364b6SAndroid Build Coastguard Worker };
133*e7c364b6SAndroid Build Coastguard Worker
134*e7c364b6SAndroid Build Coastguard Worker std::string proto = ConstructProto(partitions);
135*e7c364b6SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
136*e7c364b6SAndroid Build Coastguard Worker ASSERT_TRUE(verifier_.ParseCareMap());
137*e7c364b6SAndroid Build Coastguard Worker ASSERT_TRUE(verifier_.VerifyPartitions());
138*e7c364b6SAndroid Build Coastguard Worker }
139*e7c364b6SAndroid Build Coastguard Worker
TEST_F(UpdateVerifierTest,verify_image_protobuf_care_map_missing_name)140*e7c364b6SAndroid Build Coastguard Worker TEST_F(UpdateVerifierTest, verify_image_protobuf_care_map_missing_name) {
141*e7c364b6SAndroid Build Coastguard Worker // This test relies on dm-verity support.
142*e7c364b6SAndroid Build Coastguard Worker if (!verity_supported) {
143*e7c364b6SAndroid Build Coastguard Worker GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
144*e7c364b6SAndroid Build Coastguard Worker return;
145*e7c364b6SAndroid Build Coastguard Worker }
146*e7c364b6SAndroid Build Coastguard Worker
147*e7c364b6SAndroid Build Coastguard Worker std::vector<std::unordered_map<std::string, std::string>> partitions = {
148*e7c364b6SAndroid Build Coastguard Worker {
149*e7c364b6SAndroid Build Coastguard Worker { "ranges", "2,0,1" },
150*e7c364b6SAndroid Build Coastguard Worker { "id", property_id_ },
151*e7c364b6SAndroid Build Coastguard Worker { "fingerprint", fingerprint_ },
152*e7c364b6SAndroid Build Coastguard Worker },
153*e7c364b6SAndroid Build Coastguard Worker };
154*e7c364b6SAndroid Build Coastguard Worker
155*e7c364b6SAndroid Build Coastguard Worker std::string proto = ConstructProto(partitions);
156*e7c364b6SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
157*e7c364b6SAndroid Build Coastguard Worker ASSERT_FALSE(verifier_.ParseCareMap());
158*e7c364b6SAndroid Build Coastguard Worker }
159*e7c364b6SAndroid Build Coastguard Worker
TEST_F(UpdateVerifierTest,verify_image_protobuf_care_map_bad_ranges)160*e7c364b6SAndroid Build Coastguard Worker TEST_F(UpdateVerifierTest, verify_image_protobuf_care_map_bad_ranges) {
161*e7c364b6SAndroid Build Coastguard Worker // This test relies on dm-verity support.
162*e7c364b6SAndroid Build Coastguard Worker if (!verity_supported) {
163*e7c364b6SAndroid Build Coastguard Worker GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
164*e7c364b6SAndroid Build Coastguard Worker return;
165*e7c364b6SAndroid Build Coastguard Worker }
166*e7c364b6SAndroid Build Coastguard Worker
167*e7c364b6SAndroid Build Coastguard Worker std::vector<std::unordered_map<std::string, std::string>> partitions = {
168*e7c364b6SAndroid Build Coastguard Worker {
169*e7c364b6SAndroid Build Coastguard Worker { "name", "system" },
170*e7c364b6SAndroid Build Coastguard Worker { "ranges", "3,0,1" },
171*e7c364b6SAndroid Build Coastguard Worker { "id", property_id_ },
172*e7c364b6SAndroid Build Coastguard Worker { "fingerprint", fingerprint_ },
173*e7c364b6SAndroid Build Coastguard Worker },
174*e7c364b6SAndroid Build Coastguard Worker };
175*e7c364b6SAndroid Build Coastguard Worker
176*e7c364b6SAndroid Build Coastguard Worker std::string proto = ConstructProto(partitions);
177*e7c364b6SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
178*e7c364b6SAndroid Build Coastguard Worker ASSERT_FALSE(verifier_.ParseCareMap());
179*e7c364b6SAndroid Build Coastguard Worker }
180*e7c364b6SAndroid Build Coastguard Worker
TEST_F(UpdateVerifierTest,verify_image_protobuf_empty_fingerprint)181*e7c364b6SAndroid Build Coastguard Worker TEST_F(UpdateVerifierTest, verify_image_protobuf_empty_fingerprint) {
182*e7c364b6SAndroid Build Coastguard Worker // This test relies on dm-verity support.
183*e7c364b6SAndroid Build Coastguard Worker if (!verity_supported) {
184*e7c364b6SAndroid Build Coastguard Worker GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
185*e7c364b6SAndroid Build Coastguard Worker return;
186*e7c364b6SAndroid Build Coastguard Worker }
187*e7c364b6SAndroid Build Coastguard Worker
188*e7c364b6SAndroid Build Coastguard Worker std::vector<std::unordered_map<std::string, std::string>> partitions = {
189*e7c364b6SAndroid Build Coastguard Worker {
190*e7c364b6SAndroid Build Coastguard Worker { "name", "system" },
191*e7c364b6SAndroid Build Coastguard Worker { "ranges", "2,0,1" },
192*e7c364b6SAndroid Build Coastguard Worker },
193*e7c364b6SAndroid Build Coastguard Worker };
194*e7c364b6SAndroid Build Coastguard Worker
195*e7c364b6SAndroid Build Coastguard Worker std::string proto = ConstructProto(partitions);
196*e7c364b6SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
197*e7c364b6SAndroid Build Coastguard Worker ASSERT_FALSE(verifier_.ParseCareMap());
198*e7c364b6SAndroid Build Coastguard Worker }
199*e7c364b6SAndroid Build Coastguard Worker
TEST_F(UpdateVerifierTest,verify_image_protobuf_fingerprint_mismatch)200*e7c364b6SAndroid Build Coastguard Worker TEST_F(UpdateVerifierTest, verify_image_protobuf_fingerprint_mismatch) {
201*e7c364b6SAndroid Build Coastguard Worker // This test relies on dm-verity support.
202*e7c364b6SAndroid Build Coastguard Worker if (!verity_supported) {
203*e7c364b6SAndroid Build Coastguard Worker GTEST_LOG_(INFO) << "Test skipped on devices without dm-verity support.";
204*e7c364b6SAndroid Build Coastguard Worker return;
205*e7c364b6SAndroid Build Coastguard Worker }
206*e7c364b6SAndroid Build Coastguard Worker
207*e7c364b6SAndroid Build Coastguard Worker std::vector<std::unordered_map<std::string, std::string>> partitions = {
208*e7c364b6SAndroid Build Coastguard Worker {
209*e7c364b6SAndroid Build Coastguard Worker { "name", "system" },
210*e7c364b6SAndroid Build Coastguard Worker { "ranges", "2,0,1" },
211*e7c364b6SAndroid Build Coastguard Worker { "id", property_id_ },
212*e7c364b6SAndroid Build Coastguard Worker { "fingerprint", "unsupported_fingerprint" },
213*e7c364b6SAndroid Build Coastguard Worker },
214*e7c364b6SAndroid Build Coastguard Worker };
215*e7c364b6SAndroid Build Coastguard Worker
216*e7c364b6SAndroid Build Coastguard Worker std::string proto = ConstructProto(partitions);
217*e7c364b6SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteStringToFile(proto, care_map_pb_));
218*e7c364b6SAndroid Build Coastguard Worker ASSERT_FALSE(verifier_.ParseCareMap());
219*e7c364b6SAndroid Build Coastguard Worker }
220