diff options
author | Victor Hsieh <victorhsieh@google.com> | 2019-08-26 11:26:27 -0700 |
---|---|---|
committer | Victor Hsieh <victorhsieh@google.com> | 2019-09-25 09:52:19 -0700 |
commit | d0a4b202a4be87df5957558df095d59f5f51d47a (patch) | |
tree | 5824a65e92f3d56bf6952cc477b820a6625c57ab | |
parent | 1ba438c4ac970c4cf9b679cdde457c65a1f352b3 (diff) | |
download | security-d0a4b202a4be87df5957558df095d59f5f51d47a.tar.gz |
Rewrite fsverity_init in C++ and load keys from keystore
Test: still see keys loaded from /product appears in /proc/keys
Test: Add X.509 DER cert files to keystore, see the key in
/proc/keys after reboot
Bug: 112038744
Change-Id: I08006d8befa69e4bf416a2bed9e1813725877147
-rw-r--r-- | fsverity_init/Android.bp | 18 | ||||
-rw-r--r-- | fsverity_init/fsverity_init.cpp | 111 |
2 files changed, 129 insertions, 0 deletions
diff --git a/fsverity_init/Android.bp b/fsverity_init/Android.bp new file mode 100644 index 00000000..407849d5 --- /dev/null +++ b/fsverity_init/Android.bp @@ -0,0 +1,18 @@ +cc_binary { + name: "fsverity_init", + srcs: [ + "fsverity_init.cpp", + ], + static_libs: [ + "libc++fs", + "libmini_keyctl_static", + ], + shared_libs: [ + "libbase", + "libkeystore_binder", + "libkeyutils", + "liblog", + "liblogwrap", + ], + cflags: ["-Werror", "-Wall", "-Wextra"], +} diff --git a/fsverity_init/fsverity_init.cpp b/fsverity_init/fsverity_init.cpp new file mode 100644 index 00000000..70523756 --- /dev/null +++ b/fsverity_init/fsverity_init.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "fsverity_init" + +#include <sys/types.h> + +#include <filesystem> +#include <memory> +#include <string> +#include <vector> + +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/properties.h> +#include <android-base/strings.h> +#include <keystore/keystore_client.h> +#include <keystore/keystore_client_impl.h> +#include <keystore/keystore_get.h> +#include <log/log.h> +#include <mini_keyctl_utils.h> +#include <private/android_filesystem_config.h> + +bool LoadKeyToKeyring(key_serial_t keyring_id, const char* desc, const char* data, size_t size) { + key_serial_t key = add_key("asymmetric", desc, data, size, keyring_id); + if (key < 0) { + PLOG(ERROR) << "Failed to add key"; + return false; + } + return true; +} + +void LoadKeyFromVerifiedPartitions(key_serial_t keyring_id) { + const char* dir = "/product/etc/security/fsverity"; + if (!std::filesystem::exists(dir)) { + LOG(ERROR) << "no such dir: " << dir; + return; + } + for (const auto& entry : std::filesystem::directory_iterator(dir)) { + if (!android::base::EndsWithIgnoreCase(entry.path().c_str(), ".der")) continue; + std::string content; + if (!android::base::ReadFileToString(entry.path(), &content)) { + continue; + } + if (!LoadKeyToKeyring(keyring_id, "fsv_system", content.c_str(), content.size())) { + LOG(ERROR) << "Failed to load key from " << entry.path(); + } + } +} + +std::unique_ptr<keystore::KeystoreClient> CreateKeystoreInstance() { + return std::unique_ptr<keystore::KeystoreClient>( + static_cast<keystore::KeystoreClient*>(new keystore::KeystoreClientImpl)); +} + +void LoadKeysFromKeystore(key_serial_t keyring_id) { + auto client = CreateKeystoreInstance(); + + std::vector<std::string> aliases; + if (client == nullptr || !client->listKeysOfUid("FSV_", AID_FSVERITY_CERT, &aliases)) { + LOG(ERROR) << "Failed to list key"; + return; + } + + // Always try to load all keys even if some fails to load. The rest may still + // be important to have. + for (auto& alias : aliases) { + auto blob = client->getKey(alias, AID_FSVERITY_CERT); + if (!LoadKeyToKeyring(keyring_id, "fsv_user", reinterpret_cast<char*>(blob->data()), + blob->size())) { + LOG(ERROR) << "Failed to load key " << alias << " from keyring"; + } + } +} + +int main(int /*argc*/, const char** /*argv*/) { + key_serial_t keyring_id = android::GetKeyringId(".fs-verity"); + if (keyring_id < 0) { + LOG(ERROR) << "Failed to find .fs-verity keyring id"; + return -1; + } + + // Requires files backed by fs-verity to be verified with a key in .fs-verity + // keyring. + if (!android::base::WriteStringToFile("1", "/proc/sys/fs/verity/require_signatures")) { + PLOG(ERROR) << "Failed to enforce fs-verity signature"; + } + + LoadKeyFromVerifiedPartitions(keyring_id); + LoadKeysFromKeystore(keyring_id); + + if (!android::base::GetBoolProperty("ro.debuggable", false)) { + if (keyctl_restrict_keyring(keyring_id, nullptr, nullptr) < 0) { + PLOG(ERROR) << "Cannot restrict .fs-verity keyring"; + } + } + return 0; +} |