diff options
author | Xiaoyong Zhou <xzhou@google.com> | 2019-03-08 09:59:42 -0800 |
---|---|---|
committer | Xiaoyong Zhou <xzhou@google.com> | 2019-03-08 09:59:42 -0800 |
commit | b29b27ec7f47bde45ee65752cb218d6f7a0860d6 (patch) | |
tree | 577e5818ba4bc84e4e02d55d9a409b941c1e567b /libkeyutils/mini_keyctl_utils.cpp | |
parent | 2ba61b775a568e15153e443a58e66217152792e1 (diff) |
Change mini-keyctl command format.
This CL change the mini-keyctl tool to make it compitable with libkeyctl
tool to make it more useful.
Bug: 112038861
Test: mini-keyctl padd asymmetric 'desc' .fs-verity < /path/to/cert.der
Test: mini-keyctl unlink <key_id> <keyring_id>
Test: mini-keyctl restrict_keyring <keyring_id>
Change-Id: I950f07c7718f173823ce5a5cd08e0d1a0e23a007
Diffstat (limited to 'libkeyutils/mini_keyctl_utils.cpp')
-rw-r--r-- | libkeyutils/mini_keyctl_utils.cpp | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/libkeyutils/mini_keyctl_utils.cpp b/libkeyutils/mini_keyctl_utils.cpp new file mode 100644 index 0000000000..c4fc96cc60 --- /dev/null +++ b/libkeyutils/mini_keyctl_utils.cpp @@ -0,0 +1,212 @@ +/* + * 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. + */ + +#include <mini_keyctl_utils.h> + +#include <dirent.h> +#include <errno.h> +#include <sys/types.h> +#include <unistd.h> + +#include <fstream> +#include <iostream> +#include <iterator> +#include <sstream> +#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 <keyutils.h> + +static constexpr int kMaxCertSize = 4096; + +std::vector<std::string> SplitBySpace(const std::string& s) { + std::istringstream iss(s); + return std::vector<std::string>{std::istream_iterator<std::string>{iss}, + std::istream_iterator<std::string>{}}; +} + +int AddCertsFromDir(const std::string& type, const std::string& desc_prefix, + const std::string& cert_dir, const std::string& keyring) { + key_serial_t keyring_id; + if (!GetKeyringId(keyring, &keyring_id)) { + LOG(ERROR) << "Can not find keyring id"; + return 1; + } + + std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(cert_dir.c_str()), closedir); + if (!dir) { + PLOG(WARNING) << "Failed to open directory " << cert_dir; + return 1; + } + int keys_added = 0; + struct dirent* dp; + while ((dp = readdir(dir.get())) != NULL) { + if (dp->d_type != DT_REG) { + continue; + } + std::string cert_path = cert_dir + "/" + dp->d_name; + std::string cert_buf; + if (!android::base::ReadFileToString(cert_path, &cert_buf, false /* follow_symlinks */)) { + LOG(ERROR) << "Failed to read " << cert_path; + continue; + } + + if (cert_buf.size() > kMaxCertSize) { + LOG(ERROR) << "Certficate size too large: " << cert_path; + continue; + } + + // Add key to keyring. + int key_desc_index = keys_added; + std::string key_desc = desc_prefix + std::to_string(key_desc_index); + key_serial_t key = + add_key(type.c_str(), key_desc.c_str(), &cert_buf[0], cert_buf.size(), keyring_id); + if (key < 0) { + PLOG(ERROR) << "Failed to add key to keyring: " << cert_path; + continue; + } + LOG(INFO) << "Key " << cert_path << " added to " << keyring << " with key id 0x" << std::hex + << key; + keys_added++; + } + return 0; +} + +bool GetKeyringId(const std::string& keyring_desc, key_serial_t* keyring_id) { + if (!keyring_id) { + LOG(ERROR) << "keyring_id is null"; + return false; + } + + // If the keyring id is already a hex number, directly convert it to keyring id + try { + key_serial_t id = std::stoi(keyring_desc, nullptr, 16); + *keyring_id = id; + return true; + } catch (const std::exception& e) { + LOG(INFO) << "search /proc/keys for keyring id"; + } + + // Only keys allowed by SELinux rules will be shown here. + std::ifstream proc_keys_file("/proc/keys"); + if (!proc_keys_file.is_open()) { + PLOG(ERROR) << "Failed to open /proc/keys"; + return false; + } + + std::string line; + while (getline(proc_keys_file, line)) { + std::vector<std::string> tokens = SplitBySpace(line); + if (tokens.size() < 9) { + continue; + } + std::string key_id = tokens[0]; + std::string key_type = tokens[7]; + // The key description may contain space. + std::string key_desc_prefix = tokens[8]; + // The prefix has a ":" at the end + std::string key_desc_pattern = keyring_desc + ":"; + if (key_type != "keyring" || key_desc_prefix != key_desc_pattern) { + continue; + } + *keyring_id = std::stoi(key_id, nullptr, 16); + return true; + } + return false; +} + +int Unlink(key_serial_t key, const std::string& keyring) { + key_serial_t keyring_id; + if (!GetKeyringId(keyring, &keyring_id)) { + LOG(ERROR) << "Can't find keyring " << keyring; + return 1; + } + + if (keyctl_unlink(key, keyring_id) < 0) { + PLOG(ERROR) << "Failed to unlink key 0x" << std::hex << key << " from keyring " << keyring_id; + return 1; + } + return 0; +} + +int Add(const std::string& type, const std::string& desc, const std::string& data, + const std::string& keyring) { + if (data.size() > kMaxCertSize) { + LOG(ERROR) << "Certificate too large"; + return 1; + } + + key_serial_t keyring_id; + if (!GetKeyringId(keyring, &keyring_id)) { + LOG(ERROR) << "Can not find keyring id"; + return 1; + } + + key_serial_t key = add_key(type.c_str(), desc.c_str(), data.c_str(), data.size(), keyring_id); + + if (key < 0) { + PLOG(ERROR) << "Failed to add key"; + return 1; + } + + LOG(INFO) << "Key " << desc << " added to " << keyring << " with key id: 0x" << std::hex << key; + return 0; +} + +int Padd(const std::string& type, const std::string& desc, const std::string& keyring) { + key_serial_t keyring_id; + if (!GetKeyringId(keyring, &keyring_id)) { + LOG(ERROR) << "Can not find keyring id"; + return 1; + } + + // read from stdin to get the certificates + std::istreambuf_iterator<char> begin(std::cin), end; + std::string data(begin, end); + + if (data.size() > kMaxCertSize) { + LOG(ERROR) << "Certificate too large"; + return 1; + } + + key_serial_t key = add_key(type.c_str(), desc.c_str(), data.c_str(), data.size(), keyring_id); + + if (key < 0) { + PLOG(ERROR) << "Failed to add key"; + return 1; + } + + LOG(INFO) << "Key " << desc << " added to " << keyring << " with key id: 0x" << std::hex << key; + return 0; +} + +int RestrictKeyring(const std::string& keyring) { + key_serial_t keyring_id; + if (!GetKeyringId(keyring, &keyring_id)) { + LOG(ERROR) << "Cannot find keyring id"; + return 1; + } + + if (keyctl_restrict_keyring(keyring_id, nullptr, nullptr) < 0) { + PLOG(ERROR) << "Cannot restrict keyring " << keyring; + return 1; + } + return 0; +} |