blob: 04d7a12647d05750508105b2196c1235f023c9bd [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 {
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000596 if (!prepare_dir(user_key_dir + "/user_" + std::to_string(user_id),
597 0700, AID_ROOT, AID_ROOT)) return false;
598 if (!android::vold::storeKey(key_path, key)) return false;
Paul Crowley95376d62015-05-06 15:04:43 +0100599 }
Paul Crowley285956f2016-01-20 13:12:38 +0000600 LOG(DEBUG) << "Created key " << key_path;
Paul Crowley95376d62015-05-06 15:04:43 +0100601 return true;
602}
603
Paul Crowley285956f2016-01-20 13:12:38 +0000604static int e4crypt_set_user_policy(userid_t user_id, int serial, std::string& path) {
605 LOG(DEBUG) << "e4crypt_set_user_policy for " << user_id << " serial " << serial;
606 if (s_key_raw_refs.count(serial) != 1) {
607 LOG(ERROR) << "Key unknown, can't e4crypt_set_user_policy for "
608 << user_id << " serial " << serial;
Paul Crowley95376d62015-05-06 15:04:43 +0100609 return -1;
610 }
Paul Crowley285956f2016-01-20 13:12:38 +0000611 auto raw_ref = s_key_raw_refs[serial];
612 return do_policy_set(path.c_str(), raw_ref.data(), raw_ref.size());
Paul Crowley95376d62015-05-06 15:04:43 +0100613}
Paul Crowleyb33e8872015-05-19 12:34:09 +0100614
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000615int e4crypt_init_user0() {
616 LOG(DEBUG) << "e4crypt_init_user0";
617 if (e4crypt_is_native()) {
618 if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return -1;
619 std::string user_key;
620 if (!read_user_key(0, user_key)) {
621 // FIXME if the key exists and we just failed to read it, this destroys it.
622 if (!create_user_key(0, false)) {
623 return -1;
624 }
625 if (!read_user_key(0, user_key)) {
626 LOG(ERROR) << "Couldn't read just-created key for user 0";
627 return -1;
628 }
629 }
630 auto raw_ref = e4crypt_install_key(user_key);
631 if (raw_ref.empty()) {
632 return -1;
633 }
634 s_key_raw_refs[0] = raw_ref;
635 }
636 // Ignore failures. FIXME this is horrid
637 e4crypt_prepare_user_storage(nullptr, 0, 0, false);
638 return 0;
639}
640
Paul Crowley27cbce92015-12-10 14:51:30 +0000641int e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
Paul Crowley285956f2016-01-20 13:12:38 +0000642 LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial;
Paul Crowleyea62e262016-01-28 12:23:53 +0000643 if (!e4crypt_is_native()) {
644 return 0;
645 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000646 std::string key;
647 if (read_user_key(user_id, key)) {
Paul Crowley285956f2016-01-20 13:12:38 +0000648 LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for "
649 << user_id << " serial " << serial;
650 // FIXME should we fail the command?
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800651 return 0;
652 }
Paul Crowley285956f2016-01-20 13:12:38 +0000653 if (!create_user_key(user_id, ephemeral)) {
654 return -1;
655 }
656 if (e4crypt_unlock_user_key(user_id, serial, nullptr) != 0) {
657 return -1;
658 }
659 // TODO: create second key for user_de data
660 return 0;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800661}
662
Paul Crowley1ef25582016-01-21 20:26:12 +0000663static bool evict_user_key(userid_t user_id) {
Paul Crowley285956f2016-01-20 13:12:38 +0000664 auto key_path = get_key_path(user_id);
Paul Crowley1ef25582016-01-21 20:26:12 +0000665 std::string key;
666 if (!read_user_key(user_id, key)) return false;
Paul Crowley93363482015-07-07 15:17:22 +0100667 auto ext4_key = fill_key(key);
668 auto ref = keyname(generate_key_ref(ext4_key.raw, ext4_key.size));
669 auto key_serial = keyctl_search(e4crypt_keyring(), "logon", ref.c_str(), 0);
Paul Crowley1ef25582016-01-21 20:26:12 +0000670 if (keyctl_revoke(key_serial) != 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000671 PLOG(ERROR) << "Failed to revoke key with serial " << key_serial << " ref " << ref;
Paul Crowley1ef25582016-01-21 20:26:12 +0000672 return false;
Paul Crowley93363482015-07-07 15:17:22 +0100673 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000674 LOG(DEBUG) << "Revoked key with serial " << key_serial << " ref " << ref;
675 return true;
676}
677
678int e4crypt_destroy_user_key(userid_t user_id) {
679 LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")";
Paul Crowleyea62e262016-01-28 12:23:53 +0000680 if (!e4crypt_is_native()) {
681 return 0;
682 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000683 // TODO: destroy second key for user_de data
684 bool evict_success = evict_user_key(user_id);
685 auto key_path = get_key_path(user_id);
Lenka Trochtova395039f2015-11-25 10:13:03 +0100686 if (e4crypt_is_key_ephemeral(key_path)) {
687 s_ephemeral_user_keys.erase(key_path);
Paul Crowley1ef25582016-01-21 20:26:12 +0000688 } else {
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000689 if (!android::vold::destroyKey(key_path)) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000690 return -1;
691 }
Lenka Trochtova395039f2015-11-25 10:13:03 +0100692 }
Paul Crowley1ef25582016-01-21 20:26:12 +0000693 return evict_success ? 0 : -1;
Paul Crowleyb33e8872015-05-19 12:34:09 +0100694}
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800695
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700696static int emulated_lock(const std::string& path) {
697 if (chmod(path.c_str(), 0000) != 0) {
698 PLOG(ERROR) << "Failed to chmod " << path;
699 return -1;
700 }
701#if EMULATED_USES_SELINUX
702 if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
703 PLOG(WARNING) << "Failed to setfilecon " << path;
704 return -1;
705 }
706#endif
707 return 0;
708}
709
710static int emulated_unlock(const std::string& path, mode_t mode) {
711 if (chmod(path.c_str(), mode) != 0) {
712 PLOG(ERROR) << "Failed to chmod " << path;
Paul Crowleya042cb52016-01-21 17:24:49 +0000713 // FIXME temporary workaround for b/26713622
714 if (e4crypt_is_emulated()) return -1;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700715 }
716#if EMULATED_USES_SELINUX
717 if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
718 PLOG(WARNING) << "Failed to restorecon " << path;
Paul Crowleya042cb52016-01-21 17:24:49 +0000719 // FIXME temporary workaround for b/26713622
720 if (e4crypt_is_emulated()) return -1;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700721 }
722#endif
723 return 0;
724}
725
Paul Crowley285956f2016-01-20 13:12:38 +0000726int e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token) {
727 LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " " << (token != nullptr);
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700728 if (e4crypt_is_native()) {
Paul Crowley1ef25582016-01-21 20:26:12 +0000729 std::string user_key;
730 if (!read_user_key(user_id, user_key)) {
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000731 LOG(ERROR) << "Couldn't read key for " << user_id;
732 return -1;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800733 }
734 auto raw_ref = e4crypt_install_key(user_key);
735 if (raw_ref.empty()) {
736 return -1;
737 }
Paul Crowley285956f2016-01-20 13:12:38 +0000738 s_key_raw_refs[serial] = raw_ref;
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700739 } else {
740 // When in emulation mode, we just use chmod. However, we also
741 // unlock directories when not in emulation mode, to bring devices
742 // back into a known-good state.
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700743 if (emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
744 emulated_unlock(android::vold::BuildDataMediaPath(nullptr, user_id), 0770) ||
745 emulated_unlock(android::vold::BuildDataUserPath(nullptr, user_id), 0771)) {
746 LOG(ERROR) << "Failed to unlock user " << user_id;
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700747 return -1;
748 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800749 }
750 return 0;
751}
752
753int e4crypt_lock_user_key(userid_t user_id) {
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700754 if (e4crypt_is_native()) {
755 // TODO: remove from kernel keyring
756 } else if (e4crypt_is_emulated()) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800757 // When in emulation mode, we just use chmod
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700758 if (emulated_lock(android::vold::BuildDataSystemCePath(user_id)) ||
759 emulated_lock(android::vold::BuildDataMediaPath(nullptr, user_id)) ||
760 emulated_lock(android::vold::BuildDataUserPath(nullptr, user_id))) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800761 PLOG(ERROR) << "Failed to lock user " << user_id;
762 return -1;
763 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800764 }
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700765
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800766 return 0;
767}
768
Lenka Trochtova9ad43692015-12-11 13:27:26 +0100769int e4crypt_prepare_user_storage(const char* volume_uuid,
770 userid_t user_id,
771 int serial,
772 bool ephemeral) {
Paul Crowley285956f2016-01-20 13:12:38 +0000773 if (volume_uuid) {
774 LOG(DEBUG) << "e4crypt_prepare_user_storage " << volume_uuid << " " << user_id;
775 } else {
776 LOG(DEBUG) << "e4crypt_prepare_user_storage, null volume " << user_id;
777 }
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000778 auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
779 auto media_ce_path = android::vold::BuildDataMediaPath(volume_uuid, user_id);
780 auto user_ce_path = android::vold::BuildDataUserPath(volume_uuid, user_id);
781 auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800782
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000783 // FIXME: should this be 0770 or 0700?
784 if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return -1;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000785 if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return -1;
786 if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return -1;
787 if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return -1;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800788
789 if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) {
Paul Crowley285956f2016-01-20 13:12:38 +0000790 if (e4crypt_set_user_policy(user_id, serial, system_ce_path)
791 || e4crypt_set_user_policy(user_id, serial, media_ce_path)
792 || e4crypt_set_user_policy(user_id, serial, user_ce_path)) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800793 return -1;
794 }
795 }
796
797 return 0;
798}