1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "KeyUtil.h" 18 19 #include <iomanip> 20 #include <sstream> 21 #include <string> 22 23 #include <openssl/sha.h> 24 25 #include <android-base/file.h> 26 #include <android-base/logging.h> 27 #include <keyutils.h> 28 29 #include "KeyStorage.h" 30 #include "Utils.h" 31 32 namespace android { 33 namespace vold { 34 35 // ext4enc:TODO get this const from somewhere good 36 const int EXT4_KEY_DESCRIPTOR_SIZE = 8; 37 38 // ext4enc:TODO Include structure from somewhere sensible 39 // MUST be in sync with ext4_crypto.c in kernel 40 constexpr int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1; 41 constexpr int EXT4_AES_256_XTS_KEY_SIZE = 64; 42 constexpr int EXT4_MAX_KEY_SIZE = 64; 43 struct ext4_encryption_key { 44 uint32_t mode; 45 char raw[EXT4_MAX_KEY_SIZE]; 46 uint32_t size; 47 }; 48 49 bool randomKey(KeyBuffer* key) { 50 *key = KeyBuffer(EXT4_AES_256_XTS_KEY_SIZE); 51 if (ReadRandomBytes(key->size(), key->data()) != 0) { 52 // TODO status_t plays badly with PLOG, fix it. 53 LOG(ERROR) << "Random read failed"; 54 return false; 55 } 56 return true; 57 } 58 59 // Get raw keyref - used to make keyname and to pass to ioctl 60 static std::string generateKeyRef(const char* key, int length) { 61 SHA512_CTX c; 62 63 SHA512_Init(&c); 64 SHA512_Update(&c, key, length); 65 unsigned char key_ref1[SHA512_DIGEST_LENGTH]; 66 SHA512_Final(key_ref1, &c); 67 68 SHA512_Init(&c); 69 SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH); 70 unsigned char key_ref2[SHA512_DIGEST_LENGTH]; 71 SHA512_Final(key_ref2, &c); 72 73 static_assert(EXT4_KEY_DESCRIPTOR_SIZE <= SHA512_DIGEST_LENGTH, 74 "Hash too short for descriptor"); 75 return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE); 76 } 77 78 static bool fillKey(const KeyBuffer& key, ext4_encryption_key* ext4_key) { 79 if (key.size() != EXT4_AES_256_XTS_KEY_SIZE) { 80 LOG(ERROR) << "Wrong size key " << key.size(); 81 return false; 82 } 83 static_assert(EXT4_AES_256_XTS_KEY_SIZE <= sizeof(ext4_key->raw), "Key too long!"); 84 ext4_key->mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; 85 ext4_key->size = key.size(); 86 memset(ext4_key->raw, 0, sizeof(ext4_key->raw)); 87 memcpy(ext4_key->raw, key.data(), key.size()); 88 return true; 89 } 90 91 static char const* const NAME_PREFIXES[] = { 92 "ext4", 93 "f2fs", 94 "fscrypt", 95 nullptr 96 }; 97 98 static std::string keyname(const std::string& prefix, const std::string& raw_ref) { 99 std::ostringstream o; 100 o << prefix << ":"; 101 for (unsigned char i : raw_ref) { 102 o << std::hex << std::setw(2) << std::setfill('0') << (int)i; 103 } 104 return o.str(); 105 } 106 107 // Get the keyring we store all keys in 108 static bool e4cryptKeyring(key_serial_t* device_keyring) { 109 *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "e4crypt", 0); 110 if (*device_keyring == -1) { 111 PLOG(ERROR) << "Unable to find device keyring"; 112 return false; 113 } 114 return true; 115 } 116 117 // Install password into global keyring 118 // Return raw key reference for use in policy 119 bool installKey(const KeyBuffer& key, std::string* raw_ref) { 120 // Place ext4_encryption_key into automatically zeroing buffer. 121 KeyBuffer ext4KeyBuffer(sizeof(ext4_encryption_key)); 122 ext4_encryption_key &ext4_key = *reinterpret_cast<ext4_encryption_key*>(ext4KeyBuffer.data()); 123 124 if (!fillKey(key, &ext4_key)) return false; 125 *raw_ref = generateKeyRef(ext4_key.raw, ext4_key.size); 126 key_serial_t device_keyring; 127 if (!e4cryptKeyring(&device_keyring)) return false; 128 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) { 129 auto ref = keyname(*name_prefix, *raw_ref); 130 key_serial_t key_id = 131 add_key("logon", ref.c_str(), (void*)&ext4_key, sizeof(ext4_key), device_keyring); 132 if (key_id == -1) { 133 PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring; 134 return false; 135 } 136 LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring 137 << " in process " << getpid(); 138 } 139 return true; 140 } 141 142 bool evictKey(const std::string& raw_ref) { 143 key_serial_t device_keyring; 144 if (!e4cryptKeyring(&device_keyring)) return false; 145 bool success = true; 146 for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) { 147 auto ref = keyname(*name_prefix, raw_ref); 148 auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0); 149 150 // Unlink the key from the keyring. Prefer unlinking to revoking or 151 // invalidating, since unlinking is actually no less secure currently, and 152 // it avoids bugs in certain kernel versions where the keyring key is 153 // referenced from places it shouldn't be. 154 if (keyctl_unlink(key_serial, device_keyring) != 0) { 155 PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref; 156 success = false; 157 } else { 158 LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref; 159 } 160 } 161 return success; 162 } 163 164 bool retrieveAndInstallKey(bool create_if_absent, const KeyAuthentication& key_authentication, 165 const std::string& key_path, const std::string& tmp_path, 166 std::string* key_ref) { 167 KeyBuffer key; 168 if (pathExists(key_path)) { 169 LOG(DEBUG) << "Key exists, using: " << key_path; 170 if (!retrieveKey(key_path, key_authentication, &key)) return false; 171 } else { 172 if (!create_if_absent) { 173 LOG(ERROR) << "No key found in " << key_path; 174 return false; 175 } 176 LOG(INFO) << "Creating new key in " << key_path; 177 if (!randomKey(&key)) return false; 178 if (!storeKeyAtomically(key_path, tmp_path, key_authentication, key)) return false; 179 } 180 181 if (!installKey(key, key_ref)) { 182 LOG(ERROR) << "Failed to install key in " << key_path; 183 return false; 184 } 185 return true; 186 } 187 188 bool retrieveKey(bool create_if_absent, const std::string& key_path, 189 const std::string& tmp_path, KeyBuffer* key) { 190 if (pathExists(key_path)) { 191 LOG(DEBUG) << "Key exists, using: " << key_path; 192 if (!retrieveKey(key_path, kEmptyAuthentication, key)) return false; 193 } else { 194 if (!create_if_absent) { 195 LOG(ERROR) << "No key found in " << key_path; 196 return false; 197 } 198 LOG(INFO) << "Creating new key in " << key_path; 199 if (!randomKey(key)) return false; 200 if (!storeKeyAtomically(key_path, tmp_path, 201 kEmptyAuthentication, *key)) return false; 202 } 203 return true; 204 } 205 206 } // namespace vold 207 } // namespace android 208