blob: 3dc05004c6d4aace7fcf3718cc60e2899ba3fab8 [file] [log] [blame]
Ethan Yonkere9afc3d2018-08-30 15:16:27 -05001/*
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
23#include <openssl/sha.h>
24
25#include <android-base/file.h>
26//#include <android-base/logging.h>
27#include <keyutils.h>
28
29#include "KeyStorage4.h"
Peter Cai90edd2e2019-05-23 16:32:22 +080030#include "Ext4CryptPie.h"
Ethan Yonkere9afc3d2018-08-30 15:16:27 -050031#include "Utils.h"
32
33#include <iostream>
34#define LOG(x) std::cout
35#define PLOG(x) std::cout
36#include <sys/types.h>
37#include <unistd.h>
38
Peter Cai90edd2e2019-05-23 16:32:22 +080039#define MAX_USER_ID 0xFFFFFFFF
40
41using android::hardware::keymaster::V4_0::KeyFormat;
42using android::vold::KeyType;
43
Ethan Yonkere9afc3d2018-08-30 15:16:27 -050044namespace android {
45namespace vold {
46
47// ext4enc:TODO get this const from somewhere good
48const int EXT4_KEY_DESCRIPTOR_SIZE = 8;
49
50// ext4enc:TODO Include structure from somewhere sensible
51// MUST be in sync with ext4_crypto.c in kernel
52constexpr int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1;
53constexpr int EXT4_AES_256_XTS_KEY_SIZE = 64;
54constexpr int EXT4_MAX_KEY_SIZE = 64;
55struct ext4_encryption_key {
56 uint32_t mode;
57 char raw[EXT4_MAX_KEY_SIZE];
58 uint32_t size;
59};
60
61bool randomKey(KeyBuffer* key) {
62 *key = KeyBuffer(EXT4_AES_256_XTS_KEY_SIZE);
63 if (ReadRandomBytes(key->size(), key->data()) != 0) {
64 // TODO status_t plays badly with PLOG, fix it.
65 LOG(ERROR) << "Random read failed" << std::endl;
66 return false;
67 }
68 return true;
69}
70
71// Get raw keyref - used to make keyname and to pass to ioctl
72static std::string generateKeyRef(const char* key, int length) {
73 SHA512_CTX c;
74
75 SHA512_Init(&c);
76 SHA512_Update(&c, key, length);
77 unsigned char key_ref1[SHA512_DIGEST_LENGTH];
78 SHA512_Final(key_ref1, &c);
79
80 SHA512_Init(&c);
81 SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
82 unsigned char key_ref2[SHA512_DIGEST_LENGTH];
83 SHA512_Final(key_ref2, &c);
84
85 static_assert(EXT4_KEY_DESCRIPTOR_SIZE <= SHA512_DIGEST_LENGTH,
86 "Hash too short for descriptor");
87 return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE);
88}
89
90static bool fillKey(const KeyBuffer& key, ext4_encryption_key* ext4_key) {
91 if (key.size() != EXT4_AES_256_XTS_KEY_SIZE) {
92 LOG(ERROR) << "Wrong size key " << key.size();
93 return false;
94 }
95 static_assert(EXT4_AES_256_XTS_KEY_SIZE <= sizeof(ext4_key->raw), "Key too long!");
96 ext4_key->mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
97 ext4_key->size = key.size();
98 memset(ext4_key->raw, 0, sizeof(ext4_key->raw));
99 memcpy(ext4_key->raw, key.data(), key.size());
100 return true;
101}
102
103static char const* const NAME_PREFIXES[] = {
104 "ext4",
105 "f2fs",
106 "fscrypt",
107 nullptr
108};
109
110static std::string keyname(const std::string& prefix, const std::string& raw_ref) {
111 std::ostringstream o;
112 o << prefix << ":";
113 for (unsigned char i : raw_ref) {
114 o << std::hex << std::setw(2) << std::setfill('0') << (int)i;
115 }
116 return o.str();
117}
118
119// Get the keyring we store all keys in
120static bool e4cryptKeyring(key_serial_t* device_keyring) {
121 *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "e4crypt", 0);
122 if (*device_keyring == -1) {
123 PLOG(ERROR) << "Unable to find device keyring" << std::endl;
124 return false;
125 }
126 return true;
127}
128
129// Install password into global keyring
130// Return raw key reference for use in policy
131bool installKey(const KeyBuffer& key, std::string* raw_ref) {
132 // Place ext4_encryption_key into automatically zeroing buffer.
133 KeyBuffer ext4KeyBuffer(sizeof(ext4_encryption_key));
134 ext4_encryption_key &ext4_key = *reinterpret_cast<ext4_encryption_key*>(ext4KeyBuffer.data());
135
136 if (!fillKey(key, &ext4_key)) return false;
Peter Cai90edd2e2019-05-23 16:32:22 +0800137 if (is_wrapped_key_supported()) {
138 /* When wrapped key is supported, only the first 32 bytes are
139 the same per boot. The second 32 bytes can change as the ephemeral
140 key is different. */
141 *raw_ref = generateKeyRef(ext4_key.raw, (ext4_key.size)/2);
142 } else {
143 *raw_ref = generateKeyRef(ext4_key.raw, ext4_key.size);
144 }
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500145 key_serial_t device_keyring;
146 if (!e4cryptKeyring(&device_keyring)) return false;
147 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
148 auto ref = keyname(*name_prefix, *raw_ref);
149 key_serial_t key_id =
150 add_key("logon", ref.c_str(), (void*)&ext4_key, sizeof(ext4_key), device_keyring);
151 if (key_id == -1) {
152 PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring << std::endl;
153 return false;
154 }
155 LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
156 << " in process " << getpid() << std::endl;
157 }
158 return true;
159}
160
161bool evictKey(const std::string& raw_ref) {
162 LOG(ERROR) << "not actually evicting key\n";
163 return true;
164 key_serial_t device_keyring;
165 if (!e4cryptKeyring(&device_keyring)) return false;
166 bool success = true;
167 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
168 auto ref = keyname(*name_prefix, raw_ref);
169 auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
170
171 // Unlink the key from the keyring. Prefer unlinking to revoking or
172 // invalidating, since unlinking is actually no less secure currently, and
173 // it avoids bugs in certain kernel versions where the keyring key is
174 // referenced from places it shouldn't be.
175 if (keyctl_unlink(key_serial, device_keyring) != 0) {
176 PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
177 success = false;
178 } else {
179 LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref;
180 }
181 }
182 return success;
183}
184
185bool retrieveAndInstallKey(bool create_if_absent, const KeyAuthentication& key_authentication,
186 const std::string& key_path, const std::string& tmp_path,
Peter Cai90edd2e2019-05-23 16:32:22 +0800187 std::string* key_ref, bool wrapped_key_supported) {
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500188 KeyBuffer key;
189 if (pathExists(key_path)) {
190 LOG(DEBUG) << "Key exists, using: " << key_path << std::endl;
191 if (!retrieveKey(key_path, key_authentication, &key)) return false;
192 } else {
193 if (!create_if_absent) {
194 LOG(ERROR) << "No key found in " << key_path << std::endl;
195 return false;
196 }
197 LOG(INFO) << "Creating new key in " << key_path << std::endl;
Peter Cai90edd2e2019-05-23 16:32:22 +0800198 if (wrapped_key_supported) {
199 if(!generateWrappedKey(MAX_USER_ID, KeyType::DE_SYS, &key)) return false;
200 } else {
201 if (!randomKey(&key)) return false;
202 }
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500203 if (!storeKeyAtomically(key_path, tmp_path, key_authentication, key)) return false;
204 }
205
Peter Cai90edd2e2019-05-23 16:32:22 +0800206 if (wrapped_key_supported) {
207 KeyBuffer ephemeral_wrapped_key;
208 if (!getEphemeralWrappedKey(KeyFormat::RAW, key, &ephemeral_wrapped_key)) {
209 LOG(ERROR) << "Failed to export key in retrieveAndInstallKey";
210 return false;
211 }
212 key = std::move(ephemeral_wrapped_key);
213 }
214
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500215 if (!installKey(key, key_ref)) {
216 LOG(ERROR) << "Failed to install key in " << key_path << std::endl;
217 return false;
218 }
219 return true;
220}
221
222bool retrieveKey(bool create_if_absent, const std::string& key_path,
223 const std::string& tmp_path, KeyBuffer* key) {
224 if (pathExists(key_path)) {
225 LOG(DEBUG) << "Key exists, using: " << key_path << std::endl;
226 if (!retrieveKey(key_path, kEmptyAuthentication, key)) return false;
227 } else {
228 if (!create_if_absent) {
229 LOG(ERROR) << "No key found in " << key_path << std::endl;
230 return false;
231 }
232 LOG(INFO) << "Creating new key in " << key_path << std::endl;
233 if (!randomKey(key)) return false;
234 if (!storeKeyAtomically(key_path, tmp_path,
235 kEmptyAuthentication, *key)) return false;
236 }
237 return true;
238}
239
240} // namespace vold
241} // namespace android