• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #define LOG_TAG "apexd"
18 
19 #include "apex_key.h"
20 
21 #include <unordered_map>
22 
23 #include <android-base/file.h>
24 #include <android-base/strings.h>
25 
26 #include "apex_constants.h"
27 #include "apex_file.h"
28 #include "apexd_utils.h"
29 #include "status_or.h"
30 #include "string_log.h"
31 
32 namespace android {
33 namespace apex {
34 
35 namespace {
36 
37 std::unordered_map<std::string, const std::string> gScannedApexKeys;
38 
39 using KeyPair = std::pair<std::string, std::string>;
collectEmbedddedApexKeysFromDir(const std::string & dir)40 StatusOr<std::vector<KeyPair>> collectEmbedddedApexKeysFromDir(
41     const std::string& dir) {
42   LOG(INFO) << "Scanning " << dir << " for embedded keys";
43   // list of <key_name, key_content> pairs
44   std::vector<KeyPair> ret;
45   if (access(dir.c_str(), F_OK) != 0 && errno == ENOENT) {
46     LOG(INFO) << "... does not exist. Skipping";
47     return StatusOr<std::vector<KeyPair>>(std::move(ret));
48   }
49   const bool scanBuiltinApexes = isPathForBuiltinApexes(dir);
50   if (!scanBuiltinApexes) {
51     return StatusOr<std::vector<KeyPair>>::MakeError(
52         StringLog() << "Can't scan embedded APEX keys from " << dir);
53   }
54   StatusOr<std::vector<std::string>> apex_files =
55       FindApexFilesByName(dir, scanBuiltinApexes);
56   if (!apex_files.Ok()) {
57     return StatusOr<std::vector<KeyPair>>::MakeError(apex_files.ErrorStatus());
58   }
59 
60   for (const auto& file : *apex_files) {
61     StatusOr<ApexFile> apex_file = ApexFile::Open(file);
62     if (!apex_file.Ok()) {
63       return StatusOr<std::vector<KeyPair>>::MakeError(
64           StringLog() << "Failed to open " << file << " : "
65                       << apex_file.ErrorMessage());
66     }
67     // name of the key is the name of the apex that the key is bundled in
68     ret.push_back(std::make_pair(apex_file->GetManifest().name(),
69                                  apex_file->GetBundledPublicKey()));
70   }
71   return StatusOr<std::vector<KeyPair>>(std::move(ret));
72 }
73 
updateScannedApexKeys(const std::vector<KeyPair> & key_pairs)74 Status updateScannedApexKeys(const std::vector<KeyPair>& key_pairs) {
75   for (const KeyPair& kp : key_pairs) {
76     if (gScannedApexKeys.find(kp.first) == gScannedApexKeys.end()) {
77       gScannedApexKeys.insert({kp.first, kp.second});
78     } else {
79       const std::string& existing_key = gScannedApexKeys.at(kp.first);
80       if (existing_key != kp.second) {
81         return Status::Fail(StringLog()
82                             << "Key for package " << kp.first
83                             << " does not match with the existing key");
84       }
85     }
86   }
87   return Status::Success();
88 }
89 
90 }  // namespace
91 
collectApexKeys(bool scanExternalKeys)92 Status collectApexKeys(bool scanExternalKeys) {
93   for (const auto& dir : kApexPackageBuiltinDirs) {
94     StatusOr<std::vector<KeyPair>> key_pairs =
95         collectEmbedddedApexKeysFromDir(dir);
96     if (!key_pairs.Ok()) {
97       return Status::Fail(StringLog() << "Failed to collect keys from " << dir
98                                       << " : " << key_pairs.ErrorMessage());
99     }
100     Status st = updateScannedApexKeys(*key_pairs);
101     if (!st.Ok()) {
102       return st;
103     }
104   }
105   return Status::Success();
106 }
107 
getApexKey(const std::string & key_name)108 StatusOr<const std::string> getApexKey(const std::string& key_name) {
109   if (gScannedApexKeys.find(key_name) == gScannedApexKeys.end()) {
110     return StatusOr<const std::string>::MakeError(
111         StringLog() << "No key found for package " << key_name);
112   }
113   return StatusOr<const std::string>(gScannedApexKeys[key_name]);
114 }
115 
116 }  // namespace apex
117 }  // namespace android
118