Ext4Crypt.cpp revision ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3
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" 4347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey#include "ext4_crypt.h" 44df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include "key_control.h" 45731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 467a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#define EMULATED_USES_SELINUX 0 47be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#define MANAGE_MISC_DIRS 0 487a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey 49d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include <cutils/fs.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 { 634d2d5244d68e907feb58167b3ee9b40288927247Paul Crowleyconst std::string device_key_dir = std::string() + DATA_MNT_POINT + e4crypt_unencrypted_folder; 64df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string device_key_path = device_key_dir + "/key"; 65df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string device_key_temp = device_key_dir + "/temp"; 665a06a6481bff8916bf366bf9e951ab5c6a405207Paul Lawrence 67df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys"; 68df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string user_key_temp = user_key_dir + "/temp"; 69285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley 70df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool s_global_de_initialized = false; 717b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence 72df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// Some users are ephemeral, don't try to wipe their keys from disk 73df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::set<userid_t> s_ephemeral_users; 74aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 75df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// Map user ids to key references 76df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_de_key_raw_refs; 77df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_ce_key_raw_refs; 78df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// TODO abolish this map. Keys should not be long-lived in user memory, only kernel memory. 79df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// See 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:"; 140df528a7011b302c91579898c4a37361214ab05bbPaul Crowley for (auto 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) { 3776e410597343716924ed4943d1eabd3dea614d325Paul Lawrence if (e4crypt_policy_ensure(path.c_str(), 3786e410597343716924ed4943d1eabd3dea614d325Paul Lawrence raw_ref.data(), raw_ref.size(), 3796e410597343716924ed4943d1eabd3dea614d325Paul Lawrence cryptfs_get_file_encryption_mode()) != 0) { 380b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley LOG(ERROR) << "Failed to set policy on: " << path; 381b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return false; 38295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 383b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley return true; 38495376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley} 38595376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley 386df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool is_numeric(const char* name) { 387df528a7011b302c91579898c4a37361214ab05bbPaul Crowley for (const char* p = name; *p != '\0'; p++) { 388df528a7011b302c91579898c4a37361214ab05bbPaul Crowley if (!isdigit(*p)) return false; 389b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 390b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley return true; 391b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley} 392b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley 393b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowleystatic bool load_all_de_keys() { 394b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley auto de_dir = user_key_dir + "/de"; 395df528a7011b302c91579898c4a37361214ab05bbPaul Crowley auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(de_dir.c_str()), closedir); 396b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (!dirp) { 397b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley PLOG(ERROR) << "Unable to read de key directory"; 398b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley return false; 399b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 400b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley for (;;) { 401b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley errno = 0; 402b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley auto entry = readdir(dirp.get()); 403b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (!entry) { 404b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (errno) { 405b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley PLOG(ERROR) << "Unable to read de key directory"; 406b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley return false; 407b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 408b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley break; 409b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 410b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (entry->d_type != DT_DIR || !is_numeric(entry->d_name)) { 411b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley LOG(DEBUG) << "Skipping non-de-key " << entry->d_name; 412b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley continue; 413b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 414b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley userid_t user_id = atoi(entry->d_name); 415b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (s_de_key_raw_refs.count(user_id) == 0) { 4160572080814ea5f7456d9feea05f936c858178159Paul Crowley auto key_path = de_dir + "/" + entry->d_name; 4170572080814ea5f7456d9feea05f936c858178159Paul Crowley std::string key; 418a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!android::vold::retrieveKey(key_path, kEmptyAuthentication, &key)) return false; 419b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley std::string raw_ref; 420a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!install_key(key, &raw_ref)) return false; 421b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley s_de_key_raw_refs[user_id] = raw_ref; 422b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley LOG(DEBUG) << "Installed de key for user " << user_id; 423b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 424b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley } 425b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley // ext4enc:TODO: go through all DE directories, ensure that all user dirs have the 426b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley // correct policy set on them, and that no rogue ones exist. 427b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley return true; 428b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley} 429b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley 430df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_initialize_global_de() { 43138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley LOG(INFO) << "e4crypt_initialize_global_de"; 432aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 43338132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (s_global_de_initialized) { 43438132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley LOG(INFO) << "Already initialized"; 43576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 436aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence } 437aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 4386e410597343716924ed4943d1eabd3dea614d325Paul Lawrence std::string mode_filename = std::string("/data") + e4crypt_key_mode; 4396e410597343716924ed4943d1eabd3dea614d325Paul Lawrence std::string mode = cryptfs_get_file_encryption_mode(); 4406e410597343716924ed4943d1eabd3dea614d325Paul Lawrence if (!android::base::WriteStringToFile(mode, mode_filename)) { 4416e410597343716924ed4943d1eabd3dea614d325Paul Lawrence PLOG(ERROR) << "Cannot save type"; 4426e410597343716924ed4943d1eabd3dea614d325Paul Lawrence return false; 4436e410597343716924ed4943d1eabd3dea614d325Paul Lawrence } 4446e410597343716924ed4943d1eabd3dea614d325Paul Lawrence 445aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence std::string device_key; 44638132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (path_exists(device_key_path)) { 44738132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (!android::vold::retrieveKey(device_key_path, 448a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley kEmptyAuthentication, &device_key)) return false; 44938132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley } else { 450aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence LOG(INFO) << "Creating new key"; 451a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!random_key(&device_key)) return false; 45238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley if (!store_key(device_key_path, device_key_temp, 45376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley kEmptyAuthentication, device_key)) return false; 454aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence } 455aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 456aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence std::string device_key_ref; 457a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!install_key(device_key, &device_key_ref)) { 458aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence LOG(ERROR) << "Failed to install device key"; 45976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 460aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence } 461aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 462f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence std::string ref_filename = std::string("/data") + e4crypt_key_ref; 463f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence if (!android::base::WriteStringToFile(device_key_ref, ref_filename)) { 464f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence PLOG(ERROR) << "Cannot save key reference"; 46576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 466aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence } 467aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 46838132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley s_global_de_initialized = true; 46976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 470aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence} 471aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence 47276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_init_user0() { 4738fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley LOG(DEBUG) << "e4crypt_init_user0"; 4748fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley if (e4crypt_is_native()) { 47576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false; 47676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false; 47776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false; 478a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!path_exists(get_de_key_path(0))) { 47976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!create_and_install_user_keys(0, false)) return false; 4808fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley } 48147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // TODO: switch to loading only DE_0 here once framework makes 48247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // explicit calls to install DE keys for secondary users 48376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!load_all_de_keys()) return false; 4848fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley } 48547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // We can only safely prepare DE storage here, since CE keys are probably 48647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // entangled with user credentials. The framework will always prepare CE 48747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey // storage once CE keys are installed. 48876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!e4crypt_prepare_user_storage(nullptr, 0, 0, FLAG_STORAGE_DE)) { 48947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey LOG(ERROR) << "Failed to prepare user 0 storage"; 49076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 49147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 4920754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey 4930754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey // If this is a non-FBE device that recently left an emulated mode, 4940754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey // restore user data directories to known-good state. 4950754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey if (!e4crypt_is_native() && !e4crypt_is_emulated()) { 496695d9282862bac4fb4034ebb2d5b089b8ff9c4a3Jeff Sharkey e4crypt_unlock_user_key(0, 0, "!", "!"); 4970754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey } 4980754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey 49976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 5008fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley} 5018fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley 50276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) { 503285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial; 504ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley if (!e4crypt_is_native()) { 50576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 506ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley } 507b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley // FIXME test for existence of key that is not loaded yet 508b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley if (s_ce_key_raw_refs.count(user_id) != 0) { 509df528a7011b302c91579898c4a37361214ab05bbPaul Crowley LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for " << user_id 510df528a7011b302c91579898c4a37361214ab05bbPaul Crowley << " serial " << serial; 511285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // FIXME should we fail the command? 51276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 51395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 514b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley if (!create_and_install_user_keys(user_id, ephemeral)) { 51576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 516d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 51776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 518d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 519d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 52076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_destroy_user_key(userid_t user_id) { 5211ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")"; 522ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley if (!e4crypt_is_native()) { 52376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 524ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley } 525b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley bool success = true; 5260572080814ea5f7456d9feea05f936c858178159Paul Crowley s_ce_keys.erase(user_id); 527b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley std::string raw_ref; 5280572080814ea5f7456d9feea05f936c858178159Paul Crowley s_ce_key_raw_refs.erase(user_id); 5290572080814ea5f7456d9feea05f936c858178159Paul Crowley s_de_key_raw_refs.erase(user_id); 530b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley auto it = s_ephemeral_users.find(user_id); 531b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley if (it != s_ephemeral_users.end()) { 532b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley s_ephemeral_users.erase(it); 5331ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley } else { 534a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley for (auto const path: get_ce_key_paths(get_ce_key_directory_path(user_id))) { 535a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley success &= android::vold::destroyKey(path); 536a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 537ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley auto de_key_path = get_de_key_path(user_id); 538ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley if (path_exists(de_key_path)) { 539ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley success &= android::vold::destroyKey(de_key_path); 540ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley } else { 541ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley LOG(INFO) << "Not present so not erasing: " << de_key_path; 542ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley } 543b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley } 54476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return success; 545b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley} 546d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 54776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleystatic bool emulated_lock(const std::string& path) { 5487a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (chmod(path.c_str(), 0000) != 0) { 5497a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(ERROR) << "Failed to chmod " << path; 55076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 5517a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 5527a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX 5537a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) { 5547a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(WARNING) << "Failed to setfilecon " << path; 55576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 5567a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 5577a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif 55876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 5597a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey} 5607a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey 56176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleystatic bool emulated_unlock(const std::string& path, mode_t mode) { 5627a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (chmod(path.c_str(), mode) != 0) { 5637a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(ERROR) << "Failed to chmod " << path; 564a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley // FIXME temporary workaround for b/26713622 56576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (e4crypt_is_emulated()) return false; 5667a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 5677a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX 5687a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) { 5697a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(WARNING) << "Failed to restorecon " << path; 570a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley // FIXME temporary workaround for b/26713622 57176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (e4crypt_is_emulated()) return false; 5727a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 5737a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif 57476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 5757a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey} 5767a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey 577df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool parse_hex(const char* hex, std::string* result) { 5780572080814ea5f7456d9feea05f936c858178159Paul Crowley if (strcmp("!", hex) == 0) { 579a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley *result = ""; 5800572080814ea5f7456d9feea05f936c858178159Paul Crowley return true; 5810572080814ea5f7456d9feea05f936c858178159Paul Crowley } 582a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (android::vold::HexToStr(hex, *result) != 0) { 583df528a7011b302c91579898c4a37361214ab05bbPaul Crowley LOG(ERROR) << "Invalid FBE hex string"; // Don't log the string for security reasons 5840572080814ea5f7456d9feea05f936c858178159Paul Crowley return false; 5850572080814ea5f7456d9feea05f936c858178159Paul Crowley } 5860572080814ea5f7456d9feea05f936c858178159Paul Crowley return true; 5870572080814ea5f7456d9feea05f936c858178159Paul Crowley} 5880572080814ea5f7456d9feea05f936c858178159Paul Crowley 589a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleybool e4crypt_add_user_key_auth(userid_t user_id, int serial, const char* token_hex, 590a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley const char* secret_hex) { 591a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(DEBUG) << "e4crypt_add_user_key_auth " << user_id << " serial=" << serial 592df528a7011b302c91579898c4a37361214ab05bbPaul Crowley << " token_present=" << (strcmp(token_hex, "!") != 0); 59376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!e4crypt_is_native()) return true; 59476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (s_ephemeral_users.count(user_id) != 0) return true; 595a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::string token, secret; 596a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!parse_hex(token_hex, &token)) return false; 597a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!parse_hex(secret_hex, &secret)) return false; 598a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto auth = secret.empty() ? kEmptyAuthentication 599a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley : android::vold::KeyAuthentication(token, secret); 6000572080814ea5f7456d9feea05f936c858178159Paul Crowley auto it = s_ce_keys.find(user_id); 6010572080814ea5f7456d9feea05f936c858178159Paul Crowley if (it == s_ce_keys.end()) { 6020572080814ea5f7456d9feea05f936c858178159Paul Crowley LOG(ERROR) << "Key not loaded into memory, can't change for user " << user_id; 60376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 6040572080814ea5f7456d9feea05f936c858178159Paul Crowley } 6050572080814ea5f7456d9feea05f936c858178159Paul Crowley auto ce_key = it->second; 606a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const directory_path = get_ce_key_directory_path(user_id); 607a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const paths = get_ce_key_paths(directory_path); 608a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley std::string ce_key_path; 609a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false; 610a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!store_key(ce_key_path, user_key_temp, auth, ce_key)) return false; 611a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return true; 612a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley} 613a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley 614a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleybool e4crypt_fixate_newest_user_key_auth(userid_t user_id) { 615a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(DEBUG) << "e4crypt_fixate_newest_user_key_auth " << user_id; 616a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (!e4crypt_is_native()) return true; 617a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const directory_path = get_ce_key_directory_path(user_id); 618a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley auto const paths = get_ce_key_paths(directory_path); 619a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley if (paths.empty()) { 620a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley LOG(ERROR) << "No ce keys present, cannot fixate for user " << user_id; 621a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley return false; 622a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley } 623a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley fixate_user_ce_key(directory_path, paths[0], paths); 62476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 6250572080814ea5f7456d9feea05f936c858178159Paul Crowley} 6260572080814ea5f7456d9feea05f936c858178159Paul Crowley 62747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// TODO: rename to 'install' for consistency, and take flags to know which keys to install 628df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token_hex, 629df528a7011b302c91579898c4a37361214ab05bbPaul Crowley const char* secret_hex) { 630df528a7011b302c91579898c4a37361214ab05bbPaul Crowley LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " serial=" << serial 631df528a7011b302c91579898c4a37361214ab05bbPaul Crowley << " token_present=" << (strcmp(token_hex, "!") != 0); 632fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey if (e4crypt_is_native()) { 6330572080814ea5f7456d9feea05f936c858178159Paul Crowley if (s_ce_key_raw_refs.count(user_id) != 0) { 6340572080814ea5f7456d9feea05f936c858178159Paul Crowley LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id; 63576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 6360572080814ea5f7456d9feea05f936c858178159Paul Crowley } 6370572080814ea5f7456d9feea05f936c858178159Paul Crowley std::string token, secret; 638a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!parse_hex(token_hex, &token)) return false; 639a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!parse_hex(secret_hex, &secret)) return false; 6400572080814ea5f7456d9feea05f936c858178159Paul Crowley android::vold::KeyAuthentication auth(token, secret); 6410572080814ea5f7456d9feea05f936c858178159Paul Crowley if (!read_and_install_user_ce_key(user_id, auth)) { 6428fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley LOG(ERROR) << "Couldn't read key for " << user_id; 64376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 644d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 645fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey } else { 646fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // When in emulation mode, we just use chmod. However, we also 647fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // unlock directories when not in emulation mode, to bring devices 648fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // back into a known-good state. 64976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) || 650df528a7011b302c91579898c4a37361214ab05bbPaul Crowley !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) || 651be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey !emulated_unlock(android::vold::BuildDataMediaCePath(nullptr, user_id), 0770) || 652be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey !emulated_unlock(android::vold::BuildDataUserCePath(nullptr, user_id), 0771)) { 6537a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey LOG(ERROR) << "Failed to unlock user " << user_id; 65476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 655fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey } 656d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 65776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 658d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 659d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 66047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// TODO: rename to 'evict' for consistency 66176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_lock_user_key(userid_t user_id) { 662fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey if (e4crypt_is_native()) { 663fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // TODO: remove from kernel keyring 664fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey } else if (e4crypt_is_emulated()) { 665d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey // When in emulation mode, we just use chmod 66676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!emulated_lock(android::vold::BuildDataSystemCePath(user_id)) || 667df528a7011b302c91579898c4a37361214ab05bbPaul Crowley !emulated_lock(android::vold::BuildDataMiscCePath(user_id)) || 668be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey !emulated_lock(android::vold::BuildDataMediaCePath(nullptr, user_id)) || 669be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey !emulated_lock(android::vold::BuildDataUserCePath(nullptr, user_id))) { 67057eedbf8cbd21899a3395ce6f153cd0e05898f3bPaul Crowley LOG(ERROR) << "Failed to lock user " << user_id; 67176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return false; 672d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 673d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 674fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey 67576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 676d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 677d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 678df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial, 679be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey int flags) { 68047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey LOG(DEBUG) << "e4crypt_prepare_user_storage for volume " << escape_null(volume_uuid) 681df528a7011b302c91579898c4a37361214ab05bbPaul Crowley << ", user " << user_id << ", serial " << serial << ", flags " << flags; 68247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 68347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (flags & FLAG_STORAGE_DE) { 684be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // DE_sys key 685be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id); 686be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id); 687be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); 688be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto foreign_de_path = android::vold::BuildDataProfilesForeignDexDePath(user_id); 689be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 690be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // DE_n key 69147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto system_de_path = android::vold::BuildDataSystemDePath(user_id); 69247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); 69347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id); 69447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 695be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false; 696be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#if MANAGE_MISC_DIRS 697be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM), 698be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey multiuser_get_uid(user_id, AID_EVERYBODY))) return false; 699be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#endif 700be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; 701be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (!prepare_dir(foreign_de_path, 0773, AID_SYSTEM, AID_SYSTEM)) return false; 702be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 70376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; 70476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false; 70576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; 706d1ee944f0839d60b014722c7facbb4a66bd4f2c3Calin Juravle 707be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // For now, FBE is only supported on internal storage 708be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (e4crypt_is_native() && volume_uuid == nullptr) { 70947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey std::string de_raw_ref; 710a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_raw_ref)) return false; 71176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(de_raw_ref, system_de_path)) return false; 71276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(de_raw_ref, misc_de_path)) return false; 71376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(de_raw_ref, user_de_path)) return false; 71447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 71547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 71647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 71747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (flags & FLAG_STORAGE_CE) { 718be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // CE_n key 71947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto system_ce_path = android::vold::BuildDataSystemCePath(user_id); 72047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); 721be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id); 722be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id); 72347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 72476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; 72576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false; 72676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false; 72776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; 72847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 729be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // For now, FBE is only supported on internal storage 730be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (e4crypt_is_native() && volume_uuid == nullptr) { 73147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey std::string ce_raw_ref; 732a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_raw_ref)) return false; 73376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(ce_raw_ref, system_ce_path)) return false; 73476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(ce_raw_ref, misc_ce_path)) return false; 73576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(ce_raw_ref, media_ce_path)) return false; 73676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley if (!ensure_policy(ce_raw_ref, user_ce_path)) return false; 737d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey 738d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey // Now that credentials have been installed, we can run restorecon 739d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey // over these paths 740d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey // NOTE: these paths need to be kept in sync with libselinux 741d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey android::vold::RestoreconRecursive(system_ce_path); 742d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey android::vold::RestoreconRecursive(misc_ce_path); 74347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 744d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 745d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 74676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley return true; 747d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 748be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 749be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeybool e4crypt_destroy_user_storage(const char* volume_uuid, userid_t user_id, int flags) { 750be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey LOG(DEBUG) << "e4crypt_destroy_user_storage for volume " << escape_null(volume_uuid) 751be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey << ", user " << user_id << ", flags " << flags; 752be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey bool res = true; 753be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 754be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (flags & FLAG_STORAGE_DE) { 755be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // DE_sys key 756be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id); 757be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id); 758be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); 759be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto foreign_de_path = android::vold::BuildDataProfilesForeignDexDePath(user_id); 760be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 761be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // DE_n key 762be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto system_de_path = android::vold::BuildDataSystemDePath(user_id); 763be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); 764be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id); 765be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 766be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (volume_uuid == nullptr) { 767be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(system_legacy_path); 768be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#if MANAGE_MISC_DIRS 769be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(misc_legacy_path); 770be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#endif 771be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(profiles_de_path); 772be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(foreign_de_path); 773be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(system_de_path); 774be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(misc_de_path); 775be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey } 776be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(user_de_path); 777be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey } 778be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 779be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (flags & FLAG_STORAGE_CE) { 780be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey // CE_n key 781be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto system_ce_path = android::vold::BuildDataSystemCePath(user_id); 782be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); 783be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id); 784be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id); 785be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 786be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey if (volume_uuid == nullptr) { 787be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(system_ce_path); 788be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(misc_ce_path); 789be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey } 790be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(media_ce_path); 791be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey res &= destroy_dir(user_ce_path); 792be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey } 793be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey 794be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey return res; 795be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey} 796