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