blob: 6200c426492c53af893416a7dde936c71bf66319 [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
19#include <iomanip>
20#include <sstream>
21#include <string>
22
Eric Biggersf3dc4202019-09-30 13:05:58 -070023#include <fcntl.h>
Eric Biggers3e9c9962019-12-16 15:55:12 -080024#include <linux/fscrypt.h>
Paul Crowleyf71ace32016-06-02 11:01:19 -070025#include <openssl/sha.h>
Eric Biggersf3dc4202019-09-30 13:05:58 -070026#include <sys/ioctl.h>
Paul Crowleyf71ace32016-06-02 11:01:19 -070027
28#include <android-base/file.h>
29#include <android-base/logging.h>
Elliott Hughesc3bda182017-05-09 17:01:04 -070030#include <keyutils.h>
Paul Crowleyf71ace32016-06-02 11:01:19 -070031
Barani Muthukumaran3dfb0942020-02-03 13:06:45 -080032#include <fscrypt_uapi.h>
Paul Crowleyf71ace32016-06-02 11:01:19 -070033#include "KeyStorage.h"
34#include "Utils.h"
35
36namespace android {
37namespace vold {
38
Paul Crowley4eac2642020-02-12 11:04:05 -080039const KeyGeneration neverGen() {
40 return KeyGeneration{0, false, false};
41}
42
43static bool randomKey(size_t size, KeyBuffer* key) {
44 *key = KeyBuffer(size);
Pavel Grafove2e2d302017-08-01 17:15:53 +010045 if (ReadRandomBytes(key->size(), key->data()) != 0) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070046 // TODO status_t plays badly with PLOG, fix it.
47 LOG(ERROR) << "Random read failed";
48 return false;
49 }
50 return true;
51}
52
Paul Crowley4eac2642020-02-12 11:04:05 -080053bool generateStorageKey(const KeyGeneration& gen, KeyBuffer* key) {
54 if (!gen.allow_gen) return false;
55 if (gen.use_hw_wrapped_key) {
56 if (gen.keysize != FSCRYPT_MAX_KEY_SIZE) {
57 LOG(ERROR) << "Cannot generate a wrapped key " << gen.keysize << " bytes long";
58 return false;
59 }
Barani Muthukumaran3dfb0942020-02-03 13:06:45 -080060 return generateWrappedStorageKey(key);
Paul Crowley4eac2642020-02-12 11:04:05 -080061 } else {
62 return randomKey(gen.keysize, key);
Barani Muthukumaran3dfb0942020-02-03 13:06:45 -080063 }
Barani Muthukumaran3dfb0942020-02-03 13:06:45 -080064}
65
Eric Biggersf3dc4202019-09-30 13:05:58 -070066// Return true if the kernel supports the ioctls to add/remove fscrypt keys
67// directly to/from the filesystem.
68bool isFsKeyringSupported(void) {
69 static bool initialized = false;
70 static bool supported;
71
72 if (!initialized) {
73 android::base::unique_fd fd(open("/data", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
74
75 // FS_IOC_ADD_ENCRYPTION_KEY with a NULL argument will fail with ENOTTY
76 // if the ioctl isn't supported. Otherwise it will fail with another
77 // error code such as EFAULT.
78 errno = 0;
79 (void)ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, NULL);
80 if (errno == ENOTTY) {
81 LOG(INFO) << "Kernel doesn't support FS_IOC_ADD_ENCRYPTION_KEY. Falling back to "
82 "session keyring";
83 supported = false;
84 } else {
85 if (errno != EFAULT) {
86 PLOG(WARNING) << "Unexpected error from FS_IOC_ADD_ENCRYPTION_KEY";
87 }
88 LOG(DEBUG) << "Detected support for FS_IOC_ADD_ENCRYPTION_KEY";
89 supported = true;
90 }
91 // There's no need to check for FS_IOC_REMOVE_ENCRYPTION_KEY, since it's
92 // guaranteed to be available if FS_IOC_ADD_ENCRYPTION_KEY is. There's
93 // also no need to check for support on external volumes separately from
94 // /data, since either the kernel supports the ioctls on all
95 // fscrypt-capable filesystems or it doesn't.
96
97 initialized = true;
98 }
99 return supported;
100}
101
Paul Crowleyf71ace32016-06-02 11:01:19 -0700102// Get raw keyref - used to make keyname and to pass to ioctl
Eric Biggersba997ee2018-10-23 13:07:43 -0700103static std::string generateKeyRef(const uint8_t* key, int length) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700104 SHA512_CTX c;
105
106 SHA512_Init(&c);
107 SHA512_Update(&c, key, length);
108 unsigned char key_ref1[SHA512_DIGEST_LENGTH];
109 SHA512_Final(key_ref1, &c);
110
111 SHA512_Init(&c);
112 SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
113 unsigned char key_ref2[SHA512_DIGEST_LENGTH];
114 SHA512_Final(key_ref2, &c);
115
Eric Biggers506342f2019-12-17 13:11:25 -0800116 static_assert(FSCRYPT_KEY_DESCRIPTOR_SIZE <= SHA512_DIGEST_LENGTH,
117 "Hash too short for descriptor");
118 return std::string((char*)key_ref2, FSCRYPT_KEY_DESCRIPTOR_SIZE);
Paul Crowleyf71ace32016-06-02 11:01:19 -0700119}
120
Eric Biggersa701c452018-10-23 13:06:55 -0700121static bool fillKey(const KeyBuffer& key, fscrypt_key* fs_key) {
Eric Biggers506342f2019-12-17 13:11:25 -0800122 if (key.size() != FSCRYPT_MAX_KEY_SIZE) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700123 LOG(ERROR) << "Wrong size key " << key.size();
124 return false;
125 }
Eric Biggers506342f2019-12-17 13:11:25 -0800126 static_assert(FSCRYPT_MAX_KEY_SIZE == sizeof(fs_key->raw), "Mismatch of max key sizes");
127 fs_key->mode = 0; // unused by kernel
Eric Biggersa701c452018-10-23 13:06:55 -0700128 memcpy(fs_key->raw, key.data(), key.size());
Eric Biggers506342f2019-12-17 13:11:25 -0800129 fs_key->size = key.size();
Paul Crowleyf71ace32016-06-02 11:01:19 -0700130 return true;
131}
132
Paul Crowley14c8c072018-09-18 13:30:21 -0700133static char const* const NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt", nullptr};
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700134
Eric Biggersf3dc4202019-09-30 13:05:58 -0700135static std::string keyrefstring(const std::string& raw_ref) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700136 std::ostringstream o;
Chen, Luhai5744dfe2017-08-18 14:49:45 +0800137 for (unsigned char i : raw_ref) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700138 o << std::hex << std::setw(2) << std::setfill('0') << (int)i;
139 }
140 return o.str();
141}
142
Eric Biggersf3dc4202019-09-30 13:05:58 -0700143static std::string buildLegacyKeyName(const std::string& prefix, const std::string& raw_ref) {
144 return prefix + ":" + keyrefstring(raw_ref);
145}
146
147// Get the ID of the keyring we store all fscrypt keys in when the kernel is too
148// old to support FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY.
Eric Biggersa701c452018-10-23 13:06:55 -0700149static bool fscryptKeyring(key_serial_t* device_keyring) {
150 *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
Paul Crowleyf71ace32016-06-02 11:01:19 -0700151 if (*device_keyring == -1) {
152 PLOG(ERROR) << "Unable to find device keyring";
153 return false;
154 }
155 return true;
156}
157
Eric Biggersf3dc4202019-09-30 13:05:58 -0700158// Add an encryption key to the legacy global session keyring.
159static bool installKeyLegacy(const KeyBuffer& key, const std::string& raw_ref) {
Eric Biggersa701c452018-10-23 13:06:55 -0700160 // Place fscrypt_key into automatically zeroing buffer.
161 KeyBuffer fsKeyBuffer(sizeof(fscrypt_key));
162 fscrypt_key& fs_key = *reinterpret_cast<fscrypt_key*>(fsKeyBuffer.data());
Pavel Grafove2e2d302017-08-01 17:15:53 +0100163
Eric Biggersa701c452018-10-23 13:06:55 -0700164 if (!fillKey(key, &fs_key)) return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700165 key_serial_t device_keyring;
Eric Biggersa701c452018-10-23 13:06:55 -0700166 if (!fscryptKeyring(&device_keyring)) return false;
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700167 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
Eric Biggersf3dc4202019-09-30 13:05:58 -0700168 auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700169 key_serial_t key_id =
Eric Biggersa701c452018-10-23 13:06:55 -0700170 add_key("logon", ref.c_str(), (void*)&fs_key, sizeof(fs_key), device_keyring);
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700171 if (key_id == -1) {
172 PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
173 return false;
174 }
175 LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
176 << " in process " << getpid();
Paul Crowleyf71ace32016-06-02 11:01:19 -0700177 }
Paul Crowleyf71ace32016-06-02 11:01:19 -0700178 return true;
179}
180
Eric Biggers83a73d72019-09-30 13:06:47 -0700181// Build a struct fscrypt_key_specifier for use in the key management ioctls.
Paul Crowley77df7f22020-01-23 15:29:30 -0800182static bool buildKeySpecifier(fscrypt_key_specifier* spec, const EncryptionPolicy& policy) {
183 switch (policy.options.version) {
Eric Biggers83a73d72019-09-30 13:06:47 -0700184 case 1:
Paul Crowley77df7f22020-01-23 15:29:30 -0800185 if (policy.key_raw_ref.size() != FSCRYPT_KEY_DESCRIPTOR_SIZE) {
Eric Biggers83a73d72019-09-30 13:06:47 -0700186 LOG(ERROR) << "Invalid key specifier size for v1 encryption policy: "
Paul Crowley77df7f22020-01-23 15:29:30 -0800187 << policy.key_raw_ref.size();
Eric Biggers83a73d72019-09-30 13:06:47 -0700188 return false;
189 }
190 spec->type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
Paul Crowley77df7f22020-01-23 15:29:30 -0800191 memcpy(spec->u.descriptor, policy.key_raw_ref.c_str(), FSCRYPT_KEY_DESCRIPTOR_SIZE);
Eric Biggers83a73d72019-09-30 13:06:47 -0700192 return true;
193 case 2:
Paul Crowley77df7f22020-01-23 15:29:30 -0800194 if (policy.key_raw_ref.size() != FSCRYPT_KEY_IDENTIFIER_SIZE) {
Eric Biggers83a73d72019-09-30 13:06:47 -0700195 LOG(ERROR) << "Invalid key specifier size for v2 encryption policy: "
Paul Crowley77df7f22020-01-23 15:29:30 -0800196 << policy.key_raw_ref.size();
Eric Biggers83a73d72019-09-30 13:06:47 -0700197 return false;
198 }
199 spec->type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
Paul Crowley77df7f22020-01-23 15:29:30 -0800200 memcpy(spec->u.identifier, policy.key_raw_ref.c_str(), FSCRYPT_KEY_IDENTIFIER_SIZE);
Eric Biggers83a73d72019-09-30 13:06:47 -0700201 return true;
202 default:
Paul Crowley77df7f22020-01-23 15:29:30 -0800203 LOG(ERROR) << "Invalid encryption policy version: " << policy.options.version;
Eric Biggers83a73d72019-09-30 13:06:47 -0700204 return false;
205 }
206}
207
Paul Crowley77df7f22020-01-23 15:29:30 -0800208bool installKey(const std::string& mountpoint, const EncryptionOptions& options,
209 const KeyBuffer& key, EncryptionPolicy* policy) {
210 policy->options = options;
Eric Biggersf3dc4202019-09-30 13:05:58 -0700211 // Put the fscrypt_add_key_arg in an automatically-zeroing buffer, since we
212 // have to copy the raw key into it.
213 KeyBuffer arg_buf(sizeof(struct fscrypt_add_key_arg) + key.size(), 0);
214 struct fscrypt_add_key_arg* arg = (struct fscrypt_add_key_arg*)arg_buf.data();
215
Eric Biggers83a73d72019-09-30 13:06:47 -0700216 // Initialize the "key specifier", which is like a name for the key.
Paul Crowley77df7f22020-01-23 15:29:30 -0800217 switch (options.version) {
Eric Biggers83a73d72019-09-30 13:06:47 -0700218 case 1:
219 // A key for a v1 policy is specified by an arbitrary 8-byte
220 // "descriptor", which must be provided by userspace. We use the
221 // first 8 bytes from the double SHA-512 of the key itself.
Paul Crowley77df7f22020-01-23 15:29:30 -0800222 policy->key_raw_ref = generateKeyRef((const uint8_t*)key.data(), key.size());
Eric Biggers83a73d72019-09-30 13:06:47 -0700223 if (!isFsKeyringSupported()) {
Paul Crowley77df7f22020-01-23 15:29:30 -0800224 return installKeyLegacy(key, policy->key_raw_ref);
Eric Biggers83a73d72019-09-30 13:06:47 -0700225 }
Paul Crowley77df7f22020-01-23 15:29:30 -0800226 if (!buildKeySpecifier(&arg->key_spec, *policy)) {
Eric Biggers83a73d72019-09-30 13:06:47 -0700227 return false;
228 }
229 break;
230 case 2:
231 // A key for a v2 policy is specified by an 16-byte "identifier",
232 // which is a cryptographic hash of the key itself which the kernel
233 // computes and returns. Any user-provided value is ignored; we
234 // just need to set the specifier type to indicate that we're adding
235 // this type of key.
236 arg->key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
237 break;
238 default:
Paul Crowley77df7f22020-01-23 15:29:30 -0800239 LOG(ERROR) << "Invalid encryption policy version: " << options.version;
Eric Biggers83a73d72019-09-30 13:06:47 -0700240 return false;
241 }
Eric Biggersf3dc4202019-09-30 13:05:58 -0700242
Barani Muthukumaran3dfb0942020-02-03 13:06:45 -0800243 if (options.use_hw_wrapped_key) arg->flags |= FSCRYPT_ADD_KEY_FLAG_WRAPPED;
Eric Biggers83a73d72019-09-30 13:06:47 -0700244 // Provide the raw key.
Eric Biggersf3dc4202019-09-30 13:05:58 -0700245 arg->raw_size = key.size();
246 memcpy(arg->raw, key.data(), key.size());
247
248 android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
249 if (fd == -1) {
250 PLOG(ERROR) << "Failed to open " << mountpoint << " to install key";
251 return false;
252 }
253
254 if (ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, arg) != 0) {
Eric Biggers83a73d72019-09-30 13:06:47 -0700255 PLOG(ERROR) << "Failed to install fscrypt key to " << mountpoint;
Eric Biggersf3dc4202019-09-30 13:05:58 -0700256 return false;
257 }
258
Eric Biggers83a73d72019-09-30 13:06:47 -0700259 if (arg->key_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
260 // Retrieve the key identifier that the kernel computed.
Paul Crowley77df7f22020-01-23 15:29:30 -0800261 policy->key_raw_ref =
262 std::string((char*)arg->key_spec.u.identifier, FSCRYPT_KEY_IDENTIFIER_SIZE);
Eric Biggers83a73d72019-09-30 13:06:47 -0700263 }
Paul Crowley77df7f22020-01-23 15:29:30 -0800264 LOG(DEBUG) << "Installed fscrypt key with ref " << keyrefstring(policy->key_raw_ref) << " to "
Eric Biggersf3dc4202019-09-30 13:05:58 -0700265 << mountpoint;
266 return true;
267}
268
269// Remove an encryption key from the legacy global session keyring.
270static bool evictKeyLegacy(const std::string& raw_ref) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700271 key_serial_t device_keyring;
Eric Biggersa701c452018-10-23 13:06:55 -0700272 if (!fscryptKeyring(&device_keyring)) return false;
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700273 bool success = true;
274 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
Eric Biggersf3dc4202019-09-30 13:05:58 -0700275 auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700276 auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
Paul Crowleyf71ace32016-06-02 11:01:19 -0700277
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700278 // Unlink the key from the keyring. Prefer unlinking to revoking or
279 // invalidating, since unlinking is actually no less secure currently, and
280 // it avoids bugs in certain kernel versions where the keyring key is
281 // referenced from places it shouldn't be.
282 if (keyctl_unlink(key_serial, device_keyring) != 0) {
283 PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
284 success = false;
285 } else {
286 LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref;
287 }
Paul Crowleyf71ace32016-06-02 11:01:19 -0700288 }
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700289 return success;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700290}
291
Paul Crowley77df7f22020-01-23 15:29:30 -0800292bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy) {
293 if (policy.options.version == 1 && !isFsKeyringSupported()) {
294 return evictKeyLegacy(policy.key_raw_ref);
Eric Biggersf3dc4202019-09-30 13:05:58 -0700295 }
296
297 android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
298 if (fd == -1) {
299 PLOG(ERROR) << "Failed to open " << mountpoint << " to evict key";
300 return false;
301 }
302
303 struct fscrypt_remove_key_arg arg;
304 memset(&arg, 0, sizeof(arg));
305
Paul Crowley77df7f22020-01-23 15:29:30 -0800306 if (!buildKeySpecifier(&arg.key_spec, policy)) {
Eric Biggers83a73d72019-09-30 13:06:47 -0700307 return false;
308 }
Eric Biggersf3dc4202019-09-30 13:05:58 -0700309
Paul Crowley77df7f22020-01-23 15:29:30 -0800310 std::string ref = keyrefstring(policy.key_raw_ref);
Eric Biggersf3dc4202019-09-30 13:05:58 -0700311
312 if (ioctl(fd, FS_IOC_REMOVE_ENCRYPTION_KEY, &arg) != 0) {
313 PLOG(ERROR) << "Failed to evict fscrypt key with ref " << ref << " from " << mountpoint;
314 return false;
315 }
316
317 LOG(DEBUG) << "Evicted fscrypt key with ref " << ref << " from " << mountpoint;
318 if (arg.removal_status_flags & FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS) {
319 // Should never happen because keys are only added/removed as root.
320 LOG(ERROR) << "Unexpected case: key with ref " << ref << " is still added by other users!";
321 } else if (arg.removal_status_flags & FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY) {
322 LOG(ERROR) << "Files still open after removing key with ref " << ref
323 << ". These files were not locked!";
324 }
325 return true;
326}
327
Paul Crowley4eac2642020-02-12 11:04:05 -0800328bool retrieveOrGenerateKey(const std::string& key_path, const std::string& tmp_path,
329 const KeyAuthentication& key_authentication, const KeyGeneration& gen,
330 KeyBuffer* key, bool keepOld) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700331 if (pathExists(key_path)) {
332 LOG(DEBUG) << "Key exists, using: " << key_path;
Paul Crowley77df7f22020-01-23 15:29:30 -0800333 if (!retrieveKey(key_path, key_authentication, key, keepOld)) return false;
Paul Crowleyd5759812016-06-02 11:04:27 -0700334 } else {
Paul Crowley4eac2642020-02-12 11:04:05 -0800335 if (!gen.allow_gen) {
Paul Crowley14c8c072018-09-18 13:30:21 -0700336 LOG(ERROR) << "No key found in " << key_path;
337 return false;
Paul Crowleyd5759812016-06-02 11:04:27 -0700338 }
339 LOG(INFO) << "Creating new key in " << key_path;
Paul Crowley4eac2642020-02-12 11:04:05 -0800340 if (!generateStorageKey(gen, key)) return false;
Paul Crowley77df7f22020-01-23 15:29:30 -0800341 if (!storeKeyAtomically(key_path, tmp_path, key_authentication, *key)) return false;
Paul Crowleyd5759812016-06-02 11:04:27 -0700342 }
343 return true;
344}
345
Paul Crowleyf71ace32016-06-02 11:01:19 -0700346} // namespace vold
347} // namespace android