xref: /aosp_15_r20/system/apex/apexd/apexd_brand_new_verifier_test.cpp (revision 33f3758387333dbd2962d7edbd98681940d895da)
1 /*
2  * Copyright (C) 2024 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 "apexd_brand_new_verifier.h"
18 
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <android-base/properties.h>
22 #include <android-base/result-gmock.h>
23 #include <android-base/stringprintf.h>
24 #include <gtest/gtest.h>
25 #include <sys/stat.h>
26 
27 #include <filesystem>
28 #include <string>
29 
30 #include "apex_constants.h"
31 #include "apex_file_repository.h"
32 #include "apexd_test_utils.h"
33 
34 namespace android::apex {
35 
36 namespace fs = std::filesystem;
37 
38 using android::base::GetExecutableDirectory;
39 using android::base::testing::Ok;
40 using android::base::testing::WithMessage;
41 using ::testing::Not;
42 
GetTestDataDir()43 static std::string GetTestDataDir() { return GetExecutableDirectory(); }
GetTestFile(const std::string & name)44 static std::string GetTestFile(const std::string& name) {
45   return GetTestDataDir() + "/" + name;
46 }
47 
TEST(BrandNewApexVerifierTest,SucceedPublicKeyMatch)48 TEST(BrandNewApexVerifierTest, SucceedPublicKeyMatch) {
49   ApexFileRepository::EnableBrandNewApex();
50   auto& file_repository = ApexFileRepository::GetInstance();
51   const auto partition = ApexPartition::System;
52   TemporaryDir trusted_key_dir;
53   fs::copy(GetTestFile("apexd_testdata/com.android.apex.brand.new.avbpubkey"),
54            trusted_key_dir.path);
55   file_repository.AddBrandNewApexCredentialAndBlocklist(
56       {{partition, trusted_key_dir.path}});
57 
58   auto apex = ApexFile::Open(GetTestFile("com.android.apex.brand.new.apex"));
59   ASSERT_RESULT_OK(apex);
60 
61   auto ret = VerifyBrandNewPackageAgainstPreinstalled(*apex);
62   ASSERT_RESULT_OK(ret);
63   ASSERT_EQ(*ret, partition);
64 
65   file_repository.Reset();
66 }
67 
TEST(BrandNewApexVerifierTest,SucceedVersionBiggerThanBlocked)68 TEST(BrandNewApexVerifierTest, SucceedVersionBiggerThanBlocked) {
69   ApexFileRepository::EnableBrandNewApex();
70   auto& file_repository = ApexFileRepository::GetInstance();
71   const auto partition = ApexPartition::System;
72   TemporaryDir config_dir;
73   fs::copy(GetTestFile("apexd_testdata/com.android.apex.brand.new.avbpubkey"),
74            config_dir.path);
75   fs::copy(GetTestFile("apexd_testdata/blocklist.json"), config_dir.path);
76   file_repository.AddBrandNewApexCredentialAndBlocklist(
77       {{partition, config_dir.path}});
78 
79   auto apex = ApexFile::Open(GetTestFile("com.android.apex.brand.new.v2.apex"));
80   ASSERT_RESULT_OK(apex);
81 
82   auto ret = VerifyBrandNewPackageAgainstPreinstalled(*apex);
83   ASSERT_RESULT_OK(ret);
84   ASSERT_EQ(*ret, partition);
85 
86   file_repository.Reset();
87 }
88 
TEST(BrandNewApexVerifierTest,SucceedMatchActive)89 TEST(BrandNewApexVerifierTest, SucceedMatchActive) {
90   ApexFileRepository::EnableBrandNewApex();
91   auto& file_repository = ApexFileRepository::GetInstance();
92   TemporaryDir trusted_key_dir, data_dir;
93   fs::copy(GetTestFile("apexd_testdata/com.android.apex.brand.new.avbpubkey"),
94            trusted_key_dir.path);
95   fs::copy(GetTestFile("com.android.apex.brand.new.apex"), data_dir.path);
96   file_repository.AddBrandNewApexCredentialAndBlocklist(
97       {{ApexPartition::System, trusted_key_dir.path}});
98   file_repository.AddDataApex(data_dir.path);
99 
100   auto apex = ApexFile::Open(GetTestFile("com.android.apex.brand.new.v2.apex"));
101   ASSERT_RESULT_OK(apex);
102 
103   auto ret = VerifyBrandNewPackageAgainstActive(*apex);
104   ASSERT_RESULT_OK(ret);
105 
106   file_repository.Reset();
107 }
108 
TEST(BrandNewApexVerifierTest,SucceedSkipPreinstalled)109 TEST(BrandNewApexVerifierTest, SucceedSkipPreinstalled) {
110   ApexFileRepository::EnableBrandNewApex();
111   auto& file_repository = ApexFileRepository::GetInstance();
112   TemporaryDir built_in_dir;
113   fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
114   file_repository.AddPreInstalledApex(
115       {{ApexPartition::System, built_in_dir.path}});
116 
117   auto apex = ApexFile::Open(GetTestFile("apex.apexd_test.apex"));
118   ASSERT_RESULT_OK(apex);
119 
120   auto ret = VerifyBrandNewPackageAgainstActive(*apex);
121   ASSERT_RESULT_OK(ret);
122 
123   file_repository.Reset();
124 }
125 
TEST(BrandNewApexVerifierTest,SucceedSkipWithoutDataVersion)126 TEST(BrandNewApexVerifierTest, SucceedSkipWithoutDataVersion) {
127   ApexFileRepository::EnableBrandNewApex();
128   auto& file_repository = ApexFileRepository::GetInstance();
129 
130   auto apex = ApexFile::Open(GetTestFile("com.android.apex.brand.new.apex"));
131   ASSERT_RESULT_OK(apex);
132 
133   auto ret = VerifyBrandNewPackageAgainstActive(*apex);
134   ASSERT_RESULT_OK(ret);
135 
136   file_repository.Reset();
137 }
138 
TEST(BrandNewApexVerifierTest,FailBrandNewApexDisabled)139 TEST(BrandNewApexVerifierTest, FailBrandNewApexDisabled) {
140   auto& file_repository = ApexFileRepository::GetInstance();
141   const auto partition = ApexPartition::System;
142   TemporaryDir trusted_key_dir;
143   fs::copy(GetTestFile("apexd_testdata/com.android.apex.brand.new.avbpubkey"),
144            trusted_key_dir.path);
145   file_repository.AddBrandNewApexCredentialAndBlocklist(
146       {{partition, trusted_key_dir.path}});
147 
148   auto apex = ApexFile::Open(GetTestFile("com.android.apex.brand.new.apex"));
149   ASSERT_RESULT_OK(apex);
150 
151   ASSERT_DEATH(
152       { VerifyBrandNewPackageAgainstPreinstalled(*apex); },
153       "Brand-new APEX must be enabled in order to do verification.");
154   ASSERT_DEATH(
155       { VerifyBrandNewPackageAgainstActive(*apex); },
156       "Brand-new APEX must be enabled in order to do verification.");
157 
158   file_repository.Reset();
159 }
160 
TEST(BrandNewApexVerifierTest,FailNoMatchingPublicKey)161 TEST(BrandNewApexVerifierTest, FailNoMatchingPublicKey) {
162   ApexFileRepository::EnableBrandNewApex();
163 
164   auto apex = ApexFile::Open(GetTestFile("com.android.apex.brand.new.apex"));
165   ASSERT_RESULT_OK(apex);
166 
167   auto ret = VerifyBrandNewPackageAgainstPreinstalled(*apex);
168   ASSERT_THAT(
169       ret,
170       HasError(WithMessage(("No pre-installed public key found for the "
171                             "brand-new APEX: com.android.apex.brand.new"))));
172 }
173 
TEST(BrandNewApexVerifierTest,FailBlockedByVersion)174 TEST(BrandNewApexVerifierTest, FailBlockedByVersion) {
175   ApexFileRepository::EnableBrandNewApex();
176   auto& file_repository = ApexFileRepository::GetInstance();
177   const auto partition = ApexPartition::System;
178   TemporaryDir config_dir;
179   fs::copy(GetTestFile("apexd_testdata/com.android.apex.brand.new.avbpubkey"),
180            config_dir.path);
181   fs::copy(GetTestFile("apexd_testdata/blocklist.json"), config_dir.path);
182   file_repository.AddBrandNewApexCredentialAndBlocklist(
183       {{partition, config_dir.path}});
184 
185   auto apex = ApexFile::Open(GetTestFile("com.android.apex.brand.new.apex"));
186   ASSERT_RESULT_OK(apex);
187 
188   auto ret = VerifyBrandNewPackageAgainstPreinstalled(*apex);
189   ASSERT_THAT(ret,
190               HasError(WithMessage(
191                   ("Brand-new APEX is blocked: com.android.apex.brand.new"))));
192 
193   file_repository.Reset();
194 }
195 
TEST(BrandNewApexVerifierTest,FailPublicKeyNotMatchActive)196 TEST(BrandNewApexVerifierTest, FailPublicKeyNotMatchActive) {
197   ApexFileRepository::EnableBrandNewApex();
198   auto& file_repository = ApexFileRepository::GetInstance();
199   TemporaryDir trusted_key_dir, data_dir;
200   fs::copy(GetTestFile("apexd_testdata/com.android.apex.brand.new.avbpubkey"),
201            trusted_key_dir.path);
202   fs::copy(GetTestFile(
203                "apexd_testdata/com.android.apex.brand.new.another.avbpubkey"),
204            trusted_key_dir.path);
205   fs::copy(GetTestFile("com.android.apex.brand.new.apex"), data_dir.path);
206   file_repository.AddBrandNewApexCredentialAndBlocklist(
207       {{ApexPartition::System, trusted_key_dir.path}});
208   file_repository.AddDataApex(data_dir.path);
209 
210   auto apex =
211       ApexFile::Open(GetTestFile("com.android.apex.brand.new.v2.diffkey.apex"));
212   ASSERT_RESULT_OK(apex);
213 
214   auto ret = VerifyBrandNewPackageAgainstActive(*apex);
215   ASSERT_THAT(
216       ret,
217       HasError(WithMessage(("Brand-new APEX public key doesn't match existing "
218                             "active APEX: com.android.apex.brand.new"))));
219 
220   file_repository.Reset();
221 }
222 
223 }  // namespace android::apex
224