blob: 5523363ec95b6144d261b9c1f52a1af987b42aa6 [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
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080019#include "Utils.h"
20
Paul Lawrencefd7db732015-04-10 07:48:51 -070021#include <iomanip>
Paul Lawrence731a7a22015-04-28 22:14:15 +000022#include <map>
Paul Lawrencefd7db732015-04-10 07:48:51 -070023#include <fstream>
24#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) {
553 return StringPrintf("%s/%d", 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 Crowley285956f2016-01-20 13:12:38 +0000560static std::string read_user_key(userid_t user_id)
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()) {
565 return ephemeral_key_it->second;
566 }
567
Paul Crowley95376d62015-05-06 15:04:43 +0100568 std::string content;
Paul Crowley285956f2016-01-20 13:12:38 +0000569 if (!android::base::ReadFileToString(key_path, &content)) {
Paul Crowley95376d62015-05-06 15:04:43 +0100570 return "";
571 }
Paul Crowley285956f2016-01-20 13:12:38 +0000572 if (content.size() != key_length/8) {
573 LOG(ERROR) << "Wrong size key " << content.size() << " in " << key_path;
574 return "";
575 }
576 return content;
577}
578
579// ext4enc:TODO this can't be the only place keys are read from /dev/urandom
580// we should unite those places.
581static std::string get_random_string(size_t length) {
Paul Crowley95376d62015-05-06 15:04:43 +0100582 std::ifstream urandom("/dev/urandom");
583 if (!urandom) {
Paul Crowley285956f2016-01-20 13:12:38 +0000584 PLOG(ERROR) << "Unable to open /dev/urandom";
Paul Crowley95376d62015-05-06 15:04:43 +0100585 return "";
586 }
Paul Crowley285956f2016-01-20 13:12:38 +0000587 std::string res(length, '\0');
588 urandom.read(&res[0], length);
Paul Crowley95376d62015-05-06 15:04:43 +0100589 if (!urandom) {
Paul Crowley285956f2016-01-20 13:12:38 +0000590 PLOG(ERROR) << "Unable to read from /dev/urandom";
Paul Crowley95376d62015-05-06 15:04:43 +0100591 return "";
592 }
Paul Crowley285956f2016-01-20 13:12:38 +0000593 return res;
594}
595
596static bool create_user_key(userid_t user_id, bool create_ephemeral) {
597 if (fs_prepare_dir(user_key_dir.c_str(), 0700, AID_ROOT, AID_ROOT)) {
598 PLOG(ERROR) << "Failed to prepare " << user_key_dir;
599 return false;
600 }
601 const auto key_path = get_key_path(user_id);
602 auto key = get_random_string(key_length / 8);
603 if (key.empty()) {
604 return false;
605 }
Lenka Trochtova395039f2015-11-25 10:13:03 +0100606 if (create_ephemeral) {
607 // If the key should be created as ephemeral, store it in memory only.
608 s_ephemeral_user_keys[key_path] = key;
609 } else if (!android::base::WriteStringToFile(key, key_path)) {
Paul Crowley285956f2016-01-20 13:12:38 +0000610 PLOG(ERROR) << "Unable to write key to " << key_path;
611 return false;
Paul Crowley95376d62015-05-06 15:04:43 +0100612 }
Paul Crowley285956f2016-01-20 13:12:38 +0000613 LOG(DEBUG) << "Created key " << key_path;
Paul Crowley95376d62015-05-06 15:04:43 +0100614 return true;
615}
616
Paul Crowley285956f2016-01-20 13:12:38 +0000617static int e4crypt_set_user_policy(userid_t user_id, int serial, std::string& path) {
618 LOG(DEBUG) << "e4crypt_set_user_policy for " << user_id << " serial " << serial;
619 if (s_key_raw_refs.count(serial) != 1) {
620 LOG(ERROR) << "Key unknown, can't e4crypt_set_user_policy for "
621 << user_id << " serial " << serial;
Paul Crowley95376d62015-05-06 15:04:43 +0100622 return -1;
623 }
Paul Crowley285956f2016-01-20 13:12:38 +0000624 auto raw_ref = s_key_raw_refs[serial];
625 return do_policy_set(path.c_str(), raw_ref.data(), raw_ref.size());
Paul Crowley95376d62015-05-06 15:04:43 +0100626}
Paul Crowleyb33e8872015-05-19 12:34:09 +0100627
Paul Crowley27cbce92015-12-10 14:51:30 +0000628int e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
Paul Crowley285956f2016-01-20 13:12:38 +0000629 LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial;
630 if (!read_user_key(user_id).empty()) {
631 LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for "
632 << user_id << " serial " << serial;
633 // FIXME should we fail the command?
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800634 return 0;
635 }
Paul Crowley285956f2016-01-20 13:12:38 +0000636 if (!create_user_key(user_id, ephemeral)) {
637 return -1;
638 }
639 if (e4crypt_unlock_user_key(user_id, serial, nullptr) != 0) {
640 return -1;
641 }
642 // TODO: create second key for user_de data
643 return 0;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800644}
645
646int e4crypt_destroy_user_key(userid_t user_id) {
Paul Crowley285956f2016-01-20 13:12:38 +0000647 LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")";
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800648 // TODO: destroy second key for user_de data
Paul Crowley285956f2016-01-20 13:12:38 +0000649 auto key_path = get_key_path(user_id);
650 auto key = read_user_key(user_id);
Paul Crowley93363482015-07-07 15:17:22 +0100651 auto ext4_key = fill_key(key);
652 auto ref = keyname(generate_key_ref(ext4_key.raw, ext4_key.size));
653 auto key_serial = keyctl_search(e4crypt_keyring(), "logon", ref.c_str(), 0);
654 if (keyctl_revoke(key_serial) == 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000655 LOG(DEBUG) << "Revoked key with serial " << key_serial << " ref " << ref;
Paul Crowley93363482015-07-07 15:17:22 +0100656 } else {
Paul Crowley285956f2016-01-20 13:12:38 +0000657 PLOG(ERROR) << "Failed to revoke key with serial " << key_serial << " ref " << ref;
Paul Crowley93363482015-07-07 15:17:22 +0100658 }
Lenka Trochtova395039f2015-11-25 10:13:03 +0100659 if (e4crypt_is_key_ephemeral(key_path)) {
660 s_ephemeral_user_keys.erase(key_path);
661 return 0;
662 }
Paul Crowleycd307b72015-05-19 17:31:39 +0100663 int pid = fork();
664 if (pid < 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000665 PLOG(ERROR) << "Unable to fork";
Paul Crowleyb33e8872015-05-19 12:34:09 +0100666 return -1;
667 }
Paul Crowleycd307b72015-05-19 17:31:39 +0100668 if (pid == 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000669 LOG(DEBUG) << "Forked for secdiscard";
Paul Crowleycd307b72015-05-19 17:31:39 +0100670 execl("/system/bin/secdiscard",
671 "/system/bin/secdiscard",
Paul Crowley5ab73e92015-07-03 16:17:23 +0100672 "--",
Paul Crowleycd307b72015-05-19 17:31:39 +0100673 key_path.c_str(),
674 NULL);
Paul Crowley285956f2016-01-20 13:12:38 +0000675 PLOG(ERROR) << "Unable to launch secdiscard on " << key_path;
Paul Crowleycd307b72015-05-19 17:31:39 +0100676 exit(-1);
677 }
678 // ext4enc:TODO reap the zombie
Paul Crowleyb33e8872015-05-19 12:34:09 +0100679 return 0;
680}
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800681
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700682static int emulated_lock(const std::string& path) {
683 if (chmod(path.c_str(), 0000) != 0) {
684 PLOG(ERROR) << "Failed to chmod " << path;
685 return -1;
686 }
687#if EMULATED_USES_SELINUX
688 if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
689 PLOG(WARNING) << "Failed to setfilecon " << path;
690 return -1;
691 }
692#endif
693 return 0;
694}
695
696static int emulated_unlock(const std::string& path, mode_t mode) {
697 if (chmod(path.c_str(), mode) != 0) {
698 PLOG(ERROR) << "Failed to chmod " << path;
699 return -1;
700 }
701#if EMULATED_USES_SELINUX
702 if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
703 PLOG(WARNING) << "Failed to restorecon " << path;
704 return -1;
705 }
706#endif
707 return 0;
708}
709
Paul Crowley285956f2016-01-20 13:12:38 +0000710int e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token) {
711 LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " " << (token != nullptr);
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700712 if (e4crypt_is_native()) {
Paul Crowley285956f2016-01-20 13:12:38 +0000713 auto user_key = read_user_key(user_id);
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800714 if (user_key.empty()) {
Paul Crowley285956f2016-01-20 13:12:38 +0000715 // FIXME special case for user 0
716 if (user_id != 0) {
717 LOG(ERROR) << "Couldn't read key for " << user_id;
718 return -1;
719 }
720 // FIXME if the key exists and we just failed to read it, this destroys it.
721 if (!create_user_key(user_id, false)) {
722 return -1;
723 }
724 user_key = read_user_key(user_id);
725 if (user_key.empty()) {
726 LOG(ERROR) << "Couldn't read just-created key for " << user_id;
727 return -1;
728 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800729 }
730 auto raw_ref = e4crypt_install_key(user_key);
731 if (raw_ref.empty()) {
732 return -1;
733 }
Paul Crowley285956f2016-01-20 13:12:38 +0000734 s_key_raw_refs[serial] = raw_ref;
735 if (user_id == 0) {
736 // FIXME special case for user 0
737 // prepare their storage here
738 e4crypt_prepare_user_storage(nullptr, 0, 0, false);
739 }
740 return 0;
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700741 } else {
742 // When in emulation mode, we just use chmod. However, we also
743 // unlock directories when not in emulation mode, to bring devices
744 // back into a known-good state.
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700745 if (emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
746 emulated_unlock(android::vold::BuildDataMediaPath(nullptr, user_id), 0770) ||
747 emulated_unlock(android::vold::BuildDataUserPath(nullptr, user_id), 0771)) {
748 LOG(ERROR) << "Failed to unlock user " << user_id;
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700749 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
756int e4crypt_lock_user_key(userid_t user_id) {
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700757 if (e4crypt_is_native()) {
758 // TODO: remove from kernel keyring
759 } else if (e4crypt_is_emulated()) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800760 // When in emulation mode, we just use chmod
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700761 if (emulated_lock(android::vold::BuildDataSystemCePath(user_id)) ||
762 emulated_lock(android::vold::BuildDataMediaPath(nullptr, user_id)) ||
763 emulated_lock(android::vold::BuildDataUserPath(nullptr, user_id))) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800764 PLOG(ERROR) << "Failed to lock user " << user_id;
765 return -1;
766 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800767 }
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700768
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800769 return 0;
770}
771
Lenka Trochtova9ad43692015-12-11 13:27:26 +0100772int e4crypt_prepare_user_storage(const char* volume_uuid,
773 userid_t user_id,
774 int serial,
775 bool ephemeral) {
Paul Crowley285956f2016-01-20 13:12:38 +0000776 if (volume_uuid) {
777 LOG(DEBUG) << "e4crypt_prepare_user_storage " << volume_uuid << " " << user_id;
778 } else {
779 LOG(DEBUG) << "e4crypt_prepare_user_storage, null volume " << user_id;
780 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800781 std::string system_ce_path(android::vold::BuildDataSystemCePath(user_id));
Jeff Sharkeyd2d7bff2015-12-18 17:18:22 -0700782 std::string media_ce_path(android::vold::BuildDataMediaPath(volume_uuid, user_id));
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800783 std::string user_ce_path(android::vold::BuildDataUserPath(volume_uuid, user_id));
784 std::string user_de_path(android::vold::BuildDataUserDePath(volume_uuid, user_id));
785
786 if (fs_prepare_dir(system_ce_path.c_str(), 0700, AID_SYSTEM, AID_SYSTEM)) {
787 PLOG(ERROR) << "Failed to prepare " << system_ce_path;
788 return -1;
789 }
Jeff Sharkeyd2d7bff2015-12-18 17:18:22 -0700790 if (fs_prepare_dir(media_ce_path.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW)) {
791 PLOG(ERROR) << "Failed to prepare " << media_ce_path;
792 return -1;
793 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800794 if (fs_prepare_dir(user_ce_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM)) {
795 PLOG(ERROR) << "Failed to prepare " << user_ce_path;
796 return -1;
797 }
798 if (fs_prepare_dir(user_de_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM)) {
799 PLOG(ERROR) << "Failed to prepare " << user_de_path;
800 return -1;
801 }
802
803 if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000804 if (e4crypt_set_user_policy(user_id, serial, system_ce_path)
805 || e4crypt_set_user_policy(user_id, serial, media_ce_path)
806 || e4crypt_set_user_policy(user_id, serial, user_ce_path)) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800807 return -1;
808 }
809 }
810
811 return 0;
812}