1*33f37583SAndroid Build Coastguard Worker /*
2*33f37583SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*33f37583SAndroid Build Coastguard Worker *
4*33f37583SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*33f37583SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*33f37583SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*33f37583SAndroid Build Coastguard Worker *
8*33f37583SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*33f37583SAndroid Build Coastguard Worker *
10*33f37583SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*33f37583SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*33f37583SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*33f37583SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*33f37583SAndroid Build Coastguard Worker * limitations under the License.
15*33f37583SAndroid Build Coastguard Worker */
16*33f37583SAndroid Build Coastguard Worker
17*33f37583SAndroid Build Coastguard Worker #include <limits>
18*33f37583SAndroid Build Coastguard Worker #include <string>
19*33f37583SAndroid Build Coastguard Worker
20*33f37583SAndroid Build Coastguard Worker #include <android-base/file.h>
21*33f37583SAndroid Build Coastguard Worker #include <android-base/logging.h>
22*33f37583SAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
23*33f37583SAndroid Build Coastguard Worker #include <android-base/strings.h>
24*33f37583SAndroid Build Coastguard Worker #include <gmock/gmock.h>
25*33f37583SAndroid Build Coastguard Worker #include <gtest/gtest.h>
26*33f37583SAndroid Build Coastguard Worker #include <libavb/libavb.h>
27*33f37583SAndroid Build Coastguard Worker #include <ziparchive/zip_archive.h>
28*33f37583SAndroid Build Coastguard Worker
29*33f37583SAndroid Build Coastguard Worker #include "apex_file.h"
30*33f37583SAndroid Build Coastguard Worker #include "apexd_test_utils.h"
31*33f37583SAndroid Build Coastguard Worker #include "apexd_utils.h"
32*33f37583SAndroid Build Coastguard Worker
33*33f37583SAndroid Build Coastguard Worker using android::base::GetExecutableDirectory;
34*33f37583SAndroid Build Coastguard Worker using android::base::Result;
35*33f37583SAndroid Build Coastguard Worker
36*33f37583SAndroid Build Coastguard Worker static const std::string kTestDataDir = GetExecutableDirectory() + "/";
37*33f37583SAndroid Build Coastguard Worker
38*33f37583SAndroid Build Coastguard Worker namespace android {
39*33f37583SAndroid Build Coastguard Worker namespace apex {
40*33f37583SAndroid Build Coastguard Worker namespace {
41*33f37583SAndroid Build Coastguard Worker
42*33f37583SAndroid Build Coastguard Worker struct ApexFileTestParam {
43*33f37583SAndroid Build Coastguard Worker const char* type;
44*33f37583SAndroid Build Coastguard Worker const char* prefix;
45*33f37583SAndroid Build Coastguard Worker };
46*33f37583SAndroid Build Coastguard Worker
47*33f37583SAndroid Build Coastguard Worker constexpr const ApexFileTestParam kParameters[] = {
48*33f37583SAndroid Build Coastguard Worker {"ext4", "apex.apexd_test"},
49*33f37583SAndroid Build Coastguard Worker {"f2fs", "apex.apexd_test_f2fs"},
50*33f37583SAndroid Build Coastguard Worker {"erofs", "apex.apexd_test_erofs"}};
51*33f37583SAndroid Build Coastguard Worker
52*33f37583SAndroid Build Coastguard Worker class ApexFileTest : public ::testing::TestWithParam<ApexFileTestParam> {};
53*33f37583SAndroid Build Coastguard Worker
54*33f37583SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(Apex, ApexFileTest, ::testing::ValuesIn(kParameters));
55*33f37583SAndroid Build Coastguard Worker
TEST_P(ApexFileTest,GetOffsetOfSimplePackage)56*33f37583SAndroid Build Coastguard Worker TEST_P(ApexFileTest, GetOffsetOfSimplePackage) {
57*33f37583SAndroid Build Coastguard Worker const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
58*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
59*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(apex_file.ok());
60*33f37583SAndroid Build Coastguard Worker
61*33f37583SAndroid Build Coastguard Worker uint32_t zip_image_offset;
62*33f37583SAndroid Build Coastguard Worker size_t zip_image_size;
63*33f37583SAndroid Build Coastguard Worker {
64*33f37583SAndroid Build Coastguard Worker ZipArchiveHandle handle;
65*33f37583SAndroid Build Coastguard Worker int32_t rc = OpenArchive(file_path.c_str(), &handle);
66*33f37583SAndroid Build Coastguard Worker ASSERT_EQ(0, rc);
67*33f37583SAndroid Build Coastguard Worker auto close_guard =
68*33f37583SAndroid Build Coastguard Worker android::base::make_scope_guard([&handle]() { CloseArchive(handle); });
69*33f37583SAndroid Build Coastguard Worker
70*33f37583SAndroid Build Coastguard Worker ZipEntry entry;
71*33f37583SAndroid Build Coastguard Worker rc = FindEntry(handle, "apex_payload.img", &entry);
72*33f37583SAndroid Build Coastguard Worker ASSERT_EQ(0, rc);
73*33f37583SAndroid Build Coastguard Worker
74*33f37583SAndroid Build Coastguard Worker zip_image_offset = entry.offset;
75*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(zip_image_offset % 4096, 0U);
76*33f37583SAndroid Build Coastguard Worker zip_image_size = entry.uncompressed_length;
77*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(zip_image_size, entry.compressed_length);
78*33f37583SAndroid Build Coastguard Worker }
79*33f37583SAndroid Build Coastguard Worker
80*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(zip_image_offset, apex_file->GetImageOffset().value());
81*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(zip_image_size, apex_file->GetImageSize().value());
82*33f37583SAndroid Build Coastguard Worker }
83*33f37583SAndroid Build Coastguard Worker
TEST_P(ApexFileTest,OpenBlockApex)84*33f37583SAndroid Build Coastguard Worker TEST_P(ApexFileTest, OpenBlockApex) {
85*33f37583SAndroid Build Coastguard Worker const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
86*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
87*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
88*33f37583SAndroid Build Coastguard Worker
89*33f37583SAndroid Build Coastguard Worker TemporaryFile temp_file;
90*33f37583SAndroid Build Coastguard Worker auto loop_device = WriteBlockApex(file_path, temp_file.path);
91*33f37583SAndroid Build Coastguard Worker
92*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file_sized = ApexFile::Open(temp_file.path);
93*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file_sized);
94*33f37583SAndroid Build Coastguard Worker
95*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(apex_file->GetImageOffset(), apex_file_sized->GetImageOffset());
96*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(apex_file->GetImageSize(), apex_file_sized->GetImageSize());
97*33f37583SAndroid Build Coastguard Worker }
98*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,GetOffsetMissingFile)99*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, GetOffsetMissingFile) {
100*33f37583SAndroid Build Coastguard Worker const std::string file_path = kTestDataDir + "missing.apex";
101*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
102*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(apex_file.ok());
103*33f37583SAndroid Build Coastguard Worker ASSERT_THAT(apex_file.error().message(),
104*33f37583SAndroid Build Coastguard Worker ::testing::HasSubstr("Failed to open package"));
105*33f37583SAndroid Build Coastguard Worker }
106*33f37583SAndroid Build Coastguard Worker
TEST_P(ApexFileTest,GetApexManifest)107*33f37583SAndroid Build Coastguard Worker TEST_P(ApexFileTest, GetApexManifest) {
108*33f37583SAndroid Build Coastguard Worker const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
109*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
110*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
111*33f37583SAndroid Build Coastguard Worker EXPECT_EQ("com.android.apex.test_package", apex_file->GetManifest().name());
112*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(1u, apex_file->GetManifest().version());
113*33f37583SAndroid Build Coastguard Worker }
114*33f37583SAndroid Build Coastguard Worker
TEST_P(ApexFileTest,VerifyApexVerity)115*33f37583SAndroid Build Coastguard Worker TEST_P(ApexFileTest, VerifyApexVerity) {
116*33f37583SAndroid Build Coastguard Worker const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
117*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
118*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
119*33f37583SAndroid Build Coastguard Worker
120*33f37583SAndroid Build Coastguard Worker auto verity_or =
121*33f37583SAndroid Build Coastguard Worker apex_file->VerifyApexVerity(apex_file->GetBundledPublicKey());
122*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(verity_or);
123*33f37583SAndroid Build Coastguard Worker
124*33f37583SAndroid Build Coastguard Worker const ApexVerityData& data = *verity_or;
125*33f37583SAndroid Build Coastguard Worker EXPECT_NE(nullptr, data.desc.get());
126*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(std::string("368a22e64858647bc45498e92f749f85482ac468"
127*33f37583SAndroid Build Coastguard Worker "50ca7ec8071f49dfa47a243c"),
128*33f37583SAndroid Build Coastguard Worker data.salt);
129*33f37583SAndroid Build Coastguard Worker
130*33f37583SAndroid Build Coastguard Worker const std::string digest_path =
131*33f37583SAndroid Build Coastguard Worker kTestDataDir + GetParam().prefix + "_digest.txt";
132*33f37583SAndroid Build Coastguard Worker std::string root_digest;
133*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(digest_path, &root_digest))
134*33f37583SAndroid Build Coastguard Worker << "Failed to read " << digest_path;
135*33f37583SAndroid Build Coastguard Worker root_digest = android::base::Trim(root_digest);
136*33f37583SAndroid Build Coastguard Worker
137*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(std::string(root_digest), data.root_digest);
138*33f37583SAndroid Build Coastguard Worker }
139*33f37583SAndroid Build Coastguard Worker
TEST_P(ApexFileTest,VerifyApexVerityWrongKey)140*33f37583SAndroid Build Coastguard Worker TEST_P(ApexFileTest, VerifyApexVerityWrongKey) {
141*33f37583SAndroid Build Coastguard Worker const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
142*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
143*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
144*33f37583SAndroid Build Coastguard Worker
145*33f37583SAndroid Build Coastguard Worker auto verity_or = apex_file->VerifyApexVerity("wrong-key");
146*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(verity_or.ok());
147*33f37583SAndroid Build Coastguard Worker }
148*33f37583SAndroid Build Coastguard Worker
TEST_P(ApexFileTest,GetBundledPublicKey)149*33f37583SAndroid Build Coastguard Worker TEST_P(ApexFileTest, GetBundledPublicKey) {
150*33f37583SAndroid Build Coastguard Worker const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
151*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
152*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
153*33f37583SAndroid Build Coastguard Worker
154*33f37583SAndroid Build Coastguard Worker const std::string key_path =
155*33f37583SAndroid Build Coastguard Worker kTestDataDir + "apexd_testdata/com.android.apex.test_package.avbpubkey";
156*33f37583SAndroid Build Coastguard Worker std::string key_content;
157*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(key_path, &key_content))
158*33f37583SAndroid Build Coastguard Worker << "Failed to read " << key_path;
159*33f37583SAndroid Build Coastguard Worker
160*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(key_content, apex_file->GetBundledPublicKey());
161*33f37583SAndroid Build Coastguard Worker }
162*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,CorrutedApexB146895998)163*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, CorrutedApexB146895998) {
164*33f37583SAndroid Build Coastguard Worker const std::string apex_path = kTestDataDir + "corrupted_b146895998.apex";
165*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex = ApexFile::Open(apex_path);
166*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex);
167*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(apex->VerifyApexVerity("ignored").ok());
168*33f37583SAndroid Build Coastguard Worker }
169*33f37583SAndroid Build Coastguard Worker
TEST_P(ApexFileTest,RetrieveFsType)170*33f37583SAndroid Build Coastguard Worker TEST_P(ApexFileTest, RetrieveFsType) {
171*33f37583SAndroid Build Coastguard Worker const std::string file_path = kTestDataDir + GetParam().prefix + ".apex";
172*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
173*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(apex_file.ok());
174*33f37583SAndroid Build Coastguard Worker
175*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(std::string(GetParam().type), apex_file->GetFsType().value());
176*33f37583SAndroid Build Coastguard Worker }
177*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,OpenInvalidFilesystem)178*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, OpenInvalidFilesystem) {
179*33f37583SAndroid Build Coastguard Worker const std::string file_path =
180*33f37583SAndroid Build Coastguard Worker kTestDataDir + "apex.apexd_test_corrupt_superblock_apex.apex";
181*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
182*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(apex_file.ok());
183*33f37583SAndroid Build Coastguard Worker ASSERT_THAT(apex_file.error().message(),
184*33f37583SAndroid Build Coastguard Worker ::testing::HasSubstr("Failed to retrieve filesystem type"));
185*33f37583SAndroid Build Coastguard Worker }
186*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,OpenCompressedApexFile)187*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, OpenCompressedApexFile) {
188*33f37583SAndroid Build Coastguard Worker const std::string file_path =
189*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1.capex";
190*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
191*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(apex_file.ok());
192*33f37583SAndroid Build Coastguard Worker
193*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(apex_file->IsCompressed());
194*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(apex_file->GetImageOffset().has_value());
195*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(apex_file->GetImageSize().has_value());
196*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(apex_file->GetFsType().has_value());
197*33f37583SAndroid Build Coastguard Worker }
198*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,OpenFailureForCompressedApexWithoutApex)199*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, OpenFailureForCompressedApexWithoutApex) {
200*33f37583SAndroid Build Coastguard Worker const std::string file_path =
201*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1_without_apex.capex";
202*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
203*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(apex_file.ok());
204*33f37583SAndroid Build Coastguard Worker ASSERT_THAT(apex_file.error().message(),
205*33f37583SAndroid Build Coastguard Worker ::testing::HasSubstr("Could not find entry"));
206*33f37583SAndroid Build Coastguard Worker }
207*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,GetCompressedApexManifest)208*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, GetCompressedApexManifest) {
209*33f37583SAndroid Build Coastguard Worker const std::string file_path =
210*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1.capex";
211*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
212*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
213*33f37583SAndroid Build Coastguard Worker EXPECT_EQ("com.android.apex.compressed", apex_file->GetManifest().name());
214*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(1u, apex_file->GetManifest().version());
215*33f37583SAndroid Build Coastguard Worker }
216*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,GetBundledPublicKeyOfCompressedApex)217*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, GetBundledPublicKeyOfCompressedApex) {
218*33f37583SAndroid Build Coastguard Worker const std::string file_path =
219*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1.capex";
220*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
221*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
222*33f37583SAndroid Build Coastguard Worker
223*33f37583SAndroid Build Coastguard Worker const std::string key_path =
224*33f37583SAndroid Build Coastguard Worker kTestDataDir + "apexd_testdata/com.android.apex.compressed.avbpubkey";
225*33f37583SAndroid Build Coastguard Worker std::string key_content;
226*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFileToString(key_path, &key_content))
227*33f37583SAndroid Build Coastguard Worker << "Failed to read " << key_path;
228*33f37583SAndroid Build Coastguard Worker
229*33f37583SAndroid Build Coastguard Worker EXPECT_EQ(key_content, apex_file->GetBundledPublicKey());
230*33f37583SAndroid Build Coastguard Worker }
231*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,CannotVerifyApexVerityForCompressedApex)232*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, CannotVerifyApexVerityForCompressedApex) {
233*33f37583SAndroid Build Coastguard Worker const std::string file_path =
234*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1.capex";
235*33f37583SAndroid Build Coastguard Worker auto apex = ApexFile::Open(file_path);
236*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex);
237*33f37583SAndroid Build Coastguard Worker auto result = apex->VerifyApexVerity(apex->GetBundledPublicKey());
238*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(result.ok());
239*33f37583SAndroid Build Coastguard Worker ASSERT_THAT(
240*33f37583SAndroid Build Coastguard Worker result.error().message(),
241*33f37583SAndroid Build Coastguard Worker ::testing::HasSubstr("Cannot verify ApexVerity of compressed APEX"));
242*33f37583SAndroid Build Coastguard Worker }
243*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,DecompressCompressedApex)244*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, DecompressCompressedApex) {
245*33f37583SAndroid Build Coastguard Worker const std::string file_path =
246*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1.capex";
247*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
248*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
249*33f37583SAndroid Build Coastguard Worker
250*33f37583SAndroid Build Coastguard Worker // Create a temp dir for decompression
251*33f37583SAndroid Build Coastguard Worker TemporaryDir tmp_dir;
252*33f37583SAndroid Build Coastguard Worker
253*33f37583SAndroid Build Coastguard Worker const std::string package_name = apex_file->GetManifest().name();
254*33f37583SAndroid Build Coastguard Worker const std::string decompression_file_path =
255*33f37583SAndroid Build Coastguard Worker tmp_dir.path + package_name + ".capex";
256*33f37583SAndroid Build Coastguard Worker
257*33f37583SAndroid Build Coastguard Worker auto result = apex_file->Decompress(decompression_file_path);
258*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(result);
259*33f37583SAndroid Build Coastguard Worker
260*33f37583SAndroid Build Coastguard Worker // Assert output path is not empty
261*33f37583SAndroid Build Coastguard Worker auto exists = PathExists(decompression_file_path);
262*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(exists);
263*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(*exists) << decompression_file_path << " does not exist";
264*33f37583SAndroid Build Coastguard Worker
265*33f37583SAndroid Build Coastguard Worker // Assert properties on the decompressed APEX.
266*33f37583SAndroid Build Coastguard Worker auto decompressed_apex_file = ApexFile::Open(decompression_file_path);
267*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(decompressed_apex_file);
268*33f37583SAndroid Build Coastguard Worker ASSERT_EQ(apex_file->GetBundledPublicKey(),
269*33f37583SAndroid Build Coastguard Worker decompressed_apex_file->GetBundledPublicKey());
270*33f37583SAndroid Build Coastguard Worker ASSERT_EQ(apex_file->GetManifest().name(),
271*33f37583SAndroid Build Coastguard Worker decompressed_apex_file->GetManifest().name());
272*33f37583SAndroid Build Coastguard Worker ASSERT_EQ(apex_file->GetManifest().version(),
273*33f37583SAndroid Build Coastguard Worker decompressed_apex_file->GetManifest().version());
274*33f37583SAndroid Build Coastguard Worker auto verity_status = decompressed_apex_file->VerifyApexVerity(
275*33f37583SAndroid Build Coastguard Worker decompressed_apex_file->GetBundledPublicKey());
276*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(verity_status);
277*33f37583SAndroid Build Coastguard Worker }
278*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,DecompressFailForNormalApex)279*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, DecompressFailForNormalApex) {
280*33f37583SAndroid Build Coastguard Worker const std::string file_path =
281*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1.apex";
282*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
283*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
284*33f37583SAndroid Build Coastguard Worker
285*33f37583SAndroid Build Coastguard Worker TemporaryFile decompression_file;
286*33f37583SAndroid Build Coastguard Worker
287*33f37583SAndroid Build Coastguard Worker auto result = apex_file->Decompress(decompression_file.path);
288*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(result.ok());
289*33f37583SAndroid Build Coastguard Worker ASSERT_THAT(result.error().message(),
290*33f37583SAndroid Build Coastguard Worker ::testing::HasSubstr("Cannot decompress an uncompressed APEX"));
291*33f37583SAndroid Build Coastguard Worker }
292*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,DecompressFailIfDecompressionPathExists)293*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, DecompressFailIfDecompressionPathExists) {
294*33f37583SAndroid Build Coastguard Worker const std::string file_path =
295*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1.capex";
296*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
297*33f37583SAndroid Build Coastguard Worker
298*33f37583SAndroid Build Coastguard Worker // Attempt to decompress in a path that already exists
299*33f37583SAndroid Build Coastguard Worker TemporaryFile decompression_file;
300*33f37583SAndroid Build Coastguard Worker auto exists = PathExists(decompression_file.path);
301*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(exists);
302*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(*exists) << decompression_file.path << " does not exist";
303*33f37583SAndroid Build Coastguard Worker
304*33f37583SAndroid Build Coastguard Worker auto result = apex_file->Decompress(decompression_file.path);
305*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(result.ok());
306*33f37583SAndroid Build Coastguard Worker ASSERT_THAT(result.error().message(),
307*33f37583SAndroid Build Coastguard Worker ::testing::HasSubstr("Failed to open decompression destination"));
308*33f37583SAndroid Build Coastguard Worker }
309*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,GetPathReturnsRealpath)310*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, GetPathReturnsRealpath) {
311*33f37583SAndroid Build Coastguard Worker const std::string real_path = kTestDataDir + "apex.apexd_test.apex";
312*33f37583SAndroid Build Coastguard Worker const std::string symlink_path =
313*33f37583SAndroid Build Coastguard Worker kTestDataDir + "apex.apexd_test.symlink.apex";
314*33f37583SAndroid Build Coastguard Worker
315*33f37583SAndroid Build Coastguard Worker // In case the link already exists
316*33f37583SAndroid Build Coastguard Worker int ret = unlink(symlink_path.c_str());
317*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(ret == 0 || errno == ENOENT)
318*33f37583SAndroid Build Coastguard Worker << "failed to unlink " << symlink_path;
319*33f37583SAndroid Build Coastguard Worker
320*33f37583SAndroid Build Coastguard Worker ret = symlink(real_path.c_str(), symlink_path.c_str());
321*33f37583SAndroid Build Coastguard Worker ASSERT_EQ(0, ret) << "failed to create symlink at " << symlink_path;
322*33f37583SAndroid Build Coastguard Worker
323*33f37583SAndroid Build Coastguard Worker // Open with the symlink. Realpath is expected.
324*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(symlink_path);
325*33f37583SAndroid Build Coastguard Worker ASSERT_RESULT_OK(apex_file);
326*33f37583SAndroid Build Coastguard Worker ASSERT_EQ(real_path, apex_file->GetPath());
327*33f37583SAndroid Build Coastguard Worker }
328*33f37583SAndroid Build Coastguard Worker
TEST(ApexFileTest,CompressedSharedLibsApexIsRejected)329*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, CompressedSharedLibsApexIsRejected) {
330*33f37583SAndroid Build Coastguard Worker const std::string file_path =
331*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed_sharedlibs.capex";
332*33f37583SAndroid Build Coastguard Worker Result<ApexFile> apex_file = ApexFile::Open(file_path);
333*33f37583SAndroid Build Coastguard Worker
334*33f37583SAndroid Build Coastguard Worker ASSERT_FALSE(apex_file.ok());
335*33f37583SAndroid Build Coastguard Worker ASSERT_THAT(apex_file.error().message(),
336*33f37583SAndroid Build Coastguard Worker ::testing::HasSubstr("Apex providing sharedlibs shouldn't "
337*33f37583SAndroid Build Coastguard Worker "be compressed"));
338*33f37583SAndroid Build Coastguard Worker }
339*33f37583SAndroid Build Coastguard Worker
340*33f37583SAndroid Build Coastguard Worker // Check if CAPEX contains originalApexDigest in its manifest
TEST(ApexFileTest,OriginalApexDigest)341*33f37583SAndroid Build Coastguard Worker TEST(ApexFileTest, OriginalApexDigest) {
342*33f37583SAndroid Build Coastguard Worker const std::string capex_path =
343*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1.capex";
344*33f37583SAndroid Build Coastguard Worker auto capex = ApexFile::Open(capex_path);
345*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(capex.ok());
346*33f37583SAndroid Build Coastguard Worker const std::string decompressed_apex_path =
347*33f37583SAndroid Build Coastguard Worker kTestDataDir + "com.android.apex.compressed.v1.apex";
348*33f37583SAndroid Build Coastguard Worker auto decompressed_apex = ApexFile::Open(decompressed_apex_path);
349*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(decompressed_apex.ok());
350*33f37583SAndroid Build Coastguard Worker // Validate root digest
351*33f37583SAndroid Build Coastguard Worker auto digest = decompressed_apex->VerifyApexVerity(
352*33f37583SAndroid Build Coastguard Worker decompressed_apex->GetBundledPublicKey());
353*33f37583SAndroid Build Coastguard Worker ASSERT_TRUE(digest.ok());
354*33f37583SAndroid Build Coastguard Worker ASSERT_EQ(digest->root_digest,
355*33f37583SAndroid Build Coastguard Worker capex->GetManifest().capexmetadata().originalapexdigest());
356*33f37583SAndroid Build Coastguard Worker }
357*33f37583SAndroid Build Coastguard Worker } // namespace
358*33f37583SAndroid Build Coastguard Worker } // namespace apex
359*33f37583SAndroid Build Coastguard Worker } // namespace android
360