• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 <string>
18 
19 #include <errno.h>
20 #include <sys/stat.h>
21 
22 #include <android-base/file.h>
23 #include <android-base/logging.h>
24 #include <android-base/stringprintf.h>
25 #include <gtest/gtest.h>
26 
27 #include "apex_file.h"
28 #include "apexd_test_utils.h"
29 #include "apexd_verity.h"
30 
31 namespace android {
32 namespace apex {
33 
34 using namespace std::literals;
35 
36 using android::apex::testing::IsOk;
37 using android::base::GetExecutableDirectory;
38 using android::base::ReadFileToString;
39 using android::base::StringPrintf;
40 
GetTestDataDir()41 static std::string GetTestDataDir() { return GetExecutableDirectory(); }
GetTestFile(const std::string & name)42 static std::string GetTestFile(const std::string& name) {
43   return GetTestDataDir() + "/" + name;
44 }
45 
TEST(ApexdVerityTest,ReusesHashtree)46 TEST(ApexdVerityTest, ReusesHashtree) {
47   TemporaryDir td;
48 
49   auto apex = ApexFile::Open(GetTestFile("apex.apexd_test_no_hashtree.apex"));
50   ASSERT_TRUE(IsOk(apex));
51   auto verity_data = apex->VerifyApexVerity(apex->GetBundledPublicKey());
52   ASSERT_TRUE(IsOk(verity_data));
53 
54   auto hashtree_file = StringPrintf("%s/hashtree", td.path);
55   auto status = PrepareHashTree(*apex, *verity_data, hashtree_file);
56   ASSERT_TRUE(IsOk(status));
57   ASSERT_EQ(KRegenerate, *status);
58 
59   std::string first_hashtree;
60   ASSERT_TRUE(ReadFileToString(hashtree_file, &first_hashtree))
61       << "Failed to read " << hashtree_file;
62 
63   // Now call PrepareHashTree again. Since digest matches, hashtree should be
64   // reused.
65   status = PrepareHashTree(*apex, *verity_data, hashtree_file);
66   ASSERT_TRUE(IsOk(status));
67   ASSERT_EQ(kReuse, *status);
68 
69   std::string second_hashtree;
70   ASSERT_TRUE(ReadFileToString(hashtree_file, &second_hashtree))
71       << "Failed to read " << hashtree_file;
72 
73   // Hashtree file shouldn't be modified.
74   ASSERT_EQ(first_hashtree, second_hashtree)
75       << hashtree_file << " was regenerated";
76 }
77 
TEST(ApexdVerityTest,RegenerateHashree)78 TEST(ApexdVerityTest, RegenerateHashree) {
79   TemporaryDir td;
80 
81   auto apex = ApexFile::Open(GetTestFile("apex.apexd_test_no_hashtree.apex"));
82   ASSERT_TRUE(IsOk(apex));
83   auto verity_data = apex->VerifyApexVerity(apex->GetBundledPublicKey());
84   ASSERT_TRUE(IsOk(verity_data));
85 
86   auto hashtree_file = StringPrintf("%s/hashtree", td.path);
87   auto status = PrepareHashTree(*apex, *verity_data, hashtree_file);
88   ASSERT_TRUE(IsOk(status));
89   ASSERT_EQ(KRegenerate, *status);
90 
91   std::string first_hashtree;
92   ASSERT_TRUE(ReadFileToString(hashtree_file, &first_hashtree))
93       << "Failed to read " << hashtree_file;
94 
95   auto apex2 =
96       ApexFile::Open(GetTestFile("apex.apexd_test_no_hashtree_2.apex"));
97   ASSERT_TRUE(IsOk(apex2));
98   auto verity_data2 = apex2->VerifyApexVerity(apex2->GetBundledPublicKey());
99   ASSERT_TRUE(IsOk(verity_data2));
100 
101   // Now call PrepareHashTree again. Since digest doesn't match, hashtree
102   // should be regenerated.
103   status = PrepareHashTree(*apex2, *verity_data2, hashtree_file);
104   ASSERT_TRUE(IsOk(status));
105   ASSERT_EQ(KRegenerate, *status);
106 
107   std::string second_hashtree;
108   ASSERT_TRUE(ReadFileToString(hashtree_file, &second_hashtree))
109       << "Failed to read " << hashtree_file;
110 
111   // Hashtree file should be regenerated.
112   ASSERT_NE(first_hashtree, second_hashtree) << hashtree_file << " was reused";
113 }
114 
TEST(ApexdVerityTest,CannotPrepareHashTreeForCompressedApex)115 TEST(ApexdVerityTest, CannotPrepareHashTreeForCompressedApex) {
116   TemporaryDir td;
117 
118   auto apex =
119       ApexFile::Open(GetTestFile("com.android.apex.compressed.v1.capex"));
120   ASSERT_TRUE(IsOk(apex));
121   std::string hash_tree;
122   ApexVerityData verity_data;
123   auto result = PrepareHashTree(*apex, verity_data, hash_tree);
124   ASSERT_FALSE(IsOk(result));
125   ASSERT_THAT(
126       result.error().message(),
127       ::testing::HasSubstr("Cannot prepare HashTree of compressed APEX"));
128 }
129 
130 }  // namespace apex
131 }  // namespace android
132