blob: 252edeb4729fed60bc5eaabb48d311ec7cdb22d0 [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
Paul Crowleyf71ace32016-06-02 11:01:19 -070023#include <openssl/sha.h>
24
25#include <android-base/file.h>
26#include <android-base/logging.h>
Elliott Hughesc3bda182017-05-09 17:01:04 -070027#include <keyutils.h>
Paul Crowleyf71ace32016-06-02 11:01:19 -070028
29#include "KeyStorage.h"
30#include "Utils.h"
31
32namespace android {
33namespace vold {
34
Eric Biggersa701c452018-10-23 13:06:55 -070035// fscrypt:TODO get these definitions from <linux/fs.h>
36constexpr int FS_KEY_DESCRIPTOR_SIZE = 8;
37constexpr int FS_ENCRYPTION_MODE_AES_256_XTS = 1;
38constexpr int FS_AES_256_XTS_KEY_SIZE = 64;
39constexpr int FS_MAX_KEY_SIZE = 64;
40struct fscrypt_key {
Pavel Grafove2e2d302017-08-01 17:15:53 +010041 uint32_t mode;
Eric Biggersa701c452018-10-23 13:06:55 -070042 char raw[FS_MAX_KEY_SIZE];
Pavel Grafove2e2d302017-08-01 17:15:53 +010043 uint32_t size;
44};
45
46bool randomKey(KeyBuffer* key) {
Eric Biggersa701c452018-10-23 13:06:55 -070047 *key = KeyBuffer(FS_AES_256_XTS_KEY_SIZE);
Pavel Grafove2e2d302017-08-01 17:15:53 +010048 if (ReadRandomBytes(key->size(), key->data()) != 0) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070049 // TODO status_t plays badly with PLOG, fix it.
50 LOG(ERROR) << "Random read failed";
51 return false;
52 }
53 return true;
54}
55
56// Get raw keyref - used to make keyname and to pass to ioctl
57static std::string generateKeyRef(const char* key, int length) {
58 SHA512_CTX c;
59
60 SHA512_Init(&c);
61 SHA512_Update(&c, key, length);
62 unsigned char key_ref1[SHA512_DIGEST_LENGTH];
63 SHA512_Final(key_ref1, &c);
64
65 SHA512_Init(&c);
66 SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
67 unsigned char key_ref2[SHA512_DIGEST_LENGTH];
68 SHA512_Final(key_ref2, &c);
69
Eric Biggersa701c452018-10-23 13:06:55 -070070 static_assert(FS_KEY_DESCRIPTOR_SIZE <= SHA512_DIGEST_LENGTH, "Hash too short for descriptor");
71 return std::string((char*)key_ref2, FS_KEY_DESCRIPTOR_SIZE);
Paul Crowleyf71ace32016-06-02 11:01:19 -070072}
73
Eric Biggersa701c452018-10-23 13:06:55 -070074static bool fillKey(const KeyBuffer& key, fscrypt_key* fs_key) {
75 if (key.size() != FS_AES_256_XTS_KEY_SIZE) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070076 LOG(ERROR) << "Wrong size key " << key.size();
77 return false;
78 }
Eric Biggersa701c452018-10-23 13:06:55 -070079 static_assert(FS_AES_256_XTS_KEY_SIZE <= sizeof(fs_key->raw), "Key too long!");
80 fs_key->mode = FS_ENCRYPTION_MODE_AES_256_XTS;
81 fs_key->size = key.size();
82 memset(fs_key->raw, 0, sizeof(fs_key->raw));
83 memcpy(fs_key->raw, key.data(), key.size());
Paul Crowleyf71ace32016-06-02 11:01:19 -070084 return true;
85}
86
Paul Crowley14c8c072018-09-18 13:30:21 -070087static char const* const NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt", nullptr};
Paul Crowleycd8bfe32017-06-19 16:05:55 -070088
89static std::string keyname(const std::string& prefix, const std::string& raw_ref) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070090 std::ostringstream o;
Paul Crowleycd8bfe32017-06-19 16:05:55 -070091 o << prefix << ":";
Chen, Luhai5744dfe2017-08-18 14:49:45 +080092 for (unsigned char i : raw_ref) {
Paul Crowleyf71ace32016-06-02 11:01:19 -070093 o << std::hex << std::setw(2) << std::setfill('0') << (int)i;
94 }
95 return o.str();
96}
97
98// Get the keyring we store all keys in
Eric Biggersa701c452018-10-23 13:06:55 -070099static bool fscryptKeyring(key_serial_t* device_keyring) {
100 *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
Paul Crowleyf71ace32016-06-02 11:01:19 -0700101 if (*device_keyring == -1) {
102 PLOG(ERROR) << "Unable to find device keyring";
103 return false;
104 }
105 return true;
106}
107
108// Install password into global keyring
109// Return raw key reference for use in policy
Pavel Grafove2e2d302017-08-01 17:15:53 +0100110bool installKey(const KeyBuffer& key, std::string* raw_ref) {
Eric Biggersa701c452018-10-23 13:06:55 -0700111 // Place fscrypt_key into automatically zeroing buffer.
112 KeyBuffer fsKeyBuffer(sizeof(fscrypt_key));
113 fscrypt_key& fs_key = *reinterpret_cast<fscrypt_key*>(fsKeyBuffer.data());
Pavel Grafove2e2d302017-08-01 17:15:53 +0100114
Eric Biggersa701c452018-10-23 13:06:55 -0700115 if (!fillKey(key, &fs_key)) return false;
116 *raw_ref = generateKeyRef(fs_key.raw, fs_key.size);
Paul Crowleyf71ace32016-06-02 11:01:19 -0700117 key_serial_t device_keyring;
Eric Biggersa701c452018-10-23 13:06:55 -0700118 if (!fscryptKeyring(&device_keyring)) return false;
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700119 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
120 auto ref = keyname(*name_prefix, *raw_ref);
121 key_serial_t key_id =
Eric Biggersa701c452018-10-23 13:06:55 -0700122 add_key("logon", ref.c_str(), (void*)&fs_key, sizeof(fs_key), device_keyring);
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700123 if (key_id == -1) {
124 PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
125 return false;
126 }
127 LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
128 << " in process " << getpid();
Paul Crowleyf71ace32016-06-02 11:01:19 -0700129 }
Paul Crowleyf71ace32016-06-02 11:01:19 -0700130 return true;
131}
132
133bool evictKey(const std::string& raw_ref) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700134 key_serial_t device_keyring;
Eric Biggersa701c452018-10-23 13:06:55 -0700135 if (!fscryptKeyring(&device_keyring)) return false;
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700136 bool success = true;
137 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
138 auto ref = keyname(*name_prefix, raw_ref);
139 auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
Paul Crowleyf71ace32016-06-02 11:01:19 -0700140
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700141 // Unlink the key from the keyring. Prefer unlinking to revoking or
142 // invalidating, since unlinking is actually no less secure currently, and
143 // it avoids bugs in certain kernel versions where the keyring key is
144 // referenced from places it shouldn't be.
145 if (keyctl_unlink(key_serial, device_keyring) != 0) {
146 PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
147 success = false;
148 } else {
149 LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref;
150 }
Paul Crowleyf71ace32016-06-02 11:01:19 -0700151 }
Paul Crowleycd8bfe32017-06-19 16:05:55 -0700152 return success;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700153}
154
Paul Crowley26a53882017-10-26 11:16:39 -0700155bool retrieveAndInstallKey(bool create_if_absent, const KeyAuthentication& key_authentication,
156 const std::string& key_path, const std::string& tmp_path,
157 std::string* key_ref) {
Pavel Grafove2e2d302017-08-01 17:15:53 +0100158 KeyBuffer key;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700159 if (pathExists(key_path)) {
160 LOG(DEBUG) << "Key exists, using: " << key_path;
Paul Crowley26a53882017-10-26 11:16:39 -0700161 if (!retrieveKey(key_path, key_authentication, &key)) return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700162 } else {
163 if (!create_if_absent) {
Paul Crowley14c8c072018-09-18 13:30:21 -0700164 LOG(ERROR) << "No key found in " << key_path;
165 return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700166 }
167 LOG(INFO) << "Creating new key in " << key_path;
168 if (!randomKey(&key)) return false;
Paul Crowley26a53882017-10-26 11:16:39 -0700169 if (!storeKeyAtomically(key_path, tmp_path, key_authentication, key)) return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700170 }
171
172 if (!installKey(key, key_ref)) {
173 LOG(ERROR) << "Failed to install key in " << key_path;
174 return false;
175 }
176 return true;
177}
178
Paul Crowley14c8c072018-09-18 13:30:21 -0700179bool retrieveKey(bool create_if_absent, const std::string& key_path, const std::string& tmp_path,
180 KeyBuffer* key) {
Paul Crowleyd5759812016-06-02 11:04:27 -0700181 if (pathExists(key_path)) {
182 LOG(DEBUG) << "Key exists, using: " << key_path;
183 if (!retrieveKey(key_path, kEmptyAuthentication, key)) return false;
184 } else {
185 if (!create_if_absent) {
Paul Crowley14c8c072018-09-18 13:30:21 -0700186 LOG(ERROR) << "No key found in " << key_path;
187 return false;
Paul Crowleyd5759812016-06-02 11:04:27 -0700188 }
189 LOG(INFO) << "Creating new key in " << key_path;
190 if (!randomKey(key)) return false;
Paul Crowley14c8c072018-09-18 13:30:21 -0700191 if (!storeKeyAtomically(key_path, tmp_path, kEmptyAuthentication, *key)) return false;
Paul Crowleyd5759812016-06-02 11:04:27 -0700192 }
193 return true;
194}
195
Paul Crowleyf71ace32016-06-02 11:01:19 -0700196} // namespace vold
197} // namespace android