xref: /aosp_15_r20/bootable/recovery/tests/unit/update_verifier_test.cpp (revision e7c364b630b241adcb6c7726a21055250b91fdac)
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