Ext4Crypt.cpp revision 1ef255816c50e462acc23383a9ff747c5f55c4ff
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 22fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <iomanip> 23731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <map> 24fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <string> 25fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <sstream> 26731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 27731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <errno.h> 2895376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <dirent.h> 29731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <sys/mount.h> 3095376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <sys/types.h> 3195376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <sys/stat.h> 3295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <fcntl.h> 33731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <cutils/properties.h> 34fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <openssl/sha.h> 357a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#include <selinux/android.h> 36731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 37480fcd2750c1d30f3397d1f3152519a11f60990bPaul Crowley#include <private/android_filesystem_config.h> 38480fcd2750c1d30f3397d1f3152519a11f60990bPaul Crowley 39731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "unencrypted_properties.h" 40731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "key_control.h" 41731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "cryptfs.h" 4295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include "ext4_crypt_init_extensions.h" 43731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 44731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#define LOG_TAG "Ext4Crypt" 45d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 467a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#define EMULATED_USES_SELINUX 0 477a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey 48d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include <cutils/fs.h> 49d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include <cutils/log.h> 50731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <cutils/klog.h> 51d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 527e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/file.h> 536bf0547ccce72233bd465178b919fa7f15e48b45Elliott Hughes#include <android-base/logging.h> 547e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/stringprintf.h> 55731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 56d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeyusing android::base::StringPrintf; 57d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 58fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkeystatic bool e4crypt_is_native() { 59fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey char value[PROPERTY_VALUE_MAX]; 60fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey property_get("ro.crypto.type", value, "none"); 61fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey return !strcmp(value, "file"); 62fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey} 63fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey 64fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkeystatic bool e4crypt_is_emulated() { 65fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey return property_get_bool("persist.sys.emulate_fbe", false); 66fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey} 67c79fb89a10ea9bc3b0f1f9c7caa809a705989479Jeff Sharkey 68731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencenamespace { 69731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence // Key length in bits 70731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const int key_length = 128; 71fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence static_assert(key_length % 8 == 0, 72fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence "Key length must be multiple of 8 bits"); 73731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 7486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence // How long do we store passwords for? 7586c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence const int password_max_age_seconds = 60; 7686c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence 77285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley const std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys"; 78285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley 79731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence // How is device encrypted 80731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence struct keys { 81731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string master_key; 82731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string password; 8386c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence time_t expiry_time; 84731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence }; 85731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::map<std::string, keys> s_key_store; 86395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova // Maps the key paths of ephemeral keys to the keys 87395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova std::map<std::string, std::string> s_ephemeral_user_keys; 88285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // Map user serial numbers to key references 89285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley std::map<int, std::string> s_key_raw_refs; 90731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 91285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // ext4enc:TODO get this const from somewhere good 92fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence const int EXT4_KEY_DESCRIPTOR_SIZE = 8; 93fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 94731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence // ext4enc:TODO Include structure from somewhere sensible 95731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence // MUST be in sync with ext4_crypto.c in kernel 96fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence const int EXT4_MAX_KEY_SIZE = 64; 97fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence const int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1; 98731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence struct ext4_encryption_key { 99fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence uint32_t mode; 100fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence char raw[EXT4_MAX_KEY_SIZE]; 101fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence uint32_t size; 102731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence }; 103731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 104731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence namespace tag { 105731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* magic = "magic"; 106731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* major_version = "major_version"; 107731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* minor_version = "minor_version"; 108731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* flags = "flags"; 109731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* crypt_type = "crypt_type"; 110731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* failed_decrypt_count = "failed_decrypt_count"; 111731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* crypto_type_name = "crypto_type_name"; 112731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* master_key = "master_key"; 113731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* salt = "salt"; 114731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* kdf_type = "kdf_type"; 115731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* N_factor = "N_factor"; 116731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* r_factor = "r_factor"; 117731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* p_factor = "p_factor"; 118731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* keymaster_blob = "keymaster_blob"; 119731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* scrypted_intermediate_key = "scrypted_intermediate_key"; 120731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 121731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 122731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 12395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowleystatic std::string e4crypt_install_key(const std::string &key); 124f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley 125731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic int put_crypt_ftr_and_key(const crypt_mnt_ftr& crypt_ftr, 126731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence UnencryptedProperties& props) 127731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 128731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("Putting crypt footer"); 129731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 130731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence bool success = props.Set<int>(tag::magic, crypt_ftr.magic) 131731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<int>(tag::major_version, crypt_ftr.major_version) 132731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<int>(tag::minor_version, crypt_ftr.minor_version) 133731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<int>(tag::flags, crypt_ftr.flags) 134731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<int>(tag::crypt_type, crypt_ftr.crypt_type) 135731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<int>(tag::failed_decrypt_count, 136731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.failed_decrypt_count) 137731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<std::string>(tag::crypto_type_name, 138731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string(reinterpret_cast<const char*>(crypt_ftr.crypto_type_name))) 139731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<std::string>(tag::master_key, 140731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string((const char*) crypt_ftr.master_key, 141731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.keysize)) 142731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<std::string>(tag::salt, 143731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string((const char*) crypt_ftr.salt, 144731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SALT_LEN)) 145731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<int>(tag::kdf_type, crypt_ftr.kdf_type) 146731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<int>(tag::N_factor, crypt_ftr.N_factor) 147731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<int>(tag::r_factor, crypt_ftr.r_factor) 148731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<int>(tag::p_factor, crypt_ftr.p_factor) 149731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<std::string>(tag::keymaster_blob, 150731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string((const char*) crypt_ftr.keymaster_blob, 151731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.keymaster_blob_size)) 152731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence && props.Set<std::string>(tag::scrypted_intermediate_key, 153731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string((const char*) crypt_ftr.scrypted_intermediate_key, 154731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SCRYPT_LEN)); 155731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return success ? 0 : -1; 156731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 157731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 158731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic int get_crypt_ftr_and_key(crypt_mnt_ftr& crypt_ftr, 159731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const UnencryptedProperties& props) 160731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 161731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence memset(&crypt_ftr, 0, sizeof(crypt_ftr)); 162731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.magic = props.Get<int>(tag::magic); 163731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.major_version = props.Get<int>(tag::major_version); 164731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.minor_version = props.Get<int>(tag::minor_version); 1650d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence crypt_ftr.ftr_size = sizeof(crypt_ftr); 166731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.flags = props.Get<int>(tag::flags); 167731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.crypt_type = props.Get<int>(tag::crypt_type); 168731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.failed_decrypt_count = props.Get<int>(tag::failed_decrypt_count); 169731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string crypto_type_name = props.Get<std::string>(tag::crypto_type_name); 170731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence strlcpy(reinterpret_cast<char*>(crypt_ftr.crypto_type_name), 171731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypto_type_name.c_str(), 172731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence sizeof(crypt_ftr.crypto_type_name)); 173731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string master_key = props.Get<std::string>(tag::master_key); 174731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.keysize = master_key.size(); 175731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (crypt_ftr.keysize > sizeof(crypt_ftr.master_key)) { 176731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Master key size too long"); 177731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 178731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 179731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence memcpy(crypt_ftr.master_key, &master_key[0], crypt_ftr.keysize); 180731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string salt = props.Get<std::string>(tag::salt); 181731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (salt.size() != SALT_LEN) { 182731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Salt wrong length"); 183731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 184731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 185731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence memcpy(crypt_ftr.salt, &salt[0], SALT_LEN); 186731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.kdf_type = props.Get<int>(tag::kdf_type); 187731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.N_factor = props.Get<int>(tag::N_factor); 188731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.r_factor = props.Get<int>(tag::r_factor); 189731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.p_factor = props.Get<int>(tag::p_factor); 190731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string keymaster_blob = props.Get<std::string>(tag::keymaster_blob); 191731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.keymaster_blob_size = keymaster_blob.size(); 192731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (crypt_ftr.keymaster_blob_size > sizeof(crypt_ftr.keymaster_blob)) { 193731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Keymaster blob too long"); 194731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 195731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 196731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence memcpy(crypt_ftr.keymaster_blob, &keymaster_blob[0], 197731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_ftr.keymaster_blob_size); 198731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string scrypted_intermediate_key = props.Get<std::string>(tag::scrypted_intermediate_key); 199731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (scrypted_intermediate_key.size() != SCRYPT_LEN) { 200731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("scrypted intermediate key wrong length"); 201731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 202731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 203731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence memcpy(crypt_ftr.scrypted_intermediate_key, &scrypted_intermediate_key[0], 204731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SCRYPT_LEN); 205731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 206731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return 0; 207731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 208731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 209731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic UnencryptedProperties GetProps(const char* path) 210731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 211731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return UnencryptedProperties(path); 212731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 213731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 214731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic UnencryptedProperties GetAltProps(const char* path) 215731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 216731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return UnencryptedProperties((std::string() + path + "/tmp_mnt").c_str()); 217731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 218731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 219731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencestatic UnencryptedProperties GetPropsOrAltProps(const char* path) 220731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 221731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence UnencryptedProperties props = GetProps(path); 222731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (props.OK()) { 223731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return props; 224731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 225731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return GetAltProps(path); 226731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 227731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 228731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_enable(const char* path) 229731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 230731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence // Already enabled? 231731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (s_key_store.find(path) != s_key_store.end()) { 232731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return 0; 233731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 234731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 235731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence // Not an encryptable device? 236731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence UnencryptedProperties key_props = GetProps(path).GetChild(properties::key); 237731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (!key_props.OK()) { 238731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return 0; 239731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 240731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 241731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (key_props.Get<std::string>(tag::master_key).empty()) { 242731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_mnt_ftr ftr; 243731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (cryptfs_create_default_ftr(&ftr, key_length)) { 244731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Failed to create crypto footer"); 245731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 246731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 247731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 2480d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence // Scrub fields not used by ext4enc 2490d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence ftr.persist_data_offset[0] = 0; 2500d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence ftr.persist_data_offset[1] = 0; 2510d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence ftr.persist_data_size = 0; 2520d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence 253731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (put_crypt_ftr_and_key(ftr, key_props)) { 254731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Failed to write crypto footer"); 255731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 256731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 257731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 258731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_mnt_ftr ftr2; 259731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (get_crypt_ftr_and_key(ftr2, key_props)) { 260731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Failed to read crypto footer back"); 261731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 262731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 263731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 264731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (memcmp(&ftr, &ftr2, sizeof(ftr)) != 0) { 265731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Crypto footer not correctly written"); 2660d9cd9e9cf39e1cdb06565de6c4e11ff244b2a3aPaul Lawrence return -1; 267731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 268731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 269731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 270731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (!UnencryptedProperties(path).Remove(properties::ref)) { 271731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Failed to remove key ref"); 272731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 273731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 274731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 275731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return e4crypt_check_passwd(path, ""); 276731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 277731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 278731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_change_password(const char* path, int crypt_type, 279731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence const char* password) 280731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 281731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("e4crypt_change_password"); 282a56d3134b03a3756a740aa909aa3d72643196842Paul Lawrence auto key_props = GetProps(path).GetChild(properties::key); 283731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 284731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_mnt_ftr ftr; 285731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (get_crypt_ftr_and_key(ftr, key_props)) { 286731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Failed to read crypto footer back"); 287731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 288731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 289731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 290731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence auto mki = s_key_store.find(path); 291731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (mki == s_key_store.end()) { 292731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("No stored master key - can't change password"); 293731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 294731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 295731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 29695376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley const unsigned char* master_key_bytes 297731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence = reinterpret_cast<const unsigned char*>(&mki->second.master_key[0]); 298731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 29995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley if (cryptfs_set_password(&ftr, password, master_key_bytes)) { 300731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Failed to set password"); 301731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 302731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 303731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 304731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence ftr.crypt_type = crypt_type; 305731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 306731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (put_crypt_ftr_and_key(ftr, key_props)) { 307731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Failed to write crypto footer"); 308731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 309731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 310731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 311731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (!UnencryptedProperties(path).Set(properties::is_default, 312731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_type == CRYPT_TYPE_DEFAULT)) { 313731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Failed to update default flag"); 314731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 315731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 316731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 317731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return 0; 318731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 319731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 320731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_crypto_complete(const char* path) 321731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 322731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("ext4 crypto complete called on %s", path); 323a56d3134b03a3756a740aa909aa3d72643196842Paul Lawrence auto key_props = GetPropsOrAltProps(path).GetChild(properties::key); 324731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (key_props.Get<std::string>(tag::master_key).empty()) { 325731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("No master key, so not ext4enc"); 326731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 327731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 328731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 329731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return 0; 330731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 331731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 3329336348200758d067fed164368636521b4e58621Paul Crowley// Get raw keyref - used to make keyname and to pass to ioctl 333fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrencestatic std::string generate_key_ref(const char* key, int length) 334fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence{ 335fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_CTX c; 336fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 337fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Init(&c); 338fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Update(&c, key, length); 339285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley unsigned char key_ref1[SHA512_DIGEST_LENGTH]; 340fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Final(key_ref1, &c); 341fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 342fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Init(&c); 343285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH); 344285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley unsigned char key_ref2[SHA512_DIGEST_LENGTH]; 345fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence SHA512_Final(key_ref2, &c); 346fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 347fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE); 348fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence} 349fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 350731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_check_passwd(const char* path, const char* password) 351731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 352731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("e4crypt_check_password"); 353a56d3134b03a3756a740aa909aa3d72643196842Paul Lawrence auto props = GetPropsOrAltProps(path); 354a56d3134b03a3756a740aa909aa3d72643196842Paul Lawrence auto key_props = props.GetChild(properties::key); 355731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 356731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence crypt_mnt_ftr ftr; 357731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (get_crypt_ftr_and_key(ftr, key_props)) { 358731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("Failed to read crypto footer back"); 359731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return -1; 360731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 361731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 36295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley unsigned char master_key_bytes[key_length / 8]; 36395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley if (cryptfs_get_master_key (&ftr, password, master_key_bytes)){ 364731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("Incorrect password"); 365c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence ftr.failed_decrypt_count++; 366c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence if (put_crypt_ftr_and_key(ftr, key_props)) { 367c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence SLOGW("Failed to update failed_decrypt_count"); 368c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence } 369c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence return ftr.failed_decrypt_count; 370c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence } 371c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence 372c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence if (ftr.failed_decrypt_count) { 373c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence ftr.failed_decrypt_count = 0; 374c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence if (put_crypt_ftr_and_key(ftr, key_props)) { 375c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence SLOGW("Failed to reset failed_decrypt_count"); 376c78c71b1717613a5be921bbb8ac63c007d4af86aPaul Lawrence } 377731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 37895376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley std::string master_key(reinterpret_cast<char*>(master_key_bytes), 37995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley sizeof(master_key_bytes)); 380731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 38186c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence struct timespec now; 38286c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence clock_gettime(CLOCK_BOOTTIME, &now); 38395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley s_key_store[path] = keys{master_key, password, 38486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence now.tv_sec + password_max_age_seconds}; 385f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley auto raw_ref = e4crypt_install_key(master_key); 386f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley if (raw_ref.empty()) { 387f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley return -1; 388f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley } 389731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 390f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley // Save reference to key so we can set policy later 391f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley if (!props.Set(properties::ref, raw_ref)) { 392f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley SLOGE("Cannot save key reference"); 393f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley return -1; 394f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley } 395f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley 396f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley return 0; 397f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley} 398f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley 3999336348200758d067fed164368636521b4e58621Paul Crowleystatic ext4_encryption_key fill_key(const std::string &key) 400f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley{ 401fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence // ext4enc:TODO Currently raw key is required to be of length 402fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence // sizeof(ext4_key.raw) == EXT4_MAX_KEY_SIZE, so zero pad to 403fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence // this length. Change when kernel bug is fixed. 404fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence ext4_encryption_key ext4_key = {EXT4_ENCRYPTION_MODE_AES_256_XTS, 405fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence {0}, 406fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence sizeof(ext4_key.raw)}; 407fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence memset(ext4_key.raw, 0, sizeof(ext4_key.raw)); 408fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence static_assert(key_length / 8 <= sizeof(ext4_key.raw), 409fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence "Key too long!"); 41095376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley memcpy(ext4_key.raw, &key[0], key.size()); 4119336348200758d067fed164368636521b4e58621Paul Crowley return ext4_key; 4129336348200758d067fed164368636521b4e58621Paul Crowley} 413fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence 4149336348200758d067fed164368636521b4e58621Paul Crowleystatic std::string keyname(const std::string &raw_ref) 4159336348200758d067fed164368636521b4e58621Paul Crowley{ 416fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence std::ostringstream o; 4179336348200758d067fed164368636521b4e58621Paul Crowley o << "ext4:"; 418fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence for (auto i = raw_ref.begin(); i != raw_ref.end(); ++i) { 419fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence o << std::hex << std::setw(2) << std::setfill('0') << (int)*i; 420fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence } 4219336348200758d067fed164368636521b4e58621Paul Crowley return o.str(); 4229336348200758d067fed164368636521b4e58621Paul Crowley} 423731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 4249336348200758d067fed164368636521b4e58621Paul Crowley// Get the keyring we store all keys in 4259336348200758d067fed164368636521b4e58621Paul Crowleystatic key_serial_t e4crypt_keyring() 4269336348200758d067fed164368636521b4e58621Paul Crowley{ 4279336348200758d067fed164368636521b4e58621Paul Crowley return keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "e4crypt", 0); 4289336348200758d067fed164368636521b4e58621Paul Crowley} 429731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 4309336348200758d067fed164368636521b4e58621Paul Crowleystatic int e4crypt_install_key(const ext4_encryption_key &ext4_key, const std::string &ref) 4319336348200758d067fed164368636521b4e58621Paul Crowley{ 4329336348200758d067fed164368636521b4e58621Paul Crowley key_serial_t device_keyring = e4crypt_keyring(); 433fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence key_serial_t key_id = add_key("logon", ref.c_str(), 434731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence (void*)&ext4_key, sizeof(ext4_key), 435731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence device_keyring); 436731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (key_id == -1) { 437285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring; 4389336348200758d067fed164368636521b4e58621Paul Crowley return -1; 439731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 440285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(INFO) << "Added key " << key_id << " (" << ref << ") to keyring " 441285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley << device_keyring << " in process " << getpid(); 4429336348200758d067fed164368636521b4e58621Paul Crowley return 0; 4439336348200758d067fed164368636521b4e58621Paul Crowley} 444731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 4459336348200758d067fed164368636521b4e58621Paul Crowley// Install password into global keyring 4469336348200758d067fed164368636521b4e58621Paul Crowley// Return raw key reference for use in policy 4479336348200758d067fed164368636521b4e58621Paul Crowleystatic std::string e4crypt_install_key(const std::string &key) 4489336348200758d067fed164368636521b4e58621Paul Crowley{ 4499336348200758d067fed164368636521b4e58621Paul Crowley auto ext4_key = fill_key(key); 4509336348200758d067fed164368636521b4e58621Paul Crowley auto raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size); 4519336348200758d067fed164368636521b4e58621Paul Crowley auto ref = keyname(raw_ref); 4529336348200758d067fed164368636521b4e58621Paul Crowley if (e4crypt_install_key(ext4_key, ref) == -1) { 4539336348200758d067fed164368636521b4e58621Paul Crowley return ""; 4549336348200758d067fed164368636521b4e58621Paul Crowley } 455f25a35a1c98d4fac118ee9abe34d6bbf2d3a2201Paul Crowley return raw_ref; 456731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 457731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 458731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceint e4crypt_restart(const char* path) 459731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 460731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("e4crypt_restart"); 461731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 462731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence int rc = 0; 463731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 464731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("ext4 restart called on %s", path); 465731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence property_set("vold.decrypt", "trigger_reset_main"); 466731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("Just asked init to shut down class main"); 467731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence sleep(2); 468731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 469731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence std::string tmp_path = std::string() + path + "/tmp_mnt"; 470731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 4712f32cda63bf5c86db880d36029a27c8597fb5e3cPaul Lawrence rc = wait_and_unmount(tmp_path.c_str(), true); 472731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (rc) { 473731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("umount %s failed with rc %d, msg %s", 474731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence tmp_path.c_str(), rc, strerror(errno)); 475731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return rc; 476731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 477731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 4782f32cda63bf5c86db880d36029a27c8597fb5e3cPaul Lawrence rc = wait_and_unmount(path, true); 479731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (rc) { 480731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGE("umount %s failed with rc %d, msg %s", 481731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence path, rc, strerror(errno)); 482731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return rc; 483731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 484731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 485731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return 0; 486731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 487731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 48886c942a2537701a90b88768eab4648c0650dfad1Paul Lawrenceint e4crypt_get_password_type(const char* path) 48986c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence{ 49086c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence SLOGI("e4crypt_get_password_type"); 49186c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence return GetPropsOrAltProps(path).GetChild(properties::key) 49286c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence .Get<int>(tag::crypt_type, CRYPT_TYPE_DEFAULT); 49386c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence} 49486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence 495731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrenceconst char* e4crypt_get_password(const char* path) 496731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 497731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence SLOGI("e4crypt_get_password"); 498731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 499731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence auto i = s_key_store.find(path); 500731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence if (i == s_key_store.end()) { 501731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence return 0; 502731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence } 50386c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence 50486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence struct timespec now; 50586c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence clock_gettime(CLOCK_BOOTTIME, &now); 50686c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence if (i->second.expiry_time < now.tv_sec) { 50786c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence e4crypt_clear_password(path); 50886c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence return 0; 50986c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence } 51086c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence 51186c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence return i->second.password.c_str(); 512731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 513731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence 51486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrencevoid e4crypt_clear_password(const char* path) 515731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence{ 51686c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence SLOGI("e4crypt_clear_password"); 51786c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence 51886c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence auto i = s_key_store.find(path); 51986c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence if (i == s_key_store.end()) { 52086c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence return; 52186c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence } 52286c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence 52386c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence memset(&i->second.password[0], 0, i->second.password.size()); 52486c942a2537701a90b88768eab4648c0650dfad1Paul Lawrence i->second.password = std::string(); 525731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence} 526368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence 527368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrenceint e4crypt_get_field(const char* path, const char* fieldname, 528368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence char* value, size_t len) 529368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence{ 530368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence auto v = GetPropsOrAltProps(path).GetChild(properties::props) 531368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence .Get<std::string>(fieldname); 532368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence 533368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence if (v == "") { 534368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence return CRYPTO_GETFIELD_ERROR_NO_FIELD; 535368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence } 536368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence 537368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence if (v.length() >= len) { 538368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence return CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL; 539368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence } 540368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence 541368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence strlcpy(value, v.c_str(), len); 542368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence return 0; 543368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence} 544368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence 545368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrenceint e4crypt_set_field(const char* path, const char* fieldname, 546368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence const char* value) 547368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence{ 548368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence return GetPropsOrAltProps(path).GetChild(properties::props) 549368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence .Set(fieldname, std::string(value)) ? 0 : -1; 550368d79459e8d30474dd5cbc414623c1e2f78ee98Paul Lawrence} 55195376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley 552285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleystatic std::string get_key_path(userid_t user_id) { 553285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return StringPrintf("%s/%d", user_key_dir.c_str(), user_id); 554b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley} 555b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley 556395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtovastatic bool e4crypt_is_key_ephemeral(const std::string &key_path) { 557395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova return s_ephemeral_user_keys.find(key_path) != s_ephemeral_user_keys.end(); 558395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova} 559395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova 5601ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowleystatic bool read_user_key(userid_t user_id, std::string &key) 561b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley{ 562285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley const auto key_path = get_key_path(user_id); 563395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova const auto ephemeral_key_it = s_ephemeral_user_keys.find(key_path); 564395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova if (ephemeral_key_it != s_ephemeral_user_keys.end()) { 5651ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley key = ephemeral_key_it->second; 5661ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley return true; 567395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova } 5681ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley if (!android::vold::RetrieveKey(key_path, key)) return false; 5691ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley if (key.size() != key_length/8) { 5701ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley LOG(ERROR) << "Wrong size key " << key.size() << " in " << key_path; 5711ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley return false; 57295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 5731ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley return true; 574285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley} 575285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley 576285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleystatic bool create_user_key(userid_t user_id, bool create_ephemeral) { 577285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley if (fs_prepare_dir(user_key_dir.c_str(), 0700, AID_ROOT, AID_ROOT)) { 578285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley PLOG(ERROR) << "Failed to prepare " << user_key_dir; 579285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return false; 580285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } 581285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley const auto key_path = get_key_path(user_id); 5821ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley std::string key; 5831ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley if (android::vold::ReadRandomBytes(key_length / 8, key) != 0) { 5841ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley // TODO status_t plays badly with PLOG, fix it. 5851ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley LOG(ERROR) << "Random read failed"; 586285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return false; 587285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } 588395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova if (create_ephemeral) { 589395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova // If the key should be created as ephemeral, store it in memory only. 590395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova s_ephemeral_user_keys[key_path] = key; 5911ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley } else if (!android::vold::StoreKey(key_path, key)) { 592285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return false; 59395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 594285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(DEBUG) << "Created key " << key_path; 595285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return true; 59695376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley} 59795376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley 598285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleystatic int e4crypt_set_user_policy(userid_t user_id, int serial, std::string& path) { 599285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(DEBUG) << "e4crypt_set_user_policy for " << user_id << " serial " << serial; 600285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley if (s_key_raw_refs.count(serial) != 1) { 601285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(ERROR) << "Key unknown, can't e4crypt_set_user_policy for " 602285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley << user_id << " serial " << serial; 60395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley return -1; 60495376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 605285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley auto raw_ref = s_key_raw_refs[serial]; 606285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return do_policy_set(path.c_str(), raw_ref.data(), raw_ref.size()); 60795376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley} 60895376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley 609285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleyint e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) { 610285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial; 6111ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley std::string key; 6121ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley if (read_user_key(user_id, key)) { 613285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for " 614285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley << user_id << " serial " << serial; 615285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // FIXME should we fail the command? 61695376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley return 0; 61795376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 618285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley if (!create_user_key(user_id, ephemeral)) { 61995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley return -1; 62095376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley } 621285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley if (e4crypt_unlock_user_key(user_id, serial, nullptr) != 0) { 622d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return -1; 623d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 624285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // TODO: create second key for user_de data 625285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return 0; 626d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 627d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 6281ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowleystatic bool evict_user_key(userid_t user_id) { 629285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley auto key_path = get_key_path(user_id); 6301ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley std::string key; 6311ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley if (!read_user_key(user_id, key)) return false; 6329336348200758d067fed164368636521b4e58621Paul Crowley auto ext4_key = fill_key(key); 6339336348200758d067fed164368636521b4e58621Paul Crowley auto ref = keyname(generate_key_ref(ext4_key.raw, ext4_key.size)); 6349336348200758d067fed164368636521b4e58621Paul Crowley auto key_serial = keyctl_search(e4crypt_keyring(), "logon", ref.c_str(), 0); 6351ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley if (keyctl_revoke(key_serial) != 0) { 636285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley PLOG(ERROR) << "Failed to revoke key with serial " << key_serial << " ref " << ref; 6371ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley return false; 6389336348200758d067fed164368636521b4e58621Paul Crowley } 6391ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley LOG(DEBUG) << "Revoked key with serial " << key_serial << " ref " << ref; 6401ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley return true; 6411ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley} 6421ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley 6431ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowleyint e4crypt_destroy_user_key(userid_t user_id) { 6441ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")"; 6451ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley // TODO: destroy second key for user_de data 6461ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley bool evict_success = evict_user_key(user_id); 6471ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley auto key_path = get_key_path(user_id); 648395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova if (e4crypt_is_key_ephemeral(key_path)) { 649395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova s_ephemeral_user_keys.erase(key_path); 6501ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley } else { 6511ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley if (!android::vold::DestroyKey(key_path)) { 6521ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley return -1; 6531ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley } 654b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley } 6551ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley return evict_success ? 0 : -1; 656b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley} 657d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 6587a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkeystatic int emulated_lock(const std::string& path) { 6597a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (chmod(path.c_str(), 0000) != 0) { 6607a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(ERROR) << "Failed to chmod " << path; 6617a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey return -1; 6627a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 6637a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX 6647a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) { 6657a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(WARNING) << "Failed to setfilecon " << path; 6667a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey return -1; 6677a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 6687a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif 6697a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey return 0; 6707a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey} 6717a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey 6727a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkeystatic int emulated_unlock(const std::string& path, mode_t mode) { 6737a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (chmod(path.c_str(), mode) != 0) { 6747a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(ERROR) << "Failed to chmod " << path; 675a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley // FIXME temporary workaround for b/26713622 676a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley if (e4crypt_is_emulated()) return -1; 6777a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 6787a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX 6797a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) { 6807a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey PLOG(WARNING) << "Failed to restorecon " << path; 681a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley // FIXME temporary workaround for b/26713622 682a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley if (e4crypt_is_emulated()) return -1; 6837a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey } 6847a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif 6857a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey return 0; 6867a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey} 6877a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey 688285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowleyint e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token) { 689285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " " << (token != nullptr); 690fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey if (e4crypt_is_native()) { 6911ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley std::string user_key; 6921ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley if (!read_user_key(user_id, user_key)) { 693285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // FIXME special case for user 0 694285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley if (user_id != 0) { 695285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(ERROR) << "Couldn't read key for " << user_id; 696285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return -1; 697285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } 698285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // FIXME if the key exists and we just failed to read it, this destroys it. 699285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley if (!create_user_key(user_id, false)) { 700285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return -1; 701285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } 7021ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley if (!read_user_key(user_id, user_key)) { 703285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(ERROR) << "Couldn't read just-created key for " << user_id; 704285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return -1; 705285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } 706d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 707d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey auto raw_ref = e4crypt_install_key(user_key); 708d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey if (raw_ref.empty()) { 709d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return -1; 710d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 711285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley s_key_raw_refs[serial] = raw_ref; 712285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley if (user_id == 0) { 713285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // FIXME special case for user 0 714285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley // prepare their storage here 715285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley e4crypt_prepare_user_storage(nullptr, 0, 0, false); 716285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } 717285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley return 0; 718fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey } else { 719fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // When in emulation mode, we just use chmod. However, we also 720fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // unlock directories when not in emulation mode, to bring devices 721fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // back into a known-good state. 7227a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) || 7237a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey emulated_unlock(android::vold::BuildDataMediaPath(nullptr, user_id), 0770) || 7247a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey emulated_unlock(android::vold::BuildDataUserPath(nullptr, user_id), 0771)) { 7257a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey LOG(ERROR) << "Failed to unlock user " << user_id; 726fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey return -1; 727fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey } 728d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 729fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey 730d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return 0; 731d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 732d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 733d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeyint e4crypt_lock_user_key(userid_t user_id) { 734fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey if (e4crypt_is_native()) { 735fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey // TODO: remove from kernel keyring 736fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey } else if (e4crypt_is_emulated()) { 737d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey // When in emulation mode, we just use chmod 7387a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey if (emulated_lock(android::vold::BuildDataSystemCePath(user_id)) || 7397a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey emulated_lock(android::vold::BuildDataMediaPath(nullptr, user_id)) || 7407a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey emulated_lock(android::vold::BuildDataUserPath(nullptr, user_id))) { 741d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey PLOG(ERROR) << "Failed to lock user " << user_id; 742d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return -1; 743d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 744d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 745fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey 746d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return 0; 747d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 748d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 7499ad4369ce87cb445ea126a8a803e2b42c2c5ea2fLenka Trochtovaint e4crypt_prepare_user_storage(const char* volume_uuid, 7509ad4369ce87cb445ea126a8a803e2b42c2c5ea2fLenka Trochtova userid_t user_id, 7519ad4369ce87cb445ea126a8a803e2b42c2c5ea2fLenka Trochtova int serial, 7529ad4369ce87cb445ea126a8a803e2b42c2c5ea2fLenka Trochtova bool ephemeral) { 753285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley if (volume_uuid) { 754285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(DEBUG) << "e4crypt_prepare_user_storage " << volume_uuid << " " << user_id; 755285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } else { 756285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley LOG(DEBUG) << "e4crypt_prepare_user_storage, null volume " << user_id; 757285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley } 758d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey std::string system_ce_path(android::vold::BuildDataSystemCePath(user_id)); 759d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey std::string media_ce_path(android::vold::BuildDataMediaPath(volume_uuid, user_id)); 760d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey std::string user_ce_path(android::vold::BuildDataUserPath(volume_uuid, user_id)); 761d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey std::string user_de_path(android::vold::BuildDataUserDePath(volume_uuid, user_id)); 762d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 763d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey if (fs_prepare_dir(system_ce_path.c_str(), 0700, AID_SYSTEM, AID_SYSTEM)) { 764d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey PLOG(ERROR) << "Failed to prepare " << system_ce_path; 765d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return -1; 766d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 767d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey if (fs_prepare_dir(media_ce_path.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW)) { 768d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey PLOG(ERROR) << "Failed to prepare " << media_ce_path; 769d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey return -1; 770d2d7bffd0c666bd3dc67364b36480e57a1913571Jeff Sharkey } 771d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey if (fs_prepare_dir(user_ce_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM)) { 772d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey PLOG(ERROR) << "Failed to prepare " << user_ce_path; 773d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return -1; 774d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 775d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey if (fs_prepare_dir(user_de_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM)) { 776d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey PLOG(ERROR) << "Failed to prepare " << user_de_path; 777d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return -1; 778d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 779d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 780d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) { 781285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley if (e4crypt_set_user_policy(user_id, serial, system_ce_path) 782285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley || e4crypt_set_user_policy(user_id, serial, media_ce_path) 783285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley || e4crypt_set_user_policy(user_id, serial, user_ce_path)) { 784d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return -1; 785d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 786d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey } 787d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey 788d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey return 0; 789d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey} 790