blob: a17b8b2e37acb81f9ea9f48f27fe9fecc1d40ee9 [file] [log] [blame]
Paul Crowleyf71ace32016-06-02 11:01:19 -07001/*
2 * Copyright (C) 2016 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 "KeyUtil.h"
18
Eric Biggersba997ee2018-10-23 13:07:43 -070019#include <linux/fs.h>
Paul Crowleyf71ace32016-06-02 11:01:19 -070020#include <iomanip>
21#include <sstream>
22#include <string>
23
Paul Crowleyf71ace32016-06-02 11:01:19 -070024#include <openssl/sha.h>
25
26#include <android-base/file.h>
27#include <android-base/logging.h>
Elliott Hughesc3bda182017-05-09 17:01:04 -070028#include <keyutils.h>
Paul Crowleyf71ace32016-06-02 11:01:19 -070029
30#include "KeyStorage.h"
31#include "Utils.h"
32
33namespace android {
34namespace vold {
35
Eric Biggersa701c452018-10-23 13:06:55 -070036constexpr int FS_AES_256_XTS_KEY_SIZE = 64;
Pavel Grafove2e2d302017-08-01 17:15:53 +010037
38bool randomKey(KeyBuffer* key) {
Eric Biggersa701c452018-10-23 13:06:55 -070039 *key = KeyBuffer(FS_AES_256_XTS_KEY_SIZE);
Pavel Grafove2e2d302017-08-01 17:15:53 +010040 if (ReadRandomBytes(key->size(), key->data()) != 0) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070041 // TODO status_t plays badly with PLOG, fix it.
42 LOG(ERROR) << "Random read failed";
43 return false;
44 }
45 return true;
46}
47
48// Get raw keyref - used to make keyname and to pass to ioctl
Eric Biggersba997ee2018-10-23 13:07:43 -070049static std::string generateKeyRef(const uint8_t* key, int length) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070050 SHA512_CTX c;
51
52 SHA512_Init(&c);
53 SHA512_Update(&c, key, length);
54 unsigned char key_ref1[SHA512_DIGEST_LENGTH];
55 SHA512_Final(key_ref1, &c);
56
57 SHA512_Init(&c);
58 SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
59 unsigned char key_ref2[SHA512_DIGEST_LENGTH];
60 SHA512_Final(key_ref2, &c);
61
Eric Biggersa701c452018-10-23 13:06:55 -070062 static_assert(FS_KEY_DESCRIPTOR_SIZE <= SHA512_DIGEST_LENGTH, "Hash too short for descriptor");
63 return std::string((char*)key_ref2, FS_KEY_DESCRIPTOR_SIZE);
Paul Crowleyf71ace32016-06-02 11:01:19 -070064}
65
Eric Biggersa701c452018-10-23 13:06:55 -070066static bool fillKey(const KeyBuffer& key, fscrypt_key* fs_key) {
67 if (key.size() != FS_AES_256_XTS_KEY_SIZE) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070068 LOG(ERROR) << "Wrong size key " << key.size();
69 return false;
70 }
Eric Biggersa701c452018-10-23 13:06:55 -070071 static_assert(FS_AES_256_XTS_KEY_SIZE <= sizeof(fs_key->raw), "Key too long!");
72 fs_key->mode = FS_ENCRYPTION_MODE_AES_256_XTS;
73 fs_key->size = key.size();
74 memset(fs_key->raw, 0, sizeof(fs_key->raw));
75 memcpy(fs_key->raw, key.data(), key.size());
Paul Crowleyf71ace32016-06-02 11:01:19 -070076 return true;
77}
78
Paul Crowley14c8c072018-09-18 13:30:21 -070079static char const* const NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt", nullptr};
Paul Crowleycd8bfe32017-06-19 16:05:55 -070080
81static std::string keyname(const std::string& prefix, const std::string& raw_ref) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070082 std::ostringstream o;
Paul Crowleycd8bfe32017-06-19 16:05:55 -070083 o << prefix << ":";
Chen, Luhai5744dfe2017-08-18 14:49:45 +080084 for (unsigned char i : raw_ref) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070085 o << std::hex << std::setw(2) << std::setfill('0') << (int)i;
86 }
87 return o.str();
88}
89
90// Get the keyring we store all keys in
Eric Biggersa701c452018-10-23 13:06:55 -070091static bool fscryptKeyring(key_serial_t* device_keyring) {
92 *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
Paul Crowleyf71ace32016-06-02 11:01:19 -070093 if (*device_keyring == -1) {
94 PLOG(ERROR) << "Unable to find device keyring";
95 return false;
96 }
97 return true;
98}
99
100// Install password into global keyring
101// Return raw key reference for use in policy
Pavel Grafove2e2d302017-08-01 17:15:53 +0100102bool installKey(const KeyBuffer& key, std::string* raw_ref) {
Eric Biggersa701c452018-10-23 13:06:55 -0700103 // Place fscrypt_key into automatically zeroing buffer.
104 KeyBuffer fsKeyBuffer(sizeof(fscrypt_key));
105 fscrypt_key& fs_key = *reinterpret_cast<fscrypt_key*>(fsKeyBuffer.data());
Pavel Grafove2e2d302017-08-01 17:15:53 +0100106
Eric Biggersa701c452018-10-23 13:06:55 -0700107 if (!fillKey(key, &fs_key)) return false;
108 *raw_ref = generateKeyRef(fs_key.raw, fs_key.size);
Paul Crowleyf71ace32016-06-02 11:01:19 -0700109 key_serial_t device_keyring;
Eric Biggersa701c452018-10-23 13:06:55 -0700110 if (!fscryptKeyring(&device_keyring)) return false;
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700111 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
112 auto ref = keyname(*name_prefix, *raw_ref);
113 key_serial_t key_id =
Eric Biggersa701c452018-10-23 13:06:55 -0700114 add_key("logon", ref.c_str(), (void*)&fs_key, sizeof(fs_key), device_keyring);
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700115 if (key_id == -1) {
116 PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
117 return false;
118 }
119 LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
120 << " in process " << getpid();
Paul Crowleyf71ace32016-06-02 11:01:19 -0700121 }
Paul Crowleyf71ace32016-06-02 11:01:19 -0700122 return true;
123}
124
125bool evictKey(const std::string& raw_ref) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700126 key_serial_t device_keyring;
Eric Biggersa701c452018-10-23 13:06:55 -0700127 if (!fscryptKeyring(&device_keyring)) return false;
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700128 bool success = true;
129 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
130 auto ref = keyname(*name_prefix, raw_ref);
131 auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
Paul Crowleyf71ace32016-06-02 11:01:19 -0700132
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700133 // Unlink the key from the keyring. Prefer unlinking to revoking or
134 // invalidating, since unlinking is actually no less secure currently, and
135 // it avoids bugs in certain kernel versions where the keyring key is
136 // referenced from places it shouldn't be.
137 if (keyctl_unlink(key_serial, device_keyring) != 0) {
138 PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
139 success = false;
140 } else {
141 LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref;
142 }
Paul Crowleyf71ace32016-06-02 11:01:19 -0700143 }
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700144 return success;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700145}
146
Paul Crowley26a53882017-10-26 11:16:39 -0700147bool retrieveAndInstallKey(bool create_if_absent, const KeyAuthentication& key_authentication,
148 const std::string& key_path, const std::string& tmp_path,
149 std::string* key_ref) {
Pavel Grafove2e2d302017-08-01 17:15:53 +0100150 KeyBuffer key;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700151 if (pathExists(key_path)) {
152 LOG(DEBUG) << "Key exists, using: " << key_path;
Paul Crowley26a53882017-10-26 11:16:39 -0700153 if (!retrieveKey(key_path, key_authentication, &key)) return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700154 } else {
155 if (!create_if_absent) {
Paul Crowley14c8c072018-09-18 13:30:21 -0700156 LOG(ERROR) << "No key found in " << key_path;
157 return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700158 }
159 LOG(INFO) << "Creating new key in " << key_path;
160 if (!randomKey(&key)) return false;
Paul Crowley26a53882017-10-26 11:16:39 -0700161 if (!storeKeyAtomically(key_path, tmp_path, key_authentication, key)) return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700162 }
163
164 if (!installKey(key, key_ref)) {
165 LOG(ERROR) << "Failed to install key in " << key_path;
166 return false;
167 }
168 return true;
169}
170
Paul Crowley14c8c072018-09-18 13:30:21 -0700171bool retrieveKey(bool create_if_absent, const std::string& key_path, const std::string& tmp_path,
172 KeyBuffer* key) {
Paul Crowleyd5759812016-06-02 11:04:27 -0700173 if (pathExists(key_path)) {
174 LOG(DEBUG) << "Key exists, using: " << key_path;
175 if (!retrieveKey(key_path, kEmptyAuthentication, key)) return false;
176 } else {
177 if (!create_if_absent) {
Paul Crowley14c8c072018-09-18 13:30:21 -0700178 LOG(ERROR) << "No key found in " << key_path;
179 return false;
Paul Crowleyd5759812016-06-02 11:04:27 -0700180 }
181 LOG(INFO) << "Creating new key in " << key_path;
182 if (!randomKey(key)) return false;
Paul Crowley14c8c072018-09-18 13:30:21 -0700183 if (!storeKeyAtomically(key_path, tmp_path, kEmptyAuthentication, *key)) return false;
Paul Crowleyd5759812016-06-02 11:04:27 -0700184 }
185 return true;
186}
187
Paul Crowleyf71ace32016-06-02 11:01:19 -0700188} // namespace vold
189} // namespace android