blob: d4d49aff04d412fcfe89ac79f75ed9402c3ca851 [file] [log] [blame]
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -08001/*
2 * Copyright (C) 2015 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
Paul Lawrence731a7a22015-04-28 22:14:15 +000017#include "Ext4Crypt.h"
18
Paul Crowley1ef25582016-01-21 20:26:12 +000019#include "KeyStorage.h"
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080020#include "Utils.h"
21
Paul Lawrencefd7db732015-04-10 07:48:51 -070022#include <iomanip>
Paul Lawrence731a7a22015-04-28 22:14:15 +000023#include <map>
Paul Crowleyb1f3d242016-01-28 10:09:46 +000024#include <set>
Paul Lawrencefd7db732015-04-10 07:48:51 -070025#include <string>
26#include <sstream>
Paul Lawrence731a7a22015-04-28 22:14:15 +000027
Paul Crowleyb1f3d242016-01-28 10:09:46 +000028#include <stdio.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000029#include <errno.h>
Paul Crowley95376d62015-05-06 15:04:43 +010030#include <dirent.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000031#include <sys/mount.h>
Paul Crowley95376d62015-05-06 15:04:43 +010032#include <sys/types.h>
33#include <sys/stat.h>
34#include <fcntl.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000035#include <cutils/properties.h>
Paul Lawrencefd7db732015-04-10 07:48:51 -070036#include <openssl/sha.h>
Jeff Sharkey7a9dd952016-01-12 16:52:16 -070037#include <selinux/android.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000038
Paul Crowley480fcd22015-08-24 14:53:28 +010039#include <private/android_filesystem_config.h>
40
Paul Lawrence731a7a22015-04-28 22:14:15 +000041#include "key_control.h"
42#include "cryptfs.h"
Jeff Sharkey47695b22016-02-01 17:02:29 -070043#include "ext4_crypt.h"
Paul Lawrence731a7a22015-04-28 22:14:15 +000044
45#define LOG_TAG "Ext4Crypt"
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080046
Jeff Sharkey7a9dd952016-01-12 16:52:16 -070047#define EMULATED_USES_SELINUX 0
48
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080049#include <cutils/fs.h>
50#include <cutils/log.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000051#include <cutils/klog.h>
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080052
Elliott Hughes7e128fb2015-12-04 15:50:53 -080053#include <android-base/file.h>
Elliott Hughes6bf05472015-12-04 17:55:33 -080054#include <android-base/logging.h>
Elliott Hughes7e128fb2015-12-04 15:50:53 -080055#include <android-base/stringprintf.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000056
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080057using android::base::StringPrintf;
Paul Crowley05720802016-02-08 15:55:41 +000058using android::vold::kEmptyAuthentication;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080059
Jeff Sharkey47695b22016-02-01 17:02:29 -070060// NOTE: keep in sync with StorageManager
61static constexpr int FLAG_STORAGE_DE = 1 << 0;
62static constexpr int FLAG_STORAGE_CE = 1 << 1;
63
Jeff Sharkeyfc505c32015-12-07 17:27:01 -070064static bool e4crypt_is_native() {
65 char value[PROPERTY_VALUE_MAX];
66 property_get("ro.crypto.type", value, "none");
67 return !strcmp(value, "file");
68}
69
70static bool e4crypt_is_emulated() {
71 return property_get_bool("persist.sys.emulate_fbe", false);
72}
Jeff Sharkeyc79fb892015-11-12 20:18:02 -080073
Jeff Sharkey47695b22016-02-01 17:02:29 -070074static const char* escape_null(const char* value) {
75 return (value == nullptr) ? "null" : value;
76}
77
Paul Lawrence731a7a22015-04-28 22:14:15 +000078namespace {
79 // Key length in bits
80 const int key_length = 128;
Paul Lawrencefd7db732015-04-10 07:48:51 -070081 static_assert(key_length % 8 == 0,
82 "Key length must be multiple of 8 bits");
Paul Lawrence731a7a22015-04-28 22:14:15 +000083
Paul Lawrence5a06a642016-02-03 13:39:13 -080084 const std::string device_key_leaf = "/unencrypted/key";
85 const std::string device_key_temp = "/unencrypted/temp";
86
Paul Crowley285956f2016-01-20 13:12:38 +000087 const std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys";
Paul Crowleyb1f3d242016-01-28 10:09:46 +000088 const std::string user_key_temp = user_key_dir + "/temp";
Paul Crowley285956f2016-01-20 13:12:38 +000089
Paul Lawrence7b6b5652016-02-02 11:14:59 -080090 bool s_enabled = false;
91
Paul Crowleyb1f3d242016-01-28 10:09:46 +000092 // Some users are ephemeral, don't try to wipe their keys from disk
93 std::set<userid_t> s_ephemeral_users;
Paul Lawrenceaec34df2016-02-03 10:52:41 -080094
Paul Crowleyb1f3d242016-01-28 10:09:46 +000095 // Map user ids to key references
Paul Crowleyb92f83c2016-02-01 14:10:43 +000096 std::map<userid_t, std::string> s_de_key_raw_refs;
Paul Crowleyb1f3d242016-01-28 10:09:46 +000097 std::map<userid_t, std::string> s_ce_key_raw_refs;
Paul Crowley05720802016-02-08 15:55:41 +000098 // TODO abolish this map. Keys should not be long-lived in user memory, only kernel memory.
99 // See b/26948053
100 std::map<userid_t, std::string> s_ce_keys;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000101
Paul Crowley285956f2016-01-20 13:12:38 +0000102 // ext4enc:TODO get this const from somewhere good
Paul Lawrencefd7db732015-04-10 07:48:51 -0700103 const int EXT4_KEY_DESCRIPTOR_SIZE = 8;
104
Paul Lawrence731a7a22015-04-28 22:14:15 +0000105 // ext4enc:TODO Include structure from somewhere sensible
106 // MUST be in sync with ext4_crypto.c in kernel
Paul Lawrencefd7db732015-04-10 07:48:51 -0700107 const int EXT4_MAX_KEY_SIZE = 64;
108 const int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000109 struct ext4_encryption_key {
Paul Lawrencefd7db732015-04-10 07:48:51 -0700110 uint32_t mode;
111 char raw[EXT4_MAX_KEY_SIZE];
112 uint32_t size;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000113 };
Paul Lawrence731a7a22015-04-28 22:14:15 +0000114}
115
Paul Lawrencef10544d2016-02-04 08:18:52 -0800116// TODO replace with proper function to test for file encryption
Paul Lawrence731a7a22015-04-28 22:14:15 +0000117int e4crypt_crypto_complete(const char* path)
118{
Paul Lawrencef10544d2016-02-04 08:18:52 -0800119 return e4crypt_is_native() ? 0 : -1;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000120}
121
Paul Crowley93363482015-07-07 15:17:22 +0100122// Get raw keyref - used to make keyname and to pass to ioctl
Paul Lawrencefd7db732015-04-10 07:48:51 -0700123static std::string generate_key_ref(const char* key, int length)
124{
125 SHA512_CTX c;
126
127 SHA512_Init(&c);
128 SHA512_Update(&c, key, length);
Paul Crowley285956f2016-01-20 13:12:38 +0000129 unsigned char key_ref1[SHA512_DIGEST_LENGTH];
Paul Lawrencefd7db732015-04-10 07:48:51 -0700130 SHA512_Final(key_ref1, &c);
131
132 SHA512_Init(&c);
Paul Crowley285956f2016-01-20 13:12:38 +0000133 SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
134 unsigned char key_ref2[SHA512_DIGEST_LENGTH];
Paul Lawrencefd7db732015-04-10 07:48:51 -0700135 SHA512_Final(key_ref2, &c);
136
137 return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE);
138}
139
Paul Crowley93363482015-07-07 15:17:22 +0100140static ext4_encryption_key fill_key(const std::string &key)
Paul Crowleyf25a35a2015-05-06 13:38:53 +0100141{
Paul Lawrencefd7db732015-04-10 07:48:51 -0700142 // ext4enc:TODO Currently raw key is required to be of length
143 // sizeof(ext4_key.raw) == EXT4_MAX_KEY_SIZE, so zero pad to
144 // this length. Change when kernel bug is fixed.
145 ext4_encryption_key ext4_key = {EXT4_ENCRYPTION_MODE_AES_256_XTS,
146 {0},
147 sizeof(ext4_key.raw)};
148 memset(ext4_key.raw, 0, sizeof(ext4_key.raw));
149 static_assert(key_length / 8 <= sizeof(ext4_key.raw),
150 "Key too long!");
Paul Crowley95376d62015-05-06 15:04:43 +0100151 memcpy(ext4_key.raw, &key[0], key.size());
Paul Crowley93363482015-07-07 15:17:22 +0100152 return ext4_key;
153}
Paul Lawrence731a7a22015-04-28 22:14:15 +0000154
Paul Crowley93363482015-07-07 15:17:22 +0100155static std::string keyname(const std::string &raw_ref)
156{
Paul Lawrencefd7db732015-04-10 07:48:51 -0700157 std::ostringstream o;
Paul Crowley93363482015-07-07 15:17:22 +0100158 o << "ext4:";
Paul Lawrencefd7db732015-04-10 07:48:51 -0700159 for (auto i = raw_ref.begin(); i != raw_ref.end(); ++i) {
160 o << std::hex << std::setw(2) << std::setfill('0') << (int)*i;
161 }
Paul Crowley93363482015-07-07 15:17:22 +0100162 return o.str();
163}
Paul Lawrencefd7db732015-04-10 07:48:51 -0700164
Paul Crowley93363482015-07-07 15:17:22 +0100165// Get the keyring we store all keys in
166static key_serial_t e4crypt_keyring()
167{
168 return keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "e4crypt", 0);
169}
Paul Lawrence731a7a22015-04-28 22:14:15 +0000170
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000171// Install password into global keyring
172// Return raw key reference for use in policy
173static bool install_key(const std::string &key, std::string &raw_ref)
Paul Crowley93363482015-07-07 15:17:22 +0100174{
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000175 if (key.size() != key_length/8) {
176 LOG(ERROR) << "Wrong size key " << key.size();
177 return false;
178 }
179 auto ext4_key = fill_key(key);
180 raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size);
181 auto ref = keyname(raw_ref);
Paul Crowley93363482015-07-07 15:17:22 +0100182 key_serial_t device_keyring = e4crypt_keyring();
Paul Lawrencefd7db732015-04-10 07:48:51 -0700183 key_serial_t key_id = add_key("logon", ref.c_str(),
Paul Lawrence731a7a22015-04-28 22:14:15 +0000184 (void*)&ext4_key, sizeof(ext4_key),
185 device_keyring);
Paul Lawrence731a7a22015-04-28 22:14:15 +0000186 if (key_id == -1) {
Paul Crowley285956f2016-01-20 13:12:38 +0000187 PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000188 return false;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000189 }
Paul Crowley285956f2016-01-20 13:12:38 +0000190 LOG(INFO) << "Added key " << key_id << " (" << ref << ") to keyring "
191 << device_keyring << " in process " << getpid();
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000192 return true;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000193}
194
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000195static std::string get_de_key_path(userid_t user_id) {
196 return StringPrintf("%s/de/%d", user_key_dir.c_str(), user_id);
197}
198
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000199static std::string get_ce_key_path(userid_t user_id) {
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000200 return StringPrintf("%s/ce/%d/current", user_key_dir.c_str(), user_id);
Paul Crowleyb33e8872015-05-19 12:34:09 +0100201}
202
Paul Crowley05720802016-02-08 15:55:41 +0000203static bool read_and_install_user_ce_key(
204 userid_t user_id, const android::vold::KeyAuthentication &auth) {
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000205 if (s_ce_key_raw_refs.count(user_id) != 0) return true;
Paul Crowley05720802016-02-08 15:55:41 +0000206 const auto ce_key_path = get_ce_key_path(user_id);
207 std::string ce_key;
208 if (!android::vold::retrieveKey(ce_key_path, auth, ce_key)) return false;
209 std::string ce_raw_ref;
210 if (!install_key(ce_key, ce_raw_ref)) return false;
211 s_ce_keys[user_id] = ce_key;
212 s_ce_key_raw_refs[user_id] = ce_raw_ref;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000213 LOG(DEBUG) << "Installed ce key for user " << user_id;
Paul Crowley1ef25582016-01-21 20:26:12 +0000214 return true;
Paul Crowley285956f2016-01-20 13:12:38 +0000215}
216
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000217static bool prepare_dir(const std::string &dir, mode_t mode, uid_t uid, gid_t gid) {
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000218 LOG(DEBUG) << "Preparing: " << dir;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000219 if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
220 PLOG(ERROR) << "Failed to prepare " << dir;
Paul Crowley285956f2016-01-20 13:12:38 +0000221 return false;
222 }
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000223 return true;
224}
225
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000226static bool random_key(std::string &key) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000227 if (android::vold::ReadRandomBytes(key_length / 8, key) != 0) {
228 // TODO status_t plays badly with PLOG, fix it.
229 LOG(ERROR) << "Random read failed";
Paul Crowley285956f2016-01-20 13:12:38 +0000230 return false;
231 }
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000232 return true;
233}
234
235static bool path_exists(const std::string &path) {
236 return access(path.c_str(), F_OK) == 0;
237}
238
239// NB this assumes that there is only one thread listening for crypt commands, because
240// it creates keys in a fixed location.
Paul Crowley05720802016-02-08 15:55:41 +0000241static bool store_key(const std::string &key_path,
242 const android::vold::KeyAuthentication &auth, const std::string &key) {
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000243 if (path_exists(key_path)) {
244 LOG(ERROR) << "Already exists, cannot create key at: " << key_path;
245 return false;
246 }
247 if (path_exists(user_key_temp)) {
248 android::vold::destroyKey(user_key_temp);
249 }
Paul Crowley05720802016-02-08 15:55:41 +0000250 if (!android::vold::storeKey(user_key_temp, auth, key)) return false;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000251 if (rename(user_key_temp.c_str(), key_path.c_str()) != 0) {
252 PLOG(ERROR) << "Unable to move new key to location: " << key_path;
253 return false;
Paul Crowley95376d62015-05-06 15:04:43 +0100254 }
Paul Crowley285956f2016-01-20 13:12:38 +0000255 LOG(DEBUG) << "Created key " << key_path;
Paul Crowley95376d62015-05-06 15:04:43 +0100256 return true;
257}
258
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000259static bool create_and_install_user_keys(userid_t user_id, bool create_ephemeral) {
260 std::string de_key, ce_key;
261 if (!random_key(de_key)) return false;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000262 if (!random_key(ce_key)) return false;
263 if (create_ephemeral) {
264 // If the key should be created as ephemeral, don't store it.
265 s_ephemeral_users.insert(user_id);
266 } else {
Paul Crowley05720802016-02-08 15:55:41 +0000267 if (!store_key(get_de_key_path(user_id), kEmptyAuthentication, de_key)) return false;
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000268 if (!prepare_dir(user_key_dir + "/ce/" + std::to_string(user_id),
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000269 0700, AID_ROOT, AID_ROOT)) return false;
Paul Crowley05720802016-02-08 15:55:41 +0000270 if (!store_key(get_ce_key_path(user_id), kEmptyAuthentication, ce_key)) return false;
Paul Crowley95376d62015-05-06 15:04:43 +0100271 }
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000272 std::string de_raw_ref;
273 if (!install_key(de_key, de_raw_ref)) return false;
274 s_de_key_raw_refs[user_id] = de_raw_ref;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000275 std::string ce_raw_ref;
276 if (!install_key(ce_key, ce_raw_ref)) return false;
Paul Crowley05720802016-02-08 15:55:41 +0000277 s_ce_keys[user_id] = ce_key;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000278 s_ce_key_raw_refs[user_id] = ce_raw_ref;
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000279 LOG(DEBUG) << "Created keys for user " << user_id;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000280 return true;
281}
282
283static bool lookup_key_ref(const std::map<userid_t, std::string> &key_map,
284 userid_t user_id, std::string &raw_ref) {
285 auto refi = key_map.find(user_id);
286 if (refi == key_map.end()) {
287 LOG(ERROR) << "Cannot find key for " << user_id;
288 return false;
289 }
290 raw_ref = refi->second;
291 return true;
292}
293
Jeff Sharkey47695b22016-02-01 17:02:29 -0700294static bool ensure_policy(const std::string &raw_ref, const std::string& path) {
295 if (e4crypt_policy_ensure(path.c_str(), raw_ref.data(), raw_ref.size()) != 0) {
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000296 LOG(ERROR) << "Failed to set policy on: " << path;
297 return false;
298 }
299 return true;
Paul Crowley95376d62015-05-06 15:04:43 +0100300}
Paul Crowleyb33e8872015-05-19 12:34:09 +0100301
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000302static bool is_numeric(const char *name) {
303 for (const char *p = name; *p != '\0'; p++) {
304 if (!isdigit(*p))
305 return false;
306 }
307 return true;
308}
309
310static bool load_all_de_keys() {
311 auto de_dir = user_key_dir + "/de";
312 auto dirp = std::unique_ptr<DIR, int(*)(DIR*)>(opendir(de_dir.c_str()), closedir);
313 if (!dirp) {
314 PLOG(ERROR) << "Unable to read de key directory";
315 return false;
316 }
317 for (;;) {
318 errno = 0;
319 auto entry = readdir(dirp.get());
320 if (!entry) {
321 if (errno) {
322 PLOG(ERROR) << "Unable to read de key directory";
323 return false;
324 }
325 break;
326 }
327 if (entry->d_type != DT_DIR || !is_numeric(entry->d_name)) {
328 LOG(DEBUG) << "Skipping non-de-key " << entry->d_name;
329 continue;
330 }
331 userid_t user_id = atoi(entry->d_name);
332 if (s_de_key_raw_refs.count(user_id) == 0) {
Paul Crowley05720802016-02-08 15:55:41 +0000333 auto key_path = de_dir + "/" + entry->d_name;
334 std::string key;
335 if (!android::vold::retrieveKey(key_path, kEmptyAuthentication, key)) return false;
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000336 std::string raw_ref;
Paul Crowley05720802016-02-08 15:55:41 +0000337 if (!install_key(key, raw_ref)) return false;
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000338 s_de_key_raw_refs[user_id] = raw_ref;
339 LOG(DEBUG) << "Installed de key for user " << user_id;
340 }
341 }
342 // ext4enc:TODO: go through all DE directories, ensure that all user dirs have the
343 // correct policy set on them, and that no rogue ones exist.
344 return true;
345}
346
Paul Lawrenceaec34df2016-02-03 10:52:41 -0800347int e4crypt_enable(const char* path)
348{
349 LOG(INFO) << "e4crypt_enable";
350
351 if (s_enabled) {
352 LOG(INFO) << "Already enabled";
353 return 0;
354 }
355
356 std::string device_key;
Paul Lawrence5a06a642016-02-03 13:39:13 -0800357 std::string device_key_path = std::string(path) + device_key_leaf;
Paul Crowley05720802016-02-08 15:55:41 +0000358 if (!android::vold::retrieveKey(device_key_path, kEmptyAuthentication, device_key)) {
Paul Lawrenceaec34df2016-02-03 10:52:41 -0800359 LOG(INFO) << "Creating new key";
360 if (!random_key(device_key)) {
361 return -1;
362 }
363
Paul Lawrence5a06a642016-02-03 13:39:13 -0800364 std::string key_temp = std::string(path) + device_key_temp;
365 if (path_exists(key_temp)) {
366 android::vold::destroyKey(key_temp);
367 }
368
Paul Crowley57eedbf2016-02-09 09:30:23 +0000369 if (!android::vold::storeKey(key_temp, kEmptyAuthentication, device_key)) return -1;
Paul Lawrence5a06a642016-02-03 13:39:13 -0800370 if (rename(key_temp.c_str(), device_key_path.c_str()) != 0) {
371 PLOG(ERROR) << "Unable to move new key to location: "
372 << device_key_path;
Paul Crowley57eedbf2016-02-09 09:30:23 +0000373 return -1;
Paul Lawrenceaec34df2016-02-03 10:52:41 -0800374 }
375 }
376
377 std::string device_key_ref;
378 if (!install_key(device_key, device_key_ref)) {
379 LOG(ERROR) << "Failed to install device key";
380 return -1;
381 }
382
Paul Lawrencef10544d2016-02-04 08:18:52 -0800383 std::string ref_filename = std::string("/data") + e4crypt_key_ref;
384 if (!android::base::WriteStringToFile(device_key_ref, ref_filename)) {
385 PLOG(ERROR) << "Cannot save key reference";
Paul Lawrenceaec34df2016-02-03 10:52:41 -0800386 return -1;
387 }
388
389 s_enabled = true;
390 return 0;
391}
392
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000393int e4crypt_init_user0() {
394 LOG(DEBUG) << "e4crypt_init_user0";
395 if (e4crypt_is_native()) {
396 if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return -1;
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000397 if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return -1;
398 if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return -1;
399 auto de_path = get_de_key_path(0);
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000400 auto ce_path = get_ce_key_path(0);
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000401 if (!path_exists(de_path) || !path_exists(ce_path)) {
402 if (path_exists(de_path)) {
403 android::vold::destroyKey(de_path); // Ignore failure
404 }
405 if (path_exists(ce_path)) {
406 android::vold::destroyKey(ce_path); // Ignore failure
407 }
408 if (!create_and_install_user_keys(0, false)) return -1;
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000409 }
Jeff Sharkey47695b22016-02-01 17:02:29 -0700410 // TODO: switch to loading only DE_0 here once framework makes
411 // explicit calls to install DE keys for secondary users
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000412 if (!load_all_de_keys()) return -1;
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000413 }
Jeff Sharkey47695b22016-02-01 17:02:29 -0700414 // We can only safely prepare DE storage here, since CE keys are probably
415 // entangled with user credentials. The framework will always prepare CE
416 // storage once CE keys are installed.
417 if (e4crypt_prepare_user_storage(nullptr, 0, 0, FLAG_STORAGE_DE) != 0) {
418 LOG(ERROR) << "Failed to prepare user 0 storage";
419 return -1;
420 }
Jeff Sharkey0754a452016-02-08 12:21:42 -0700421
422 // If this is a non-FBE device that recently left an emulated mode,
423 // restore user data directories to known-good state.
424 if (!e4crypt_is_native() && !e4crypt_is_emulated()) {
Jeff Sharkey695d9282016-02-08 18:10:34 -0700425 e4crypt_unlock_user_key(0, 0, "!", "!");
Jeff Sharkey0754a452016-02-08 12:21:42 -0700426 }
427
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000428 return 0;
429}
430
Paul Crowley27cbce92015-12-10 14:51:30 +0000431int e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
Paul Crowley285956f2016-01-20 13:12:38 +0000432 LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial;
Paul Crowleyea62e262016-01-28 12:23:53 +0000433 if (!e4crypt_is_native()) {
434 return 0;
435 }
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000436 // FIXME test for existence of key that is not loaded yet
437 if (s_ce_key_raw_refs.count(user_id) != 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000438 LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for "
439 << user_id << " serial " << serial;
440 // FIXME should we fail the command?
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800441 return 0;
442 }
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000443 if (!create_and_install_user_keys(user_id, ephemeral)) {
Paul Crowley285956f2016-01-20 13:12:38 +0000444 return -1;
445 }
446 // TODO: create second key for user_de data
447 return 0;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800448}
449
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000450static bool evict_key(const std::string &raw_ref) {
451 auto ref = keyname(raw_ref);
Paul Crowley93363482015-07-07 15:17:22 +0100452 auto key_serial = keyctl_search(e4crypt_keyring(), "logon", ref.c_str(), 0);
Paul Crowley1ef25582016-01-21 20:26:12 +0000453 if (keyctl_revoke(key_serial) != 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000454 PLOG(ERROR) << "Failed to revoke key with serial " << key_serial << " ref " << ref;
Paul Crowley1ef25582016-01-21 20:26:12 +0000455 return false;
Paul Crowley93363482015-07-07 15:17:22 +0100456 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000457 LOG(DEBUG) << "Revoked key with serial " << key_serial << " ref " << ref;
458 return true;
459}
460
461int e4crypt_destroy_user_key(userid_t user_id) {
462 LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")";
Paul Crowleyea62e262016-01-28 12:23:53 +0000463 if (!e4crypt_is_native()) {
464 return 0;
465 }
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000466 bool success = true;
Paul Crowley05720802016-02-08 15:55:41 +0000467 s_ce_keys.erase(user_id);
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000468 std::string raw_ref;
469 success &= lookup_key_ref(s_ce_key_raw_refs, user_id, raw_ref) && evict_key(raw_ref);
Paul Crowley05720802016-02-08 15:55:41 +0000470 s_ce_key_raw_refs.erase(user_id);
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000471 success &= lookup_key_ref(s_de_key_raw_refs, user_id, raw_ref) && evict_key(raw_ref);
Paul Crowley05720802016-02-08 15:55:41 +0000472 s_de_key_raw_refs.erase(user_id);
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000473 auto it = s_ephemeral_users.find(user_id);
474 if (it != s_ephemeral_users.end()) {
475 s_ephemeral_users.erase(it);
Paul Crowley1ef25582016-01-21 20:26:12 +0000476 } else {
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000477 success &= android::vold::destroyKey(get_ce_key_path(user_id));
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000478 success &= android::vold::destroyKey(get_de_key_path(user_id));
Lenka Trochtova395039f2015-11-25 10:13:03 +0100479 }
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000480 return success ? 0 : -1;
Paul Crowleyb33e8872015-05-19 12:34:09 +0100481}
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800482
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700483static int emulated_lock(const std::string& path) {
484 if (chmod(path.c_str(), 0000) != 0) {
485 PLOG(ERROR) << "Failed to chmod " << path;
486 return -1;
487 }
488#if EMULATED_USES_SELINUX
489 if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
490 PLOG(WARNING) << "Failed to setfilecon " << path;
491 return -1;
492 }
493#endif
494 return 0;
495}
496
497static int emulated_unlock(const std::string& path, mode_t mode) {
498 if (chmod(path.c_str(), mode) != 0) {
499 PLOG(ERROR) << "Failed to chmod " << path;
Paul Crowleya042cb52016-01-21 17:24:49 +0000500 // FIXME temporary workaround for b/26713622
501 if (e4crypt_is_emulated()) return -1;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700502 }
503#if EMULATED_USES_SELINUX
504 if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
505 PLOG(WARNING) << "Failed to restorecon " << path;
Paul Crowleya042cb52016-01-21 17:24:49 +0000506 // FIXME temporary workaround for b/26713622
507 if (e4crypt_is_emulated()) return -1;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700508 }
509#endif
510 return 0;
511}
512
Paul Crowley05720802016-02-08 15:55:41 +0000513static bool parse_hex(const char *hex, std::string &result) {
514 if (strcmp("!", hex) == 0) {
515 result = "";
516 return true;
517 }
518 if (android::vold::HexToStr(hex, result) != 0) {
519 LOG(ERROR) << "Invalid FBE hex string"; // Don't log the string for security reasons
520 return false;
521 }
522 return true;
523}
524
525int e4crypt_change_user_key(userid_t user_id, int serial,
526 const char* token_hex, const char* old_secret_hex, const char* new_secret_hex) {
527 LOG(DEBUG) << "e4crypt_change_user_key " << user_id << " serial=" << serial <<
528 " token_present=" << (strcmp(token_hex, "!") != 0);
529 if (!e4crypt_is_native()) return 0;
530 if (s_ephemeral_users.count(user_id) != 0) return 0;
531 std::string token, old_secret, new_secret;
532 if (!parse_hex(token_hex, token)) return -1;
533 if (!parse_hex(old_secret_hex, old_secret)) return -1;
534 if (!parse_hex(new_secret_hex, new_secret)) return -1;
535 auto auth = new_secret.empty()
536 ? kEmptyAuthentication
537 : android::vold::KeyAuthentication(token, new_secret);
538 auto it = s_ce_keys.find(user_id);
539 if (it == s_ce_keys.end()) {
540 LOG(ERROR) << "Key not loaded into memory, can't change for user " << user_id;
541 return -1;
542 }
543 auto ce_key = it->second;
544 auto ce_key_path = get_ce_key_path(user_id);
545 android::vold::destroyKey(ce_key_path);
546 if (!store_key(ce_key_path, auth, ce_key)) return -1;
547 return 0;
548}
549
Jeff Sharkey47695b22016-02-01 17:02:29 -0700550// TODO: rename to 'install' for consistency, and take flags to know which keys to install
Paul Crowley05720802016-02-08 15:55:41 +0000551int e4crypt_unlock_user_key(userid_t user_id, int serial,
552 const char* token_hex, const char* secret_hex) {
553 LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " serial=" << serial <<
554 " token_present=" << (strcmp(token_hex, "!") != 0);
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700555 if (e4crypt_is_native()) {
Paul Crowley05720802016-02-08 15:55:41 +0000556 if (s_ce_key_raw_refs.count(user_id) != 0) {
557 LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id;
558 return 0;
559 }
560 std::string token, secret;
561 if (!parse_hex(token_hex, token)) return false;
562 if (!parse_hex(secret_hex, secret)) return false;
563 android::vold::KeyAuthentication auth(token, secret);
564 if (!read_and_install_user_ce_key(user_id, auth)) {
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000565 LOG(ERROR) << "Couldn't read key for " << user_id;
566 return -1;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800567 }
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700568 } else {
569 // When in emulation mode, we just use chmod. However, we also
570 // unlock directories when not in emulation mode, to bring devices
571 // back into a known-good state.
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700572 if (emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
Jeff Sharkey0754a452016-02-08 12:21:42 -0700573 emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) ||
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700574 emulated_unlock(android::vold::BuildDataMediaPath(nullptr, user_id), 0770) ||
575 emulated_unlock(android::vold::BuildDataUserPath(nullptr, user_id), 0771)) {
576 LOG(ERROR) << "Failed to unlock user " << user_id;
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700577 return -1;
578 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800579 }
580 return 0;
581}
582
Jeff Sharkey47695b22016-02-01 17:02:29 -0700583// TODO: rename to 'evict' for consistency
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800584int e4crypt_lock_user_key(userid_t user_id) {
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700585 if (e4crypt_is_native()) {
586 // TODO: remove from kernel keyring
587 } else if (e4crypt_is_emulated()) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800588 // When in emulation mode, we just use chmod
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700589 if (emulated_lock(android::vold::BuildDataSystemCePath(user_id)) ||
Jeff Sharkey0754a452016-02-08 12:21:42 -0700590 emulated_lock(android::vold::BuildDataMiscCePath(user_id)) ||
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700591 emulated_lock(android::vold::BuildDataMediaPath(nullptr, user_id)) ||
592 emulated_lock(android::vold::BuildDataUserPath(nullptr, user_id))) {
Paul Crowley57eedbf2016-02-09 09:30:23 +0000593 LOG(ERROR) << "Failed to lock user " << user_id;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800594 return -1;
595 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800596 }
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700597
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800598 return 0;
599}
600
Jeff Sharkey47695b22016-02-01 17:02:29 -0700601int e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id,
602 int serial, int flags) {
603 LOG(DEBUG) << "e4crypt_prepare_user_storage for volume " << escape_null(volume_uuid)
604 << ", user " << user_id << ", serial " << serial << ", flags " << flags;
605
606 if (flags & FLAG_STORAGE_DE) {
607 auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
608 auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
609 auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
610
611 if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return -1;
612 if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return -1;
613 if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return -1;
614
615 if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) {
616 std::string de_raw_ref;
617 if (!lookup_key_ref(s_de_key_raw_refs, user_id, de_raw_ref)) return -1;
618 if (!ensure_policy(de_raw_ref, system_de_path)) return -1;
619 if (!ensure_policy(de_raw_ref, misc_de_path)) return -1;
620 if (!ensure_policy(de_raw_ref, user_de_path)) return -1;
621 }
Paul Crowley285956f2016-01-20 13:12:38 +0000622 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800623
Jeff Sharkey47695b22016-02-01 17:02:29 -0700624 if (flags & FLAG_STORAGE_CE) {
625 auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
626 auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
627 auto media_ce_path = android::vold::BuildDataMediaPath(volume_uuid, user_id);
628 auto user_ce_path = android::vold::BuildDataUserPath(volume_uuid, user_id);
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800629
Jeff Sharkey47695b22016-02-01 17:02:29 -0700630 if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return -1;
631 if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return -1;
632 if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return -1;
633 if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return -1;
634
635 if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) {
636 std::string ce_raw_ref;
637 if (!lookup_key_ref(s_ce_key_raw_refs, user_id, ce_raw_ref)) return -1;
638 if (!ensure_policy(ce_raw_ref, system_ce_path)) return -1;
639 if (!ensure_policy(ce_raw_ref, misc_ce_path)) return -1;
640 if (!ensure_policy(ce_raw_ref, media_ce_path)) return -1;
641 if (!ensure_policy(ce_raw_ref, user_ce_path)) return -1;
642 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800643 }
644
645 return 0;
646}