blob: 7dbdc2a5aa9c37117723921d7f574a988979459e [file] [log] [blame]
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Paul Lawrence731a7a22015-04-28 22:14:15 +000017#include "Ext4Crypt.h"
18
Paul Crowley1ef25582016-01-21 20:26:12 +000019#include "KeyStorage.h"
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080020#include "Utils.h"
21
Paul Lawrencefd7db732015-04-10 07:48:51 -070022#include <iomanip>
Paul Lawrence731a7a22015-04-28 22:14:15 +000023#include <map>
Paul Lawrencefd7db732015-04-10 07:48:51 -070024#include <string>
25#include <sstream>
Paul Lawrence731a7a22015-04-28 22:14:15 +000026
27#include <errno.h>
Paul Crowley95376d62015-05-06 15:04:43 +010028#include <dirent.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000029#include <sys/mount.h>
Paul Crowley95376d62015-05-06 15:04:43 +010030#include <sys/types.h>
31#include <sys/stat.h>
32#include <fcntl.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000033#include <cutils/properties.h>
Paul Lawrencefd7db732015-04-10 07:48:51 -070034#include <openssl/sha.h>
Jeff Sharkey7a9dd952016-01-12 16:52:16 -070035#include <selinux/android.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000036
Paul Crowley480fcd22015-08-24 14:53:28 +010037#include <private/android_filesystem_config.h>
38
Paul Lawrence731a7a22015-04-28 22:14:15 +000039#include "unencrypted_properties.h"
40#include "key_control.h"
41#include "cryptfs.h"
Paul Crowley95376d62015-05-06 15:04:43 +010042#include "ext4_crypt_init_extensions.h"
Paul Lawrence731a7a22015-04-28 22:14:15 +000043
44#define LOG_TAG "Ext4Crypt"
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080045
Jeff Sharkey7a9dd952016-01-12 16:52:16 -070046#define EMULATED_USES_SELINUX 0
47
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080048#include <cutils/fs.h>
49#include <cutils/log.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000050#include <cutils/klog.h>
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080051
Elliott Hughes7e128fb2015-12-04 15:50:53 -080052#include <android-base/file.h>
Elliott Hughes6bf05472015-12-04 17:55:33 -080053#include <android-base/logging.h>
Elliott Hughes7e128fb2015-12-04 15:50:53 -080054#include <android-base/stringprintf.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000055
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080056using android::base::StringPrintf;
57
Jeff Sharkeyfc505c32015-12-07 17:27:01 -070058static bool e4crypt_is_native() {
59 char value[PROPERTY_VALUE_MAX];
60 property_get("ro.crypto.type", value, "none");
61 return !strcmp(value, "file");
62}
63
64static bool e4crypt_is_emulated() {
65 return property_get_bool("persist.sys.emulate_fbe", false);
66}
Jeff Sharkeyc79fb892015-11-12 20:18:02 -080067
Paul Lawrence731a7a22015-04-28 22:14:15 +000068namespace {
69 // Key length in bits
70 const int key_length = 128;
Paul Lawrencefd7db732015-04-10 07:48:51 -070071 static_assert(key_length % 8 == 0,
72 "Key length must be multiple of 8 bits");
Paul Lawrence731a7a22015-04-28 22:14:15 +000073
Paul Lawrence86c942a2015-05-06 13:53:43 -070074 // How long do we store passwords for?
75 const int password_max_age_seconds = 60;
76
Paul Crowley285956f2016-01-20 13:12:38 +000077 const std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys";
78
Paul Lawrence731a7a22015-04-28 22:14:15 +000079 // How is device encrypted
80 struct keys {
81 std::string master_key;
82 std::string password;
Paul Lawrence86c942a2015-05-06 13:53:43 -070083 time_t expiry_time;
Paul Lawrence731a7a22015-04-28 22:14:15 +000084 };
85 std::map<std::string, keys> s_key_store;
Lenka Trochtova395039f2015-11-25 10:13:03 +010086 // Maps the key paths of ephemeral keys to the keys
87 std::map<std::string, std::string> s_ephemeral_user_keys;
Paul Crowley285956f2016-01-20 13:12:38 +000088 // Map user serial numbers to key references
89 std::map<int, std::string> s_key_raw_refs;
Paul Lawrence731a7a22015-04-28 22:14:15 +000090
Paul Crowley285956f2016-01-20 13:12:38 +000091 // ext4enc:TODO get this const from somewhere good
Paul Lawrencefd7db732015-04-10 07:48:51 -070092 const int EXT4_KEY_DESCRIPTOR_SIZE = 8;
93
Paul Lawrence731a7a22015-04-28 22:14:15 +000094 // ext4enc:TODO Include structure from somewhere sensible
95 // MUST be in sync with ext4_crypto.c in kernel
Paul Lawrencefd7db732015-04-10 07:48:51 -070096 const int EXT4_MAX_KEY_SIZE = 64;
97 const int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1;
Paul Lawrence731a7a22015-04-28 22:14:15 +000098 struct ext4_encryption_key {
Paul Lawrencefd7db732015-04-10 07:48:51 -070099 uint32_t mode;
100 char raw[EXT4_MAX_KEY_SIZE];
101 uint32_t size;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000102 };
103
104 namespace tag {
105 const char* magic = "magic";
106 const char* major_version = "major_version";
107 const char* minor_version = "minor_version";
108 const char* flags = "flags";
109 const char* crypt_type = "crypt_type";
110 const char* failed_decrypt_count = "failed_decrypt_count";
111 const char* crypto_type_name = "crypto_type_name";
112 const char* master_key = "master_key";
113 const char* salt = "salt";
114 const char* kdf_type = "kdf_type";
115 const char* N_factor = "N_factor";
116 const char* r_factor = "r_factor";
117 const char* p_factor = "p_factor";
118 const char* keymaster_blob = "keymaster_blob";
119 const char* scrypted_intermediate_key = "scrypted_intermediate_key";
120 }
121}
122
Paul Crowley95376d62015-05-06 15:04:43 +0100123static std::string e4crypt_install_key(const std::string &key);
Paul Crowleyf25a35a2015-05-06 13:38:53 +0100124
Paul Lawrence731a7a22015-04-28 22:14:15 +0000125static int put_crypt_ftr_and_key(const crypt_mnt_ftr& crypt_ftr,
126 UnencryptedProperties& props)
127{
128 SLOGI("Putting crypt footer");
129
130 bool success = props.Set<int>(tag::magic, crypt_ftr.magic)
131 && props.Set<int>(tag::major_version, crypt_ftr.major_version)
132 && props.Set<int>(tag::minor_version, crypt_ftr.minor_version)
133 && props.Set<int>(tag::flags, crypt_ftr.flags)
134 && props.Set<int>(tag::crypt_type, crypt_ftr.crypt_type)
135 && props.Set<int>(tag::failed_decrypt_count,
136 crypt_ftr.failed_decrypt_count)
137 && props.Set<std::string>(tag::crypto_type_name,
138 std::string(reinterpret_cast<const char*>(crypt_ftr.crypto_type_name)))
139 && props.Set<std::string>(tag::master_key,
140 std::string((const char*) crypt_ftr.master_key,
141 crypt_ftr.keysize))
142 && props.Set<std::string>(tag::salt,
143 std::string((const char*) crypt_ftr.salt,
144 SALT_LEN))
145 && props.Set<int>(tag::kdf_type, crypt_ftr.kdf_type)
146 && props.Set<int>(tag::N_factor, crypt_ftr.N_factor)
147 && props.Set<int>(tag::r_factor, crypt_ftr.r_factor)
148 && props.Set<int>(tag::p_factor, crypt_ftr.p_factor)
149 && props.Set<std::string>(tag::keymaster_blob,
150 std::string((const char*) crypt_ftr.keymaster_blob,
151 crypt_ftr.keymaster_blob_size))
152 && props.Set<std::string>(tag::scrypted_intermediate_key,
153 std::string((const char*) crypt_ftr.scrypted_intermediate_key,
154 SCRYPT_LEN));
155 return success ? 0 : -1;
156}
157
158static int get_crypt_ftr_and_key(crypt_mnt_ftr& crypt_ftr,
159 const UnencryptedProperties& props)
160{
161 memset(&crypt_ftr, 0, sizeof(crypt_ftr));
162 crypt_ftr.magic = props.Get<int>(tag::magic);
163 crypt_ftr.major_version = props.Get<int>(tag::major_version);
164 crypt_ftr.minor_version = props.Get<int>(tag::minor_version);
Paul Lawrence0d9cd9e2015-05-05 15:58:27 -0700165 crypt_ftr.ftr_size = sizeof(crypt_ftr);
Paul Lawrence731a7a22015-04-28 22:14:15 +0000166 crypt_ftr.flags = props.Get<int>(tag::flags);
167 crypt_ftr.crypt_type = props.Get<int>(tag::crypt_type);
168 crypt_ftr.failed_decrypt_count = props.Get<int>(tag::failed_decrypt_count);
169 std::string crypto_type_name = props.Get<std::string>(tag::crypto_type_name);
170 strlcpy(reinterpret_cast<char*>(crypt_ftr.crypto_type_name),
171 crypto_type_name.c_str(),
172 sizeof(crypt_ftr.crypto_type_name));
173 std::string master_key = props.Get<std::string>(tag::master_key);
174 crypt_ftr.keysize = master_key.size();
175 if (crypt_ftr.keysize > sizeof(crypt_ftr.master_key)) {
176 SLOGE("Master key size too long");
177 return -1;
178 }
179 memcpy(crypt_ftr.master_key, &master_key[0], crypt_ftr.keysize);
180 std::string salt = props.Get<std::string>(tag::salt);
181 if (salt.size() != SALT_LEN) {
182 SLOGE("Salt wrong length");
183 return -1;
184 }
185 memcpy(crypt_ftr.salt, &salt[0], SALT_LEN);
186 crypt_ftr.kdf_type = props.Get<int>(tag::kdf_type);
187 crypt_ftr.N_factor = props.Get<int>(tag::N_factor);
188 crypt_ftr.r_factor = props.Get<int>(tag::r_factor);
189 crypt_ftr.p_factor = props.Get<int>(tag::p_factor);
190 std::string keymaster_blob = props.Get<std::string>(tag::keymaster_blob);
191 crypt_ftr.keymaster_blob_size = keymaster_blob.size();
192 if (crypt_ftr.keymaster_blob_size > sizeof(crypt_ftr.keymaster_blob)) {
193 SLOGE("Keymaster blob too long");
194 return -1;
195 }
196 memcpy(crypt_ftr.keymaster_blob, &keymaster_blob[0],
197 crypt_ftr.keymaster_blob_size);
198 std::string scrypted_intermediate_key = props.Get<std::string>(tag::scrypted_intermediate_key);
199 if (scrypted_intermediate_key.size() != SCRYPT_LEN) {
200 SLOGE("scrypted intermediate key wrong length");
201 return -1;
202 }
203 memcpy(crypt_ftr.scrypted_intermediate_key, &scrypted_intermediate_key[0],
204 SCRYPT_LEN);
205
206 return 0;
207}
208
209static UnencryptedProperties GetProps(const char* path)
210{
211 return UnencryptedProperties(path);
212}
213
214static UnencryptedProperties GetAltProps(const char* path)
215{
216 return UnencryptedProperties((std::string() + path + "/tmp_mnt").c_str());
217}
218
219static UnencryptedProperties GetPropsOrAltProps(const char* path)
220{
221 UnencryptedProperties props = GetProps(path);
222 if (props.OK()) {
223 return props;
224 }
225 return GetAltProps(path);
226}
227
228int e4crypt_enable(const char* path)
229{
230 // Already enabled?
231 if (s_key_store.find(path) != s_key_store.end()) {
232 return 0;
233 }
234
235 // Not an encryptable device?
236 UnencryptedProperties key_props = GetProps(path).GetChild(properties::key);
237 if (!key_props.OK()) {
238 return 0;
239 }
240
241 if (key_props.Get<std::string>(tag::master_key).empty()) {
242 crypt_mnt_ftr ftr;
243 if (cryptfs_create_default_ftr(&ftr, key_length)) {
244 SLOGE("Failed to create crypto footer");
245 return -1;
246 }
247
Paul Lawrence0d9cd9e2015-05-05 15:58:27 -0700248 // Scrub fields not used by ext4enc
249 ftr.persist_data_offset[0] = 0;
250 ftr.persist_data_offset[1] = 0;
251 ftr.persist_data_size = 0;
252
Paul Lawrence731a7a22015-04-28 22:14:15 +0000253 if (put_crypt_ftr_and_key(ftr, key_props)) {
254 SLOGE("Failed to write crypto footer");
255 return -1;
256 }
257
258 crypt_mnt_ftr ftr2;
259 if (get_crypt_ftr_and_key(ftr2, key_props)) {
260 SLOGE("Failed to read crypto footer back");
261 return -1;
262 }
263
264 if (memcmp(&ftr, &ftr2, sizeof(ftr)) != 0) {
265 SLOGE("Crypto footer not correctly written");
Paul Lawrence0d9cd9e2015-05-05 15:58:27 -0700266 return -1;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000267 }
268 }
269
270 if (!UnencryptedProperties(path).Remove(properties::ref)) {
271 SLOGE("Failed to remove key ref");
272 return -1;
273 }
274
275 return e4crypt_check_passwd(path, "");
276}
277
278int e4crypt_change_password(const char* path, int crypt_type,
279 const char* password)
280{
281 SLOGI("e4crypt_change_password");
Paul Lawrencea56d3132015-05-04 15:48:24 -0700282 auto key_props = GetProps(path).GetChild(properties::key);
Paul Lawrence731a7a22015-04-28 22:14:15 +0000283
284 crypt_mnt_ftr ftr;
285 if (get_crypt_ftr_and_key(ftr, key_props)) {
286 SLOGE("Failed to read crypto footer back");
287 return -1;
288 }
289
290 auto mki = s_key_store.find(path);
291 if (mki == s_key_store.end()) {
292 SLOGE("No stored master key - can't change password");
293 return -1;
294 }
295
Paul Crowley95376d62015-05-06 15:04:43 +0100296 const unsigned char* master_key_bytes
Paul Lawrence731a7a22015-04-28 22:14:15 +0000297 = reinterpret_cast<const unsigned char*>(&mki->second.master_key[0]);
298
Paul Crowley95376d62015-05-06 15:04:43 +0100299 if (cryptfs_set_password(&ftr, password, master_key_bytes)) {
Paul Lawrence731a7a22015-04-28 22:14:15 +0000300 SLOGE("Failed to set password");
301 return -1;
302 }
303
304 ftr.crypt_type = crypt_type;
305
306 if (put_crypt_ftr_and_key(ftr, key_props)) {
307 SLOGE("Failed to write crypto footer");
308 return -1;
309 }
310
311 if (!UnencryptedProperties(path).Set(properties::is_default,
312 crypt_type == CRYPT_TYPE_DEFAULT)) {
313 SLOGE("Failed to update default flag");
314 return -1;
315 }
316
317 return 0;
318}
319
320int e4crypt_crypto_complete(const char* path)
321{
322 SLOGI("ext4 crypto complete called on %s", path);
Paul Lawrencea56d3132015-05-04 15:48:24 -0700323 auto key_props = GetPropsOrAltProps(path).GetChild(properties::key);
Paul Lawrence731a7a22015-04-28 22:14:15 +0000324 if (key_props.Get<std::string>(tag::master_key).empty()) {
325 SLOGI("No master key, so not ext4enc");
326 return -1;
327 }
328
329 return 0;
330}
331
Paul Crowley93363482015-07-07 15:17:22 +0100332// Get raw keyref - used to make keyname and to pass to ioctl
Paul Lawrencefd7db732015-04-10 07:48:51 -0700333static std::string generate_key_ref(const char* key, int length)
334{
335 SHA512_CTX c;
336
337 SHA512_Init(&c);
338 SHA512_Update(&c, key, length);
Paul Crowley285956f2016-01-20 13:12:38 +0000339 unsigned char key_ref1[SHA512_DIGEST_LENGTH];
Paul Lawrencefd7db732015-04-10 07:48:51 -0700340 SHA512_Final(key_ref1, &c);
341
342 SHA512_Init(&c);
Paul Crowley285956f2016-01-20 13:12:38 +0000343 SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
344 unsigned char key_ref2[SHA512_DIGEST_LENGTH];
Paul Lawrencefd7db732015-04-10 07:48:51 -0700345 SHA512_Final(key_ref2, &c);
346
347 return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE);
348}
349
Paul Lawrence731a7a22015-04-28 22:14:15 +0000350int e4crypt_check_passwd(const char* path, const char* password)
351{
352 SLOGI("e4crypt_check_password");
Paul Lawrencea56d3132015-05-04 15:48:24 -0700353 auto props = GetPropsOrAltProps(path);
354 auto key_props = props.GetChild(properties::key);
Paul Lawrence731a7a22015-04-28 22:14:15 +0000355
356 crypt_mnt_ftr ftr;
357 if (get_crypt_ftr_and_key(ftr, key_props)) {
358 SLOGE("Failed to read crypto footer back");
359 return -1;
360 }
361
Paul Crowley95376d62015-05-06 15:04:43 +0100362 unsigned char master_key_bytes[key_length / 8];
363 if (cryptfs_get_master_key (&ftr, password, master_key_bytes)){
Paul Lawrence731a7a22015-04-28 22:14:15 +0000364 SLOGI("Incorrect password");
Paul Lawrencec78c71b2015-04-14 15:26:29 -0700365 ftr.failed_decrypt_count++;
366 if (put_crypt_ftr_and_key(ftr, key_props)) {
367 SLOGW("Failed to update failed_decrypt_count");
368 }
369 return ftr.failed_decrypt_count;
370 }
371
372 if (ftr.failed_decrypt_count) {
373 ftr.failed_decrypt_count = 0;
374 if (put_crypt_ftr_and_key(ftr, key_props)) {
375 SLOGW("Failed to reset failed_decrypt_count");
376 }
Paul Lawrence731a7a22015-04-28 22:14:15 +0000377 }
Paul Crowley95376d62015-05-06 15:04:43 +0100378 std::string master_key(reinterpret_cast<char*>(master_key_bytes),
379 sizeof(master_key_bytes));
Paul Lawrence731a7a22015-04-28 22:14:15 +0000380
Paul Lawrence86c942a2015-05-06 13:53:43 -0700381 struct timespec now;
382 clock_gettime(CLOCK_BOOTTIME, &now);
Paul Crowley95376d62015-05-06 15:04:43 +0100383 s_key_store[path] = keys{master_key, password,
Paul Lawrence86c942a2015-05-06 13:53:43 -0700384 now.tv_sec + password_max_age_seconds};
Paul Crowleyf25a35a2015-05-06 13:38:53 +0100385 auto raw_ref = e4crypt_install_key(master_key);
386 if (raw_ref.empty()) {
387 return -1;
388 }
Paul Lawrence731a7a22015-04-28 22:14:15 +0000389
Paul Crowleyf25a35a2015-05-06 13:38:53 +0100390 // Save reference to key so we can set policy later
391 if (!props.Set(properties::ref, raw_ref)) {
392 SLOGE("Cannot save key reference");
393 return -1;
394 }
395
396 return 0;
397}
398
Paul Crowley93363482015-07-07 15:17:22 +0100399static ext4_encryption_key fill_key(const std::string &key)
Paul Crowleyf25a35a2015-05-06 13:38:53 +0100400{
Paul Lawrencefd7db732015-04-10 07:48:51 -0700401 // ext4enc:TODO Currently raw key is required to be of length
402 // sizeof(ext4_key.raw) == EXT4_MAX_KEY_SIZE, so zero pad to
403 // this length. Change when kernel bug is fixed.
404 ext4_encryption_key ext4_key = {EXT4_ENCRYPTION_MODE_AES_256_XTS,
405 {0},
406 sizeof(ext4_key.raw)};
407 memset(ext4_key.raw, 0, sizeof(ext4_key.raw));
408 static_assert(key_length / 8 <= sizeof(ext4_key.raw),
409 "Key too long!");
Paul Crowley95376d62015-05-06 15:04:43 +0100410 memcpy(ext4_key.raw, &key[0], key.size());
Paul Crowley93363482015-07-07 15:17:22 +0100411 return ext4_key;
412}
Paul Lawrence731a7a22015-04-28 22:14:15 +0000413
Paul Crowley93363482015-07-07 15:17:22 +0100414static std::string keyname(const std::string &raw_ref)
415{
Paul Lawrencefd7db732015-04-10 07:48:51 -0700416 std::ostringstream o;
Paul Crowley93363482015-07-07 15:17:22 +0100417 o << "ext4:";
Paul Lawrencefd7db732015-04-10 07:48:51 -0700418 for (auto i = raw_ref.begin(); i != raw_ref.end(); ++i) {
419 o << std::hex << std::setw(2) << std::setfill('0') << (int)*i;
420 }
Paul Crowley93363482015-07-07 15:17:22 +0100421 return o.str();
422}
Paul Lawrencefd7db732015-04-10 07:48:51 -0700423
Paul Crowley93363482015-07-07 15:17:22 +0100424// Get the keyring we store all keys in
425static key_serial_t e4crypt_keyring()
426{
427 return keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "e4crypt", 0);
428}
Paul Lawrence731a7a22015-04-28 22:14:15 +0000429
Paul Crowley93363482015-07-07 15:17:22 +0100430static int e4crypt_install_key(const ext4_encryption_key &ext4_key, const std::string &ref)
431{
432 key_serial_t device_keyring = e4crypt_keyring();
Paul Lawrencefd7db732015-04-10 07:48:51 -0700433 key_serial_t key_id = add_key("logon", ref.c_str(),
Paul Lawrence731a7a22015-04-28 22:14:15 +0000434 (void*)&ext4_key, sizeof(ext4_key),
435 device_keyring);
Paul Lawrence731a7a22015-04-28 22:14:15 +0000436 if (key_id == -1) {
Paul Crowley285956f2016-01-20 13:12:38 +0000437 PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
Paul Crowley93363482015-07-07 15:17:22 +0100438 return -1;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000439 }
Paul Crowley285956f2016-01-20 13:12:38 +0000440 LOG(INFO) << "Added key " << key_id << " (" << ref << ") to keyring "
441 << device_keyring << " in process " << getpid();
Paul Crowley93363482015-07-07 15:17:22 +0100442 return 0;
443}
Paul Lawrence731a7a22015-04-28 22:14:15 +0000444
Paul Crowley93363482015-07-07 15:17:22 +0100445// Install password into global keyring
446// Return raw key reference for use in policy
447static std::string e4crypt_install_key(const std::string &key)
448{
449 auto ext4_key = fill_key(key);
450 auto raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size);
451 auto ref = keyname(raw_ref);
452 if (e4crypt_install_key(ext4_key, ref) == -1) {
453 return "";
454 }
Paul Crowleyf25a35a2015-05-06 13:38:53 +0100455 return raw_ref;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000456}
457
458int e4crypt_restart(const char* path)
459{
460 SLOGI("e4crypt_restart");
461
462 int rc = 0;
463
464 SLOGI("ext4 restart called on %s", path);
465 property_set("vold.decrypt", "trigger_reset_main");
466 SLOGI("Just asked init to shut down class main");
467 sleep(2);
468
469 std::string tmp_path = std::string() + path + "/tmp_mnt";
470
Paul Lawrence2f32cda2015-05-05 14:28:25 -0700471 rc = wait_and_unmount(tmp_path.c_str(), true);
Paul Lawrence731a7a22015-04-28 22:14:15 +0000472 if (rc) {
473 SLOGE("umount %s failed with rc %d, msg %s",
474 tmp_path.c_str(), rc, strerror(errno));
475 return rc;
476 }
477
Paul Lawrence2f32cda2015-05-05 14:28:25 -0700478 rc = wait_and_unmount(path, true);
Paul Lawrence731a7a22015-04-28 22:14:15 +0000479 if (rc) {
480 SLOGE("umount %s failed with rc %d, msg %s",
481 path, rc, strerror(errno));
482 return rc;
483 }
484
485 return 0;
486}
487
Paul Lawrence731a7a22015-04-28 22:14:15 +0000488int e4crypt_get_password_type(const char* path)
489{
490 SLOGI("e4crypt_get_password_type");
491 return GetPropsOrAltProps(path).GetChild(properties::key)
492 .Get<int>(tag::crypt_type, CRYPT_TYPE_DEFAULT);
493}
Paul Lawrence368d7942015-04-15 14:12:00 -0700494
Paul Lawrence86c942a2015-05-06 13:53:43 -0700495const char* e4crypt_get_password(const char* path)
496{
497 SLOGI("e4crypt_get_password");
498
499 auto i = s_key_store.find(path);
500 if (i == s_key_store.end()) {
501 return 0;
502 }
503
504 struct timespec now;
505 clock_gettime(CLOCK_BOOTTIME, &now);
506 if (i->second.expiry_time < now.tv_sec) {
507 e4crypt_clear_password(path);
508 return 0;
509 }
510
511 return i->second.password.c_str();
512}
513
514void e4crypt_clear_password(const char* path)
515{
516 SLOGI("e4crypt_clear_password");
517
518 auto i = s_key_store.find(path);
519 if (i == s_key_store.end()) {
520 return;
521 }
522
523 memset(&i->second.password[0], 0, i->second.password.size());
524 i->second.password = std::string();
525}
526
Paul Lawrence368d7942015-04-15 14:12:00 -0700527int e4crypt_get_field(const char* path, const char* fieldname,
528 char* value, size_t len)
529{
530 auto v = GetPropsOrAltProps(path).GetChild(properties::props)
531 .Get<std::string>(fieldname);
532
533 if (v == "") {
534 return CRYPTO_GETFIELD_ERROR_NO_FIELD;
535 }
536
537 if (v.length() >= len) {
538 return CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
539 }
540
541 strlcpy(value, v.c_str(), len);
542 return 0;
543}
544
545int e4crypt_set_field(const char* path, const char* fieldname,
546 const char* value)
547{
548 return GetPropsOrAltProps(path).GetChild(properties::props)
549 .Set(fieldname, std::string(value)) ? 0 : -1;
550}
Paul Crowley95376d62015-05-06 15:04:43 +0100551
Paul Crowley285956f2016-01-20 13:12:38 +0000552static std::string get_key_path(userid_t user_id) {
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000553 return StringPrintf("%s/user_%d/current", user_key_dir.c_str(), user_id);
Paul Crowleyb33e8872015-05-19 12:34:09 +0100554}
555
Lenka Trochtova395039f2015-11-25 10:13:03 +0100556static bool e4crypt_is_key_ephemeral(const std::string &key_path) {
557 return s_ephemeral_user_keys.find(key_path) != s_ephemeral_user_keys.end();
558}
559
Paul Crowley1ef25582016-01-21 20:26:12 +0000560static bool read_user_key(userid_t user_id, std::string &key)
Paul Crowleyb33e8872015-05-19 12:34:09 +0100561{
Paul Crowley285956f2016-01-20 13:12:38 +0000562 const auto key_path = get_key_path(user_id);
Lenka Trochtova395039f2015-11-25 10:13:03 +0100563 const auto ephemeral_key_it = s_ephemeral_user_keys.find(key_path);
564 if (ephemeral_key_it != s_ephemeral_user_keys.end()) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000565 key = ephemeral_key_it->second;
566 return true;
Lenka Trochtova395039f2015-11-25 10:13:03 +0100567 }
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000568 if (!android::vold::retrieveKey(key_path, key)) return false;
Paul Crowley1ef25582016-01-21 20:26:12 +0000569 if (key.size() != key_length/8) {
570 LOG(ERROR) << "Wrong size key " << key.size() << " in " << key_path;
571 return false;
Paul Crowley95376d62015-05-06 15:04:43 +0100572 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000573 return true;
Paul Crowley285956f2016-01-20 13:12:38 +0000574}
575
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000576static bool prepare_dir(const std::string &dir, mode_t mode, uid_t uid, gid_t gid) {
577 if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
578 PLOG(ERROR) << "Failed to prepare " << dir;
Paul Crowley285956f2016-01-20 13:12:38 +0000579 return false;
580 }
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000581 return true;
582}
583
584static bool create_user_key(userid_t user_id, bool create_ephemeral) {
Paul Crowley285956f2016-01-20 13:12:38 +0000585 const auto key_path = get_key_path(user_id);
Paul Crowley1ef25582016-01-21 20:26:12 +0000586 std::string key;
587 if (android::vold::ReadRandomBytes(key_length / 8, key) != 0) {
588 // TODO status_t plays badly with PLOG, fix it.
589 LOG(ERROR) << "Random read failed";
Paul Crowley285956f2016-01-20 13:12:38 +0000590 return false;
591 }
Lenka Trochtova395039f2015-11-25 10:13:03 +0100592 if (create_ephemeral) {
593 // If the key should be created as ephemeral, store it in memory only.
594 s_ephemeral_user_keys[key_path] = key;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000595 } else {
596 if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false;
597 if (!prepare_dir(user_key_dir + "/user_" + std::to_string(user_id),
598 0700, AID_ROOT, AID_ROOT)) return false;
599 if (!android::vold::storeKey(key_path, key)) return false;
Paul Crowley95376d62015-05-06 15:04:43 +0100600 }
Paul Crowley285956f2016-01-20 13:12:38 +0000601 LOG(DEBUG) << "Created key " << key_path;
Paul Crowley95376d62015-05-06 15:04:43 +0100602 return true;
603}
604
Paul Crowley285956f2016-01-20 13:12:38 +0000605static int e4crypt_set_user_policy(userid_t user_id, int serial, std::string& path) {
606 LOG(DEBUG) << "e4crypt_set_user_policy for " << user_id << " serial " << serial;
607 if (s_key_raw_refs.count(serial) != 1) {
608 LOG(ERROR) << "Key unknown, can't e4crypt_set_user_policy for "
609 << user_id << " serial " << serial;
Paul Crowley95376d62015-05-06 15:04:43 +0100610 return -1;
611 }
Paul Crowley285956f2016-01-20 13:12:38 +0000612 auto raw_ref = s_key_raw_refs[serial];
613 return do_policy_set(path.c_str(), raw_ref.data(), raw_ref.size());
Paul Crowley95376d62015-05-06 15:04:43 +0100614}
Paul Crowleyb33e8872015-05-19 12:34:09 +0100615
Paul Crowley27cbce92015-12-10 14:51:30 +0000616int e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
Paul Crowley285956f2016-01-20 13:12:38 +0000617 LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial;
Paul Crowley1ef25582016-01-21 20:26:12 +0000618 std::string key;
619 if (read_user_key(user_id, key)) {
Paul Crowley285956f2016-01-20 13:12:38 +0000620 LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for "
621 << user_id << " serial " << serial;
622 // FIXME should we fail the command?
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800623 return 0;
624 }
Paul Crowley285956f2016-01-20 13:12:38 +0000625 if (!create_user_key(user_id, ephemeral)) {
626 return -1;
627 }
628 if (e4crypt_unlock_user_key(user_id, serial, nullptr) != 0) {
629 return -1;
630 }
631 // TODO: create second key for user_de data
632 return 0;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800633}
634
Paul Crowley1ef25582016-01-21 20:26:12 +0000635static bool evict_user_key(userid_t user_id) {
Paul Crowley285956f2016-01-20 13:12:38 +0000636 auto key_path = get_key_path(user_id);
Paul Crowley1ef25582016-01-21 20:26:12 +0000637 std::string key;
638 if (!read_user_key(user_id, key)) return false;
Paul Crowley93363482015-07-07 15:17:22 +0100639 auto ext4_key = fill_key(key);
640 auto ref = keyname(generate_key_ref(ext4_key.raw, ext4_key.size));
641 auto key_serial = keyctl_search(e4crypt_keyring(), "logon", ref.c_str(), 0);
Paul Crowley1ef25582016-01-21 20:26:12 +0000642 if (keyctl_revoke(key_serial) != 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000643 PLOG(ERROR) << "Failed to revoke key with serial " << key_serial << " ref " << ref;
Paul Crowley1ef25582016-01-21 20:26:12 +0000644 return false;
Paul Crowley93363482015-07-07 15:17:22 +0100645 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000646 LOG(DEBUG) << "Revoked key with serial " << key_serial << " ref " << ref;
647 return true;
648}
649
650int e4crypt_destroy_user_key(userid_t user_id) {
651 LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")";
652 // TODO: destroy second key for user_de data
653 bool evict_success = evict_user_key(user_id);
654 auto key_path = get_key_path(user_id);
Lenka Trochtova395039f2015-11-25 10:13:03 +0100655 if (e4crypt_is_key_ephemeral(key_path)) {
656 s_ephemeral_user_keys.erase(key_path);
Paul Crowley1ef25582016-01-21 20:26:12 +0000657 } else {
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000658 if (!android::vold::destroyKey(key_path)) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000659 return -1;
660 }
Lenka Trochtova395039f2015-11-25 10:13:03 +0100661 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000662 return evict_success ? 0 : -1;
Paul Crowleyb33e8872015-05-19 12:34:09 +0100663}
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800664
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700665static int emulated_lock(const std::string& path) {
666 if (chmod(path.c_str(), 0000) != 0) {
667 PLOG(ERROR) << "Failed to chmod " << path;
668 return -1;
669 }
670#if EMULATED_USES_SELINUX
671 if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
672 PLOG(WARNING) << "Failed to setfilecon " << path;
673 return -1;
674 }
675#endif
676 return 0;
677}
678
679static int emulated_unlock(const std::string& path, mode_t mode) {
680 if (chmod(path.c_str(), mode) != 0) {
681 PLOG(ERROR) << "Failed to chmod " << path;
Paul Crowleya042cb52016-01-21 17:24:49 +0000682 // FIXME temporary workaround for b/26713622
683 if (e4crypt_is_emulated()) return -1;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700684 }
685#if EMULATED_USES_SELINUX
686 if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
687 PLOG(WARNING) << "Failed to restorecon " << path;
Paul Crowleya042cb52016-01-21 17:24:49 +0000688 // FIXME temporary workaround for b/26713622
689 if (e4crypt_is_emulated()) return -1;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700690 }
691#endif
692 return 0;
693}
694
Paul Crowley285956f2016-01-20 13:12:38 +0000695int e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token) {
696 LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " " << (token != nullptr);
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700697 if (e4crypt_is_native()) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000698 std::string user_key;
699 if (!read_user_key(user_id, user_key)) {
Paul Crowley285956f2016-01-20 13:12:38 +0000700 // FIXME special case for user 0
701 if (user_id != 0) {
702 LOG(ERROR) << "Couldn't read key for " << user_id;
703 return -1;
704 }
705 // FIXME if the key exists and we just failed to read it, this destroys it.
706 if (!create_user_key(user_id, false)) {
707 return -1;
708 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000709 if (!read_user_key(user_id, user_key)) {
Paul Crowley285956f2016-01-20 13:12:38 +0000710 LOG(ERROR) << "Couldn't read just-created key for " << user_id;
711 return -1;
712 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800713 }
714 auto raw_ref = e4crypt_install_key(user_key);
715 if (raw_ref.empty()) {
716 return -1;
717 }
Paul Crowley285956f2016-01-20 13:12:38 +0000718 s_key_raw_refs[serial] = raw_ref;
719 if (user_id == 0) {
720 // FIXME special case for user 0
721 // prepare their storage here
722 e4crypt_prepare_user_storage(nullptr, 0, 0, false);
723 }
724 return 0;
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700725 } else {
726 // When in emulation mode, we just use chmod. However, we also
727 // unlock directories when not in emulation mode, to bring devices
728 // back into a known-good state.
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700729 if (emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
730 emulated_unlock(android::vold::BuildDataMediaPath(nullptr, user_id), 0770) ||
731 emulated_unlock(android::vold::BuildDataUserPath(nullptr, user_id), 0771)) {
732 LOG(ERROR) << "Failed to unlock user " << user_id;
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700733 return -1;
734 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800735 }
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700736
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800737 return 0;
738}
739
740int e4crypt_lock_user_key(userid_t user_id) {
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700741 if (e4crypt_is_native()) {
742 // TODO: remove from kernel keyring
743 } else if (e4crypt_is_emulated()) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800744 // When in emulation mode, we just use chmod
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700745 if (emulated_lock(android::vold::BuildDataSystemCePath(user_id)) ||
746 emulated_lock(android::vold::BuildDataMediaPath(nullptr, user_id)) ||
747 emulated_lock(android::vold::BuildDataUserPath(nullptr, user_id))) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800748 PLOG(ERROR) << "Failed to lock user " << user_id;
749 return -1;
750 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800751 }
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700752
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800753 return 0;
754}
755
Lenka Trochtova9ad43692015-12-11 13:27:26 +0100756int e4crypt_prepare_user_storage(const char* volume_uuid,
757 userid_t user_id,
758 int serial,
759 bool ephemeral) {
Paul Crowley285956f2016-01-20 13:12:38 +0000760 if (volume_uuid) {
761 LOG(DEBUG) << "e4crypt_prepare_user_storage " << volume_uuid << " " << user_id;
762 } else {
763 LOG(DEBUG) << "e4crypt_prepare_user_storage, null volume " << user_id;
764 }
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000765 auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
766 auto media_ce_path = android::vold::BuildDataMediaPath(volume_uuid, user_id);
767 auto user_ce_path = android::vold::BuildDataUserPath(volume_uuid, user_id);
768 auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800769
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000770 if (!prepare_dir(system_ce_path, 0700, AID_SYSTEM, AID_SYSTEM)) return -1;
771 if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return -1;
772 if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return -1;
773 if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return -1;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800774
775 if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000776 if (e4crypt_set_user_policy(user_id, serial, system_ce_path)
777 || e4crypt_set_user_policy(user_id, serial, media_ce_path)
778 || e4crypt_set_user_policy(user_id, serial, user_ce_path)) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800779 return -1;
780 }
781 }
782
783 return 0;
784}