1d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey/* 2d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * Copyright (C) 2015 The Android Open Source Project 3d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * 4d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * you may not use this file except in compliance with the License. 6d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * You may obtain a copy of the License at 7d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * 8d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * 10d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * See the License for the specific language governing permissions and 14d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * limitations under the License. 15d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey */ 16d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 17731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "Ext4Crypt.h" 18731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 191ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley#include "KeyStorage.h" 20d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include "Utils.h" 21d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 22a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley#include <algorithm> 23fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <iomanip> 24731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <map> 25b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley#include <set> 26fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <sstream> 27df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <string> 28731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 2995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <dirent.h> 30df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <errno.h> 3195376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <fcntl.h> 32a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley#include <limits.h> 33fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <openssl/sha.h> 347a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#include <selinux/android.h> 35df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <stdio.h> 36df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <sys/mount.h> 37df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <sys/stat.h> 38df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <sys/types.h> 39731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 40480fcd2750c1d30f3397d1f3152519a11f60990bPaul Crowley#include <private/android_filesystem_config.h> 41480fcd2750c1d30f3397d1f3152519a11f60990bPaul Crowley 42731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "cryptfs.h" 43731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 447a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#define EMULATED_USES_SELINUX 0 45be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#define MANAGE_MISC_DIRS 0 467a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey 47d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include <cutils/fs.h> 48989fec27690758ad1e6c521713f1a88c50c9c857Tao Bao#include <ext4_utils/ext4_crypt.h> 49989fec27690758ad1e6c521713f1a88c50c9c857Tao Bao#include <ext4_utils/key_control.h> 50d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 517e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/file.h> 526bf0547ccce72233bd465178b919fa7f15e48b45Elliott Hughes#include <android-base/logging.h> 537e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/stringprintf.h> 54731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 55d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeyusing android::base::StringPrintf; 560572080814ea5f7456d9feea05f936c858178159Paul Crowleyusing android::vold::kEmptyAuthentication; 57d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 5847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// NOTE: keep in sync with StorageManager 5947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkeystatic constexpr int FLAG_STORAGE_DE = 1 << 0; 6047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkeystatic constexpr int FLAG_STORAGE_CE = 1 << 1; 6147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 62731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencenamespace { 637ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull 644d2d5244d68e907feb58167b3ee9b40288927247Paul Crowleyconst std::string device_key_dir = std::string() + DATA_MNT_POINT + e4crypt_unencrypted_folder; 65df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string device_key_path = device_key_dir + "/key"; 66df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string device_key_temp = device_key_dir + "/temp"; 675a06a6481bff8916bf366bf9e951ab5c6a405207Paul Lawrence 68df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys"; 69df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string user_key_temp = user_key_dir + "/temp"; 70285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley 71df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool s_global_de_initialized = false; 727b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence 73df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// Some users are ephemeral, don't try to wipe their keys from disk 74df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::set<userid_t> s_ephemeral_users; 75aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 76df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// Map user ids to key references 77df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_de_key_raw_refs; 78df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_ce_key_raw_refs; 7999360d76e548dcf4301669ad7763c90347615861Paul Crowley// TODO abolish this map, per b/26948053 80df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_ce_keys; 81731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 82df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// ext4enc:TODO get this const from somewhere good 83df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst int EXT4_KEY_DESCRIPTOR_SIZE = 8; 84fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 85df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// ext4enc:TODO Include structure from somewhere sensible 86df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// MUST be in sync with ext4_crypto.c in kernel 87df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconstexpr int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1; 88df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconstexpr int EXT4_AES_256_XTS_KEY_SIZE = 64; 89df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconstexpr int EXT4_MAX_KEY_SIZE = 64; 90df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystruct ext4_encryption_key { 91df528a7011b302c91579898c4a37361214ab05bbPaul Crowley uint32_t mode; 92df528a7011b302c91579898c4a37361214ab05bbPaul Crowley char raw[EXT4_MAX_KEY_SIZE]; 93df528a7011b302c91579898c4a37361214ab05bbPaul Crowley uint32_t size; 94df528a7011b302c91579898c4a37361214ab05bbPaul Crowley}; 95731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 96731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 9738132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowleystatic bool e4crypt_is_emulated() { 9838132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley return property_get_bool("persist.sys.emulate_fbe", false); 9938132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley} 10038132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley 10138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowleystatic const char* escape_null(const char* value) { 10238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley return (value == nullptr) ? "null" : value; 103731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 104731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 1059336348200758d067fed164368636521b4e58621Paul Crowley// Get raw keyref - used to make keyname and to pass to ioctl 106df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic std::string generate_key_ref(const char* key, int length) { 107fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_CTX c; 108fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 109fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Init(&c); 110fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Update(&c, key, length); 111285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley unsigned char key_ref1[SHA512_DIGEST_LENGTH]; 112fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Final(key_ref1, &c); 113fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 114fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Init(&c); 115285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH); 116285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley unsigned char key_ref2[SHA512_DIGEST_LENGTH]; 117fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Final(key_ref2, &c); 118fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 119d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley static_assert(EXT4_KEY_DESCRIPTOR_SIZE <= SHA512_DIGEST_LENGTH, 120df528a7011b302c91579898c4a37361214ab05bbPaul Crowley "Hash too short for descriptor"); 121fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE); 122fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence} 123fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 124df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool fill_key(const std::string& key, ext4_encryption_key* ext4_key) { 1252199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley if (key.size() != EXT4_AES_256_XTS_KEY_SIZE) { 1262199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley LOG(ERROR) << "Wrong size key " << key.size(); 1272199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley return false; 1282199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley } 129df528a7011b302c91579898c4a37361214ab05bbPaul Crowley static_assert(EXT4_AES_256_XTS_KEY_SIZE <= sizeof(ext4_key->raw), "Key too long!"); 130a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley ext4_key->mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; 131a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley ext4_key->size = key.size(); 132a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley memset(ext4_key->raw, 0, sizeof(ext4_key->raw)); 133a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley memcpy(ext4_key->raw, key.data(), key.size()); 1342199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley return true; 1359336348200758d067fed164368636521b4e58621Paul Crowley} 136fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 137df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic std::string keyname(const std::string& raw_ref) { 138fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence std::ostringstream o; 1399336348200758d067fed164368636521b4e58621Paul Crowley o << "ext4:"; 140392c4dbdc1a0220f35d5c34d5c61f8a8197d175fYong Yao for (unsigned char i : raw_ref) { 141d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley o << std::hex << std::setw(2) << std::setfill('0') << (int)i; 142fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence } 1439336348200758d067fed164368636521b4e58621Paul Crowley return o.str(); 1449336348200758d067fed164368636521b4e58621Paul Crowley} 145731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 1469336348200758d067fed164368636521b4e58621Paul Crowley// Get the keyring we store all keys in 147df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool e4crypt_keyring(key_serial_t* device_keyring) { 148a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "e4crypt", 0); 149a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (*device_keyring == -1) { 150d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley PLOG(ERROR) << "Unable to find device keyring"; 151d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley return false; 152d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley } 153d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley return true; 1549336348200758d067fed164368636521b4e58621Paul Crowley} 155731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 156b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley// Install password into global keyring 157b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley// Return raw key reference for use in policy 158df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool install_key(const std::string& key, std::string* raw_ref) { 1592199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley ext4_encryption_key ext4_key; 160a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!fill_key(key, &ext4_key)) return false; 161a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley *raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size); 162a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley auto ref = keyname(*raw_ref); 163d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley key_serial_t device_keyring; 164a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!e4crypt_keyring(&device_keyring)) return false; 165df528a7011b302c91579898c4a37361214ab05bbPaul Crowley key_serial_t key_id = 166df528a7011b302c91579898c4a37361214ab05bbPaul Crowley add_key("logon", ref.c_str(), (void*)&ext4_key, sizeof(ext4_key), device_keyring); 167731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (key_id == -1) { 168285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring; 169b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return false; 170731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 171df528a7011b302c91579898c4a37361214ab05bbPaul Crowley LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring 172df528a7011b302c91579898c4a37361214ab05bbPaul Crowley << " in process " << getpid(); 17385e3d8cd50c540b1a4827bd179e3b8b609731e61Paul Lawrence 174b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return true; 175731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 176731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 177b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowleystatic std::string get_de_key_path(userid_t user_id) { 178b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley return StringPrintf("%s/de/%d", user_key_dir.c_str(), user_id); 179b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley} 180b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley 181a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic std::string get_ce_key_directory_path(userid_t user_id) { 182a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return StringPrintf("%s/ce/%d", user_key_dir.c_str(), user_id); 183a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley} 184a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley 185a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley// Returns the keys newest first 186a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic std::vector<std::string> get_ce_key_paths(const std::string& directory_path) { 187a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(directory_path.c_str()), closedir); 188a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!dirp) { 189a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley PLOG(ERROR) << "Unable to open ce key directory: " + directory_path; 190a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return std::vector<std::string>(); 191a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 192a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::vector<std::string> result; 193a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley for (;;) { 194a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley errno = 0; 195a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const entry = readdir(dirp.get()); 196a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!entry) { 197a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (errno) { 198a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley PLOG(ERROR) << "Unable to read ce key directory: " + directory_path; 199a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return std::vector<std::string>(); 200a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 201a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley break; 202a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 203a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (entry->d_type != DT_DIR || entry->d_name[0] != 'c') { 204a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(DEBUG) << "Skipping non-key " << entry->d_name; 205a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley continue; 206a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 207a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley result.emplace_back(directory_path + "/" + entry->d_name); 208a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 209a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::sort(result.begin(), result.end()); 210a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::reverse(result.begin(), result.end()); 211a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return result; 212a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley} 213a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley 214a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic std::string get_ce_key_current_path(const std::string& directory_path) { 215a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return directory_path + "/current"; 216a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley} 217a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley 218a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic bool get_ce_key_new_path(const std::string& directory_path, 219a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley const std::vector<std::string>& paths, 220a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::string *ce_key_path) { 221a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (paths.empty()) { 222a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley *ce_key_path = get_ce_key_current_path(directory_path); 223a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return true; 224a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 225a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley for (unsigned int i = 0; i < UINT_MAX; i++) { 226a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const candidate = StringPrintf("%s/cx%010u", directory_path.c_str(), i); 227a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (paths[0] < candidate) { 228a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley *ce_key_path = candidate; 229a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return true; 230a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 231a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 232a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return false; 233a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley} 234a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley 235a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley// Discard all keys but the named one; rename it to canonical name. 236a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley// No point in acting on errors in this; ignore them. 237a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic void fixate_user_ce_key(const std::string& directory_path, const std::string &to_fix, 238a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley const std::vector<std::string>& paths) { 239a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley for (auto const other_path: paths) { 240a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (other_path != to_fix) { 241a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley android::vold::destroyKey(other_path); 242a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 243a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 244a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const current_path = get_ce_key_current_path(directory_path); 245a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (to_fix != current_path) { 246a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(DEBUG) << "Renaming " << to_fix << " to " << current_path; 247a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (rename(to_fix.c_str(), current_path.c_str()) != 0) { 248a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley PLOG(WARNING) << "Unable to rename " << to_fix << " to " << current_path; 249a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 250a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 251a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley} 252a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley 253a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic bool read_and_fixate_user_ce_key(userid_t user_id, 254a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley const android::vold::KeyAuthentication& auth, 255a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::string *ce_key) { 256a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const directory_path = get_ce_key_directory_path(user_id); 257a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const paths = get_ce_key_paths(directory_path); 258a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley for (auto const ce_key_path: paths) { 259a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(DEBUG) << "Trying user CE key " << ce_key_path; 260a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (android::vold::retrieveKey(ce_key_path, auth, ce_key)) { 261a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(DEBUG) << "Successfully retrieved key"; 262a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley fixate_user_ce_key(directory_path, ce_key_path, paths); 263a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return true; 264a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 265a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 266a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(ERROR) << "Failed to find working ce key for user " << user_id; 267a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return false; 268b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley} 269b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley 270df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool read_and_install_user_ce_key(userid_t user_id, 271df528a7011b302c91579898c4a37361214ab05bbPaul Crowley const android::vold::KeyAuthentication& auth) { 272b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley if (s_ce_key_raw_refs.count(user_id) != 0) return true; 2730572080814ea5f7456d9feea05f936c858178159Paul Crowley std::string ce_key; 274a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!read_and_fixate_user_ce_key(user_id, auth, &ce_key)) return false; 2750572080814ea5f7456d9feea05f936c858178159Paul Crowley std::string ce_raw_ref; 276a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!install_key(ce_key, &ce_raw_ref)) return false; 2770572080814ea5f7456d9feea05f936c858178159Paul Crowley s_ce_keys[user_id] = ce_key; 2780572080814ea5f7456d9feea05f936c858178159Paul Crowley s_ce_key_raw_refs[user_id] = ce_raw_ref; 279b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley LOG(DEBUG) << "Installed ce key for user " << user_id; 2801ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley return true; 281285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley} 282285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley 283df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool prepare_dir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid) { 284b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley LOG(DEBUG) << "Preparing: " << dir; 28513ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) { 28613ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley PLOG(ERROR) << "Failed to prepare " << dir; 287285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return false; 288285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } 28913ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley return true; 29013ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley} 29113ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley 292be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeystatic bool destroy_dir(const std::string& dir) { 293be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey LOG(DEBUG) << "Destroying: " << dir; 294be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (rmdir(dir.c_str()) != 0 && errno != ENOENT) { 295be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey PLOG(ERROR) << "Failed to destroy " << dir; 296be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey return false; 297be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey } 298be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey return true; 299be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey} 300be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 301df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool random_key(std::string* key) { 302a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (android::vold::ReadRandomBytes(EXT4_AES_256_XTS_KEY_SIZE, *key) != 0) { 3031ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley // TODO status_t plays badly with PLOG, fix it. 3041ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley LOG(ERROR) << "Random read failed"; 305285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return false; 306285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } 307b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return true; 308b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley} 309b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley 310df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool path_exists(const std::string& path) { 311b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return access(path.c_str(), F_OK) == 0; 312b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley} 313b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley 314b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley// NB this assumes that there is only one thread listening for crypt commands, because 315b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley// it creates keys in a fixed location. 316df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool store_key(const std::string& key_path, const std::string& tmp_path, 317df528a7011b302c91579898c4a37361214ab05bbPaul Crowley const android::vold::KeyAuthentication& auth, const std::string& key) { 318b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley if (path_exists(key_path)) { 319b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley LOG(ERROR) << "Already exists, cannot create key at: " << key_path; 320b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return false; 321b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley } 32238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (path_exists(tmp_path)) { 323df528a7011b302c91579898c4a37361214ab05bbPaul Crowley android::vold::destroyKey(tmp_path); // May be partially created so ignore errors 324b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley } 32538132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (!android::vold::storeKey(tmp_path, auth, key)) return false; 32638132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (rename(tmp_path.c_str(), key_path.c_str()) != 0) { 327b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley PLOG(ERROR) << "Unable to move new key to location: " << key_path; 328b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return false; 329b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley } 330b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley LOG(DEBUG) << "Created key " << key_path; 331b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return true; 332b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley} 333b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley 334b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowleystatic bool create_and_install_user_keys(userid_t user_id, bool create_ephemeral) { 335b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley std::string de_key, ce_key; 336a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!random_key(&de_key)) return false; 337a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!random_key(&ce_key)) return false; 338395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova if (create_ephemeral) { 339b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley // If the key should be created as ephemeral, don't store it. 340b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley s_ephemeral_users.insert(user_id); 34113ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley } else { 342a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const directory_path = get_ce_key_directory_path(user_id); 343a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!prepare_dir(directory_path, 0700, AID_ROOT, AID_ROOT)) return false; 344a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const paths = get_ce_key_paths(directory_path); 345a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::string ce_key_path; 346a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false; 347a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!store_key(ce_key_path, user_key_temp, 348a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley kEmptyAuthentication, ce_key)) return false; 349a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley fixate_user_ce_key(directory_path, ce_key_path, paths); 350a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley // Write DE key second; once this is written, all is good. 35138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (!store_key(get_de_key_path(user_id), user_key_temp, 35238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley kEmptyAuthentication, de_key)) return false; 35395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 354b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley std::string de_raw_ref; 355a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!install_key(de_key, &de_raw_ref)) return false; 356b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley s_de_key_raw_refs[user_id] = de_raw_ref; 357b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley std::string ce_raw_ref; 358a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!install_key(ce_key, &ce_raw_ref)) return false; 3590572080814ea5f7456d9feea05f936c858178159Paul Crowley s_ce_keys[user_id] = ce_key; 360b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley s_ce_key_raw_refs[user_id] = ce_raw_ref; 361b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley LOG(DEBUG) << "Created keys for user " << user_id; 362285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return true; 36395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley} 36495376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley 365df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t user_id, 366df528a7011b302c91579898c4a37361214ab05bbPaul Crowley std::string* raw_ref) { 367b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley auto refi = key_map.find(user_id); 368b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley if (refi == key_map.end()) { 369b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley LOG(ERROR) << "Cannot find key for " << user_id; 370b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return false; 371b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley } 372a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley *raw_ref = refi->second; 373b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return true; 374b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley} 375b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley 376df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool ensure_policy(const std::string& raw_ref, const std::string& path) { 377b45caafbccbb743c8b01a5287188969883dec377Eric Biggers const char *contents_mode; 378b45caafbccbb743c8b01a5287188969883dec377Eric Biggers const char *filenames_mode; 379b45caafbccbb743c8b01a5287188969883dec377Eric Biggers 380b45caafbccbb743c8b01a5287188969883dec377Eric Biggers cryptfs_get_file_encryption_modes(&contents_mode, &filenames_mode); 381b45caafbccbb743c8b01a5287188969883dec377Eric Biggers 3826e410597343716924ed4943d1eabd3dea614d325Paul Lawrence if (e4crypt_policy_ensure(path.c_str(), 3836e410597343716924ed4943d1eabd3dea614d325Paul Lawrence raw_ref.data(), raw_ref.size(), 384b45caafbccbb743c8b01a5287188969883dec377Eric Biggers contents_mode, filenames_mode) != 0) { 385b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley LOG(ERROR) << "Failed to set policy on: " << path; 386b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return false; 38795376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 388b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return true; 38995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley} 39095376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley 391df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool is_numeric(const char* name) { 392df528a7011b302c91579898c4a37361214ab05bbPaul Crowley for (const char* p = name; *p != '\0'; p++) { 393df528a7011b302c91579898c4a37361214ab05bbPaul Crowley if (!isdigit(*p)) return false; 394b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 395b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley return true; 396b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley} 397b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley 398b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowleystatic bool load_all_de_keys() { 399b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley auto de_dir = user_key_dir + "/de"; 400df528a7011b302c91579898c4a37361214ab05bbPaul Crowley auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(de_dir.c_str()), closedir); 401b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (!dirp) { 402b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley PLOG(ERROR) << "Unable to read de key directory"; 403b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley return false; 404b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 405b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley for (;;) { 406b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley errno = 0; 407b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley auto entry = readdir(dirp.get()); 408b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (!entry) { 409b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (errno) { 410b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley PLOG(ERROR) << "Unable to read de key directory"; 411b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley return false; 412b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 413b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley break; 414b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 415b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (entry->d_type != DT_DIR || !is_numeric(entry->d_name)) { 416b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley LOG(DEBUG) << "Skipping non-de-key " << entry->d_name; 417b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley continue; 418b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 419b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley userid_t user_id = atoi(entry->d_name); 420b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (s_de_key_raw_refs.count(user_id) == 0) { 4210572080814ea5f7456d9feea05f936c858178159Paul Crowley auto key_path = de_dir + "/" + entry->d_name; 4220572080814ea5f7456d9feea05f936c858178159Paul Crowley std::string key; 423a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!android::vold::retrieveKey(key_path, kEmptyAuthentication, &key)) return false; 424b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley std::string raw_ref; 425a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!install_key(key, &raw_ref)) return false; 426b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley s_de_key_raw_refs[user_id] = raw_ref; 427b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley LOG(DEBUG) << "Installed de key for user " << user_id; 428b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 429b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 430b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley // ext4enc:TODO: go through all DE directories, ensure that all user dirs have the 431b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley // correct policy set on them, and that no rogue ones exist. 432b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley return true; 433b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley} 434b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley 435df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_initialize_global_de() { 43638132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley LOG(INFO) << "e4crypt_initialize_global_de"; 437aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 43838132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (s_global_de_initialized) { 43938132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley LOG(INFO) << "Already initialized"; 44076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 441aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence } 442aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 443b45caafbccbb743c8b01a5287188969883dec377Eric Biggers const char *contents_mode; 444b45caafbccbb743c8b01a5287188969883dec377Eric Biggers const char *filenames_mode; 445b45caafbccbb743c8b01a5287188969883dec377Eric Biggers cryptfs_get_file_encryption_modes(&contents_mode, &filenames_mode); 446b45caafbccbb743c8b01a5287188969883dec377Eric Biggers std::string modestring = std::string(contents_mode) + ":" + filenames_mode; 447b45caafbccbb743c8b01a5287188969883dec377Eric Biggers 4486e410597343716924ed4943d1eabd3dea614d325Paul Lawrence std::string mode_filename = std::string("/data") + e4crypt_key_mode; 449b45caafbccbb743c8b01a5287188969883dec377Eric Biggers if (!android::base::WriteStringToFile(modestring, mode_filename)) { 4506e410597343716924ed4943d1eabd3dea614d325Paul Lawrence PLOG(ERROR) << "Cannot save type"; 4516e410597343716924ed4943d1eabd3dea614d325Paul Lawrence return false; 4526e410597343716924ed4943d1eabd3dea614d325Paul Lawrence } 4536e410597343716924ed4943d1eabd3dea614d325Paul Lawrence 454aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence std::string device_key; 45538132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (path_exists(device_key_path)) { 45638132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (!android::vold::retrieveKey(device_key_path, 457a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley kEmptyAuthentication, &device_key)) return false; 45838132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley } else { 459aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence LOG(INFO) << "Creating new key"; 460a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!random_key(&device_key)) return false; 46138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (!store_key(device_key_path, device_key_temp, 46276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley kEmptyAuthentication, device_key)) return false; 463aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence } 464aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 465aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence std::string device_key_ref; 466a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!install_key(device_key, &device_key_ref)) { 467aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence LOG(ERROR) << "Failed to install device key"; 46876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 469aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence } 470aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 471f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence std::string ref_filename = std::string("/data") + e4crypt_key_ref; 472f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence if (!android::base::WriteStringToFile(device_key_ref, ref_filename)) { 473f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence PLOG(ERROR) << "Cannot save key reference"; 47476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 475aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence } 476aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 47738132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley s_global_de_initialized = true; 47876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 479aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence} 480aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 48176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_init_user0() { 4828fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley LOG(DEBUG) << "e4crypt_init_user0"; 4838fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley if (e4crypt_is_native()) { 48476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false; 48576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false; 48676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false; 487a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!path_exists(get_de_key_path(0))) { 48876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!create_and_install_user_keys(0, false)) return false; 4898fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley } 49047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // TODO: switch to loading only DE_0 here once framework makes 49147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // explicit calls to install DE keys for secondary users 49276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!load_all_de_keys()) return false; 4938fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley } 49447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // We can only safely prepare DE storage here, since CE keys are probably 49547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // entangled with user credentials. The framework will always prepare CE 49647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // storage once CE keys are installed. 49776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!e4crypt_prepare_user_storage(nullptr, 0, 0, FLAG_STORAGE_DE)) { 49847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey LOG(ERROR) << "Failed to prepare user 0 storage"; 49976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 50047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 5010754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey 5020754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey // If this is a non-FBE device that recently left an emulated mode, 5030754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey // restore user data directories to known-good state. 5040754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey if (!e4crypt_is_native() && !e4crypt_is_emulated()) { 505695d9282862bac4fb4034ebb2d5b089b8ff9c4a3Jeff Sharkey e4crypt_unlock_user_key(0, 0, "!", "!"); 5060754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey } 5070754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey 50876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 5098fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley} 5108fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley 51176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) { 512285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial; 513ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley if (!e4crypt_is_native()) { 51476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 515ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley } 516b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley // FIXME test for existence of key that is not loaded yet 517b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley if (s_ce_key_raw_refs.count(user_id) != 0) { 518df528a7011b302c91579898c4a37361214ab05bbPaul Crowley LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for " << user_id 519df528a7011b302c91579898c4a37361214ab05bbPaul Crowley << " serial " << serial; 520285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // FIXME should we fail the command? 52176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 52295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 523b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (!create_and_install_user_keys(user_id, ephemeral)) { 52476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 525d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 52676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 527d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 528d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 529fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggersstatic bool evict_key(const std::string &raw_ref) { 5307ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull auto ref = keyname(raw_ref); 5317ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull key_serial_t device_keyring; 532fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers if (!e4crypt_keyring(&device_keyring)) return false; 5337ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0); 5347ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull 535fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers // Unlink the key from the keyring. Prefer unlinking to revoking or 536fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers // invalidating, since unlinking is actually no less secure currently, and 537fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers // it avoids bugs in certain kernel versions where the keyring key is 538fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers // referenced from places it shouldn't be. 539fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers if (keyctl_unlink(key_serial, device_keyring) != 0) { 540fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref; 541fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers return false; 542fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers } 543fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref; 544fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers return true; 5457ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull} 5467ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull 5477ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scullstatic bool evict_ce_key(userid_t user_id) { 5487ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull s_ce_keys.erase(user_id); 5497ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull bool success = true; 5507ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull std::string raw_ref; 5517ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull // If we haven't loaded the CE key, no need to evict it. 5527ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull if (lookup_key_ref(s_ce_key_raw_refs, user_id, &raw_ref)) { 5537ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull success &= evict_key(raw_ref); 5547ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull } 5557ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull s_ce_key_raw_refs.erase(user_id); 5567ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull return success; 5577ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull} 5587ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull 55976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_destroy_user_key(userid_t user_id) { 5601ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")"; 561ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley if (!e4crypt_is_native()) { 56276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 563ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley } 564b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley bool success = true; 565b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley std::string raw_ref; 5667ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull success &= evict_ce_key(user_id); 5677ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull success &= lookup_key_ref(s_de_key_raw_refs, user_id, &raw_ref) && evict_key(raw_ref); 5680572080814ea5f7456d9feea05f936c858178159Paul Crowley s_de_key_raw_refs.erase(user_id); 569b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley auto it = s_ephemeral_users.find(user_id); 570b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley if (it != s_ephemeral_users.end()) { 571b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley s_ephemeral_users.erase(it); 5721ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley } else { 573a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley for (auto const path: get_ce_key_paths(get_ce_key_directory_path(user_id))) { 574a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley success &= android::vold::destroyKey(path); 575a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 576ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley auto de_key_path = get_de_key_path(user_id); 577ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley if (path_exists(de_key_path)) { 578ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley success &= android::vold::destroyKey(de_key_path); 579ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley } else { 580ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley LOG(INFO) << "Not present so not erasing: " << de_key_path; 581ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley } 582b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley } 58376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return success; 584b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley} 585d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 58676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleystatic bool emulated_lock(const std::string& path) { 5877a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (chmod(path.c_str(), 0000) != 0) { 5887a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(ERROR) << "Failed to chmod " << path; 58976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 5907a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 5917a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX 5927a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) { 5937a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(WARNING) << "Failed to setfilecon " << path; 59476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 5957a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 5967a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif 59776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 5987a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey} 5997a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey 60076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleystatic bool emulated_unlock(const std::string& path, mode_t mode) { 6017a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (chmod(path.c_str(), mode) != 0) { 6027a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(ERROR) << "Failed to chmod " << path; 603a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley // FIXME temporary workaround for b/26713622 60476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (e4crypt_is_emulated()) return false; 6057a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 6067a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX 6077a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) { 6087a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(WARNING) << "Failed to restorecon " << path; 609a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley // FIXME temporary workaround for b/26713622 61076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (e4crypt_is_emulated()) return false; 6117a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 6127a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif 61376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 6147a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey} 6157a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey 616df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool parse_hex(const char* hex, std::string* result) { 6170572080814ea5f7456d9feea05f936c858178159Paul Crowley if (strcmp("!", hex) == 0) { 618a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley *result = ""; 6190572080814ea5f7456d9feea05f936c858178159Paul Crowley return true; 6200572080814ea5f7456d9feea05f936c858178159Paul Crowley } 621a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (android::vold::HexToStr(hex, *result) != 0) { 622df528a7011b302c91579898c4a37361214ab05bbPaul Crowley LOG(ERROR) << "Invalid FBE hex string"; // Don't log the string for security reasons 6230572080814ea5f7456d9feea05f936c858178159Paul Crowley return false; 6240572080814ea5f7456d9feea05f936c858178159Paul Crowley } 6250572080814ea5f7456d9feea05f936c858178159Paul Crowley return true; 6260572080814ea5f7456d9feea05f936c858178159Paul Crowley} 6270572080814ea5f7456d9feea05f936c858178159Paul Crowley 628a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleybool e4crypt_add_user_key_auth(userid_t user_id, int serial, const char* token_hex, 629a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley const char* secret_hex) { 630a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(DEBUG) << "e4crypt_add_user_key_auth " << user_id << " serial=" << serial 631df528a7011b302c91579898c4a37361214ab05bbPaul Crowley << " token_present=" << (strcmp(token_hex, "!") != 0); 63276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!e4crypt_is_native()) return true; 63376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (s_ephemeral_users.count(user_id) != 0) return true; 634a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::string token, secret; 635a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!parse_hex(token_hex, &token)) return false; 636a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!parse_hex(secret_hex, &secret)) return false; 637a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto auth = secret.empty() ? kEmptyAuthentication 638a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley : android::vold::KeyAuthentication(token, secret); 6390572080814ea5f7456d9feea05f936c858178159Paul Crowley auto it = s_ce_keys.find(user_id); 6400572080814ea5f7456d9feea05f936c858178159Paul Crowley if (it == s_ce_keys.end()) { 6410572080814ea5f7456d9feea05f936c858178159Paul Crowley LOG(ERROR) << "Key not loaded into memory, can't change for user " << user_id; 64276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 6430572080814ea5f7456d9feea05f936c858178159Paul Crowley } 6440572080814ea5f7456d9feea05f936c858178159Paul Crowley auto ce_key = it->second; 645a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const directory_path = get_ce_key_directory_path(user_id); 646a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const paths = get_ce_key_paths(directory_path); 647a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::string ce_key_path; 648a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false; 649a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!store_key(ce_key_path, user_key_temp, auth, ce_key)) return false; 650a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return true; 651a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley} 652a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley 653a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleybool e4crypt_fixate_newest_user_key_auth(userid_t user_id) { 654a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(DEBUG) << "e4crypt_fixate_newest_user_key_auth " << user_id; 655a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!e4crypt_is_native()) return true; 65625a713873c8f8d37f7ebbadfbf1ebfaf4bac106bPaul Crowley if (s_ephemeral_users.count(user_id) != 0) return true; 657a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const directory_path = get_ce_key_directory_path(user_id); 658a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const paths = get_ce_key_paths(directory_path); 659a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (paths.empty()) { 660a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(ERROR) << "No ce keys present, cannot fixate for user " << user_id; 661a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return false; 662a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 663a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley fixate_user_ce_key(directory_path, paths[0], paths); 66476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 6650572080814ea5f7456d9feea05f936c858178159Paul Crowley} 6660572080814ea5f7456d9feea05f936c858178159Paul Crowley 66747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// TODO: rename to 'install' for consistency, and take flags to know which keys to install 668df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token_hex, 669df528a7011b302c91579898c4a37361214ab05bbPaul Crowley const char* secret_hex) { 670df528a7011b302c91579898c4a37361214ab05bbPaul Crowley LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " serial=" << serial 671df528a7011b302c91579898c4a37361214ab05bbPaul Crowley << " token_present=" << (strcmp(token_hex, "!") != 0); 672fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey if (e4crypt_is_native()) { 6730572080814ea5f7456d9feea05f936c858178159Paul Crowley if (s_ce_key_raw_refs.count(user_id) != 0) { 6740572080814ea5f7456d9feea05f936c858178159Paul Crowley LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id; 67576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 6760572080814ea5f7456d9feea05f936c858178159Paul Crowley } 6770572080814ea5f7456d9feea05f936c858178159Paul Crowley std::string token, secret; 678a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!parse_hex(token_hex, &token)) return false; 679a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!parse_hex(secret_hex, &secret)) return false; 6800572080814ea5f7456d9feea05f936c858178159Paul Crowley android::vold::KeyAuthentication auth(token, secret); 6810572080814ea5f7456d9feea05f936c858178159Paul Crowley if (!read_and_install_user_ce_key(user_id, auth)) { 6828fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley LOG(ERROR) << "Couldn't read key for " << user_id; 68376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 684d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 685fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey } else { 686fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // When in emulation mode, we just use chmod. However, we also 687fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // unlock directories when not in emulation mode, to bring devices 688fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // back into a known-good state. 68976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) || 690df528a7011b302c91579898c4a37361214ab05bbPaul Crowley !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) || 691be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey !emulated_unlock(android::vold::BuildDataMediaCePath(nullptr, user_id), 0770) || 692be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey !emulated_unlock(android::vold::BuildDataUserCePath(nullptr, user_id), 0771)) { 6937a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey LOG(ERROR) << "Failed to unlock user " << user_id; 69476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 695fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey } 696d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 69776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 698d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 699d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 70047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// TODO: rename to 'evict' for consistency 70176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_lock_user_key(userid_t user_id) { 7027ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull LOG(DEBUG) << "e4crypt_lock_user_key " << user_id; 703fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey if (e4crypt_is_native()) { 7047ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull return evict_ce_key(user_id); 705fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey } else if (e4crypt_is_emulated()) { 706d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey // When in emulation mode, we just use chmod 70776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!emulated_lock(android::vold::BuildDataSystemCePath(user_id)) || 708df528a7011b302c91579898c4a37361214ab05bbPaul Crowley !emulated_lock(android::vold::BuildDataMiscCePath(user_id)) || 709be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey !emulated_lock(android::vold::BuildDataMediaCePath(nullptr, user_id)) || 710be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey !emulated_lock(android::vold::BuildDataUserCePath(nullptr, user_id))) { 71157eedbf8cbd21899a3395ce6f153cd0e05898f3bPaul Crowley LOG(ERROR) << "Failed to lock user " << user_id; 71276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 713d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 714d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 715fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey 71676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 717d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 718d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 719df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial, 720be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey int flags) { 72147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey LOG(DEBUG) << "e4crypt_prepare_user_storage for volume " << escape_null(volume_uuid) 722df528a7011b302c91579898c4a37361214ab05bbPaul Crowley << ", user " << user_id << ", serial " << serial << ", flags " << flags; 72347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 72447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (flags & FLAG_STORAGE_DE) { 725be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // DE_sys key 726be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id); 727be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id); 728be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); 729be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 730be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // DE_n key 73147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto system_de_path = android::vold::BuildDataSystemDePath(user_id); 73247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); 73347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id); 73447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 735be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false; 736be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#if MANAGE_MISC_DIRS 737be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM), 738be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey multiuser_get_uid(user_id, AID_EVERYBODY))) return false; 739be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#endif 740be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; 741be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 74276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; 74376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false; 74476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; 745d1ee944f0839d60b014722c7facbb4a66bd4f2c3Calin Juravle 746be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // For now, FBE is only supported on internal storage 747be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (e4crypt_is_native() && volume_uuid == nullptr) { 74847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey std::string de_raw_ref; 749a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_raw_ref)) return false; 75076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(de_raw_ref, system_de_path)) return false; 75176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(de_raw_ref, misc_de_path)) return false; 75276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(de_raw_ref, user_de_path)) return false; 75347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 75447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 75547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 75647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (flags & FLAG_STORAGE_CE) { 757be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // CE_n key 75847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto system_ce_path = android::vold::BuildDataSystemCePath(user_id); 75947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); 760be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id); 761be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id); 76247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 76376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; 76476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false; 76576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false; 76676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; 76747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 768be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // For now, FBE is only supported on internal storage 769be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (e4crypt_is_native() && volume_uuid == nullptr) { 77047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey std::string ce_raw_ref; 771a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_raw_ref)) return false; 77276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(ce_raw_ref, system_ce_path)) return false; 77376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(ce_raw_ref, misc_ce_path)) return false; 77476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(ce_raw_ref, media_ce_path)) return false; 77576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(ce_raw_ref, user_ce_path)) return false; 776d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey 777d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey // Now that credentials have been installed, we can run restorecon 778d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey // over these paths 779d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey // NOTE: these paths need to be kept in sync with libselinux 780d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey android::vold::RestoreconRecursive(system_ce_path); 781d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey android::vold::RestoreconRecursive(misc_ce_path); 78247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 783d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 784d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 78576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 786d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 787be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 788be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeybool e4crypt_destroy_user_storage(const char* volume_uuid, userid_t user_id, int flags) { 789be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey LOG(DEBUG) << "e4crypt_destroy_user_storage for volume " << escape_null(volume_uuid) 790be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey << ", user " << user_id << ", flags " << flags; 791be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey bool res = true; 792be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 793be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (flags & FLAG_STORAGE_DE) { 794be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // DE_sys key 795be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id); 796be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id); 797be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); 798be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 799be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // DE_n key 800be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto system_de_path = android::vold::BuildDataSystemDePath(user_id); 801be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); 802be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id); 803be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 804be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (volume_uuid == nullptr) { 805be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(system_legacy_path); 806be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#if MANAGE_MISC_DIRS 807be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(misc_legacy_path); 808be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#endif 809be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(profiles_de_path); 810be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(system_de_path); 811be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(misc_de_path); 812be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey } 813be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(user_de_path); 814be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey } 815be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 816be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (flags & FLAG_STORAGE_CE) { 817be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // CE_n key 818be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto system_ce_path = android::vold::BuildDataSystemCePath(user_id); 819be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); 820be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id); 821be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id); 822be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 823be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (volume_uuid == nullptr) { 824be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(system_ce_path); 825be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(misc_ce_path); 826be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey } 827be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(media_ce_path); 828be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(user_ce_path); 829be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey } 830be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 831be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey return res; 832be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey} 833f8d604caf3f9bf0aed9ef070c40933a94016232bRubin Xu 834f8d604caf3f9bf0aed9ef070c40933a94016232bRubin Xubool e4crypt_secdiscard(const char* path) { 835f8d604caf3f9bf0aed9ef070c40933a94016232bRubin Xu return android::vold::runSecdiscardSingle(std::string(path)); 836f8d604caf3f9bf0aed9ef070c40933a94016232bRubin Xu} 837