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 "fsverity_init" 18 19 #include <sys/types.h> 20 21 #include <filesystem> 22 #include <string> 23 24 #include <android-base/file.h> 25 #include <android-base/logging.h> 26 #include <android-base/properties.h> 27 #include <android-base/strings.h> 28 #include <log/log.h> 29 #include <mini_keyctl_utils.h> 30 31 bool LoadKeyToKeyring(key_serial_t keyring_id, const char* desc, const char* data, size_t size) { 32 key_serial_t key = add_key("asymmetric", desc, data, size, keyring_id); 33 if (key < 0) { 34 PLOG(ERROR) << "Failed to add key"; 35 return false; 36 } 37 return true; 38 } 39 40 void LoadKeyFromStdin(key_serial_t keyring_id, const char* keyname) { 41 std::string content; 42 if (!android::base::ReadFdToString(STDIN_FILENO, &content)) { 43 LOG(ERROR) << "Failed to read key from stdin"; 44 return; 45 } 46 if (!LoadKeyToKeyring(keyring_id, keyname, content.c_str(), content.size())) { 47 LOG(ERROR) << "Failed to load key from stdin"; 48 } 49 } 50 51 void LoadKeyFromFile(key_serial_t keyring_id, const char* keyname, const std::string& path) { 52 LOG(INFO) << "LoadKeyFromFile path=" << path << " keyname=" << keyname; 53 std::string content; 54 if (!android::base::ReadFileToString(path, &content)) { 55 LOG(ERROR) << "Failed to read key from " << path; 56 return; 57 } 58 if (!LoadKeyToKeyring(keyring_id, keyname, content.c_str(), content.size())) { 59 LOG(ERROR) << "Failed to load key from " << path; 60 } 61 } 62 63 void LoadKeyFromDirectory(key_serial_t keyring_id, const char* keyname_prefix, const char* dir) { 64 if (!std::filesystem::exists(dir)) { 65 return; 66 } 67 int counter = 0; 68 for (const auto& entry : std::filesystem::directory_iterator(dir)) { 69 if (!android::base::EndsWithIgnoreCase(entry.path().c_str(), ".der")) continue; 70 std::string keyname = keyname_prefix + std::to_string(counter); 71 counter++; 72 LoadKeyFromFile(keyring_id, keyname.c_str(), entry.path()); 73 } 74 } 75 76 void LoadKeyFromVerifiedPartitions(key_serial_t keyring_id) { 77 // NB: Directories need to be synced with FileIntegrityService.java in 78 // frameworks/base. 79 LoadKeyFromDirectory(keyring_id, "fsv_system_", "/system/etc/security/fsverity"); 80 LoadKeyFromDirectory(keyring_id, "fsv_product_", "/product/etc/security/fsverity"); 81 } 82 83 int main(int argc, const char** argv) { 84 if (argc < 2) { 85 LOG(ERROR) << "Not enough arguments"; 86 return -1; 87 } 88 89 key_serial_t keyring_id = android::GetKeyringId(".fs-verity"); 90 if (keyring_id < 0) { 91 LOG(ERROR) << "Failed to find .fs-verity keyring id"; 92 return -1; 93 } 94 95 const std::string_view command = argv[1]; 96 97 if (command == "--load-verified-keys") { 98 LoadKeyFromVerifiedPartitions(keyring_id); 99 } else if (command == "--load-extra-key") { 100 if (argc != 3) { 101 LOG(ERROR) << "--load-extra-key requires <key_name> argument."; 102 return -1; 103 } 104 LoadKeyFromStdin(keyring_id, argv[2]); 105 } else if (command == "--lock") { 106 // Requires files backed by fs-verity to be verified with a key in .fs-verity 107 // keyring. 108 if (!android::base::WriteStringToFile("1", "/proc/sys/fs/verity/require_signatures")) { 109 PLOG(ERROR) << "Failed to enforce fs-verity signature"; 110 } 111 112 if (!android::base::GetBoolProperty("ro.debuggable", false)) { 113 if (keyctl_restrict_keyring(keyring_id, nullptr, nullptr) < 0) { 114 PLOG(ERROR) << "Cannot restrict .fs-verity keyring"; 115 } 116 } 117 } else { 118 LOG(ERROR) << "Unknown argument(s)."; 119 return -1; 120 } 121 122 return 0; 123 } 124