blob: 548e4e445c70c33ac94db7b2f053ea46bbbde3a4 [file] [log] [blame]
Ethan Yonkere9afc3d2018-08-30 15:16:27 -05001/*
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
17#include "Ext4CryptPie.h"
18
Peter Cai90edd2e2019-05-23 16:32:22 +080019#include "Keymaster4.h"
Ethan Yonkere9afc3d2018-08-30 15:16:27 -050020#include "KeyStorage4.h"
21#include "KeyUtil.h"
22#include "Utils.h"
23#include "Decrypt.h"
24//#include "VoldUtil.h"
25
26#include <algorithm>
27#include <map>
28#include <set>
29#include <sstream>
30#include <string>
31#include <vector>
32
33#include <dirent.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <unistd.h>
37#include <limits.h>
38#include <selinux/android.h>
39#include <sys/mount.h>
40#include <sys/stat.h>
41#include <sys/types.h>
42
43#include <private/android_filesystem_config.h>
44
45//#include "android/os/IVold.h"
46
47//#include "cryptfs.h"
48
49#define EMULATED_USES_SELINUX 0
50#define MANAGE_MISC_DIRS 0
51
52#include <cutils/fs.h>
53#include <cutils/properties.h>
54
55#include <ext4_utils/ext4_crypt.h>
56#include <keyutils.h>
57
58#include <android-base/file.h>
59//#include <android-base/logging.h>
60#include <android-base/properties.h>
61#include <android-base/stringprintf.h>
62
63#include <iostream>
64#define LOG(x) std::cout
65#define PLOG(x) std::cout
66#define DATA_MNT_POINT "/data"
67
68using android::base::StringPrintf;
69using android::base::WriteStringToFile;
70using android::vold::kEmptyAuthentication;
71using android::vold::KeyBuffer;
Peter Cai90edd2e2019-05-23 16:32:22 +080072using android::vold::Keymaster;
73using android::hardware::keymaster::V4_0::KeyFormat;
Ethan Yonkere9afc3d2018-08-30 15:16:27 -050074
75// Store main DE raw ref / policy
76std::string de_raw_ref;
77// Map user ids to key references
78std::map<userid_t, std::string> s_de_key_raw_refs;
79std::map<userid_t, std::string> s_ce_key_raw_refs;
80// TODO abolish this map, per b/26948053
81std::map<userid_t, KeyBuffer> s_ce_keys;
82
83namespace {
84
85struct PolicyKeyRef {
86 std::string contents_mode;
87 std::string filenames_mode;
88 std::string key_raw_ref;
89};
90
91const std::string device_key_dir = std::string() + DATA_MNT_POINT + e4crypt_unencrypted_folder;
92const std::string device_key_path = device_key_dir + "/key";
93const std::string device_key_temp = device_key_dir + "/temp";
94
95const std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys";
96const std::string user_key_temp = user_key_dir + "/temp";
97const std::string prepare_subdirs_path = "/system/bin/vold_prepare_subdirs";
98
99const std::string systemwide_volume_key_dir =
100 std::string() + DATA_MNT_POINT + "/misc/vold/volume_keys";
101
102bool s_global_de_initialized = false;
103
104// Some users are ephemeral, don't try to wipe their keys from disk
105std::set<userid_t> s_ephemeral_users;
106
107}
108
109static bool e4crypt_is_emulated() {
110 return property_get_bool("persist.sys.emulate_fbe", false);
111}
112
bigbiffadc599e2020-05-28 19:36:30 +0000113static const char* escape_empty(const std::string& value) {
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500114 return value.empty() ? "null" : value.c_str();
bigbiffadc599e2020-05-28 19:36:30 +0000115}
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500116
117static std::string get_de_key_path(userid_t user_id) {
118 return StringPrintf("%s/de/%d", user_key_dir.c_str(), user_id);
119}
120
121static std::string get_ce_key_directory_path(userid_t user_id) {
122 return StringPrintf("%s/ce/%d", user_key_dir.c_str(), user_id);
123}
124
125// Returns the keys newest first
126static std::vector<std::string> get_ce_key_paths(const std::string& directory_path) {
127 auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(directory_path.c_str()), closedir);
128 if (!dirp) {
129 PLOG(ERROR) << "Unable to open ce key directory: " + directory_path << std::endl;
130 return std::vector<std::string>();
131 }
132 std::vector<std::string> result;
133 for (;;) {
134 errno = 0;
135 auto const entry = readdir(dirp.get());
136 if (!entry) {
137 if (errno) {
138 PLOG(ERROR) << "Unable to read ce key directory: " + directory_path << std::endl;
139 return std::vector<std::string>();
140 }
141 break;
142 }
143 if (entry->d_type != DT_DIR || entry->d_name[0] != 'c') {
144 LOG(DEBUG) << "Skipping non-key " << entry->d_name << std::endl;
145 continue;
146 }
147 result.emplace_back(directory_path + "/" + entry->d_name);
148 }
149 std::sort(result.begin(), result.end());
150 std::reverse(result.begin(), result.end());
151 return result;
152}
153
154static std::string get_ce_key_current_path(const std::string& directory_path) {
155 return directory_path + "/current";
156}
157
bigbiffadc599e2020-05-28 19:36:30 +0000158/*static bool get_ce_key_new_path(const std::string& directory_path,
159 const std::vector<std::string>& paths,
160 std::string *ce_key_path) {
161 if (paths.empty()) {
162 *ce_key_path = get_ce_key_current_path(directory_path);
163 return true;
164 }
165 for (unsigned int i = 0; i < UINT_MAX; i++) {
166 auto const candidate = StringPrintf("%s/cx%010u", directory_path.c_str(), i);
167 if (paths[0] < candidate) {
168 *ce_key_path = candidate;
169 return true;
170 }
171 }
172 return false;
173}*/
174
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500175// Discard all keys but the named one; rename it to canonical name.
176// No point in acting on errors in this; ignore them.
177static void fixate_user_ce_key(const std::string& directory_path, const std::string &to_fix,
178 const std::vector<std::string>& paths) {
179 for (auto const other_path: paths) {
180 if (other_path != to_fix) {
181 android::vold::destroyKey(other_path);
182 }
183 }
184 auto const current_path = get_ce_key_current_path(directory_path);
185 if (to_fix != current_path) {
186 LOG(DEBUG) << "Renaming " << to_fix << " to " << current_path << std::endl;
187 if (rename(to_fix.c_str(), current_path.c_str()) != 0) {
188 PLOG(WARNING) << "Unable to rename " << to_fix << " to " << current_path << std::endl;
189 }
190 }
191}
192
193static bool read_and_fixate_user_ce_key(userid_t user_id,
194 const android::vold::KeyAuthentication& auth,
195 KeyBuffer *ce_key) {
196 auto const directory_path = get_ce_key_directory_path(user_id);
197 auto const paths = get_ce_key_paths(directory_path);
198 for (auto const ce_key_path: paths) {
199 LOG(DEBUG) << "Trying user CE key " << ce_key_path << std::endl;
200 if (android::vold::retrieveKey(ce_key_path, auth, ce_key)) {
201 LOG(DEBUG) << "Successfully retrieved key" << std::endl;
202 fixate_user_ce_key(directory_path, ce_key_path, paths);
203 return true;
204 }
205 }
206 LOG(ERROR) << "Failed to find working ce key for user " << user_id << std::endl;
207 return false;
208}
209
Peter Cai90edd2e2019-05-23 16:32:22 +0800210static bool is_wrapped_key_supported_common(const std::string& mount_point) {
bigbiff bigbiff0be03b32019-08-27 20:50:31 -0400211 LOG(DEBUG) << "Determining wrapped-key support for " << mount_point << std::endl;
Peter Cai90edd2e2019-05-23 16:32:22 +0800212 std::string wrapped_key_supported = android::base::GetProperty("fbe.data.wrappedkey", "false");
bigbiff bigbiff0be03b32019-08-27 20:50:31 -0400213 LOG(DEBUG) << "fbe.data.wrappedkey = " << wrapped_key_supported << std::endl;
Peter Cai90edd2e2019-05-23 16:32:22 +0800214 if (mount_point == DATA_MNT_POINT && wrapped_key_supported == "true") {
bigbiff bigbiff0be03b32019-08-27 20:50:31 -0400215 LOG(DEBUG) << "Wrapped key supported on " << mount_point << std::endl;
Peter Cai90edd2e2019-05-23 16:32:22 +0800216 return true;
217 } else {
218 return false;
219 }
220}
221
222bool is_wrapped_key_supported() {
223 return is_wrapped_key_supported_common(DATA_MNT_POINT);
224}
225
226bool is_wrapped_key_supported_external() {
227 return false;
228}
229
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500230static bool read_and_install_user_ce_key(userid_t user_id,
231 const android::vold::KeyAuthentication& auth) {
232 if (s_ce_key_raw_refs.count(user_id) != 0) return true;
233 KeyBuffer ce_key;
234 if (!read_and_fixate_user_ce_key(user_id, auth, &ce_key)) return false;
235 std::string ce_raw_ref;
Peter Cai90edd2e2019-05-23 16:32:22 +0800236
237 if (is_wrapped_key_supported()) {
238 KeyBuffer ephemeral_wrapped_key;
239 if (!getEphemeralWrappedKey(KeyFormat::RAW, ce_key, &ephemeral_wrapped_key)) {
240 LOG(ERROR) << "Failed to export ce key";
241 return false;
242 }
243
244 ce_key = std::move(ephemeral_wrapped_key);
245 }
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500246 if (!android::vold::installKey(ce_key, &ce_raw_ref)) return false;
247 s_ce_keys[user_id] = std::move(ce_key);
248 s_ce_key_raw_refs[user_id] = ce_raw_ref;
249 LOG(DEBUG) << "Installed ce key for user " << user_id << std::endl;
250 return true;
251}
252
253static bool prepare_dir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid) {
254 LOG(DEBUG) << "Preparing: " << dir << std::endl;
255 if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
256 PLOG(ERROR) << "Failed to prepare " << dir << std::endl;
257 return false;
258 }
259 return true;
260}
261
bigbiffadc599e2020-05-28 19:36:30 +0000262/*static bool destroy_dir(const std::string& dir) {
263 LOG(DEBUG) << "Destroying: " << dir;
264 if (rmdir(dir.c_str()) != 0 && errno != ENOENT) {
265 PLOG(ERROR) << "Failed to destroy " << dir;
266 return false;
267 }
268 return true;
269}*/
270
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500271// NB this assumes that there is only one thread listening for crypt commands, because
272// it creates keys in a fixed location.
273static bool create_and_install_user_keys(userid_t user_id, bool create_ephemeral) {
274 /*KeyBuffer de_key, ce_key;
275 if (!android::vold::randomKey(&de_key)) return false;
276 if (!android::vold::randomKey(&ce_key)) return false;
277 if (create_ephemeral) {
278 // If the key should be created as ephemeral, don't store it.
279 s_ephemeral_users.insert(user_id);
280 } else {
281 auto const directory_path = get_ce_key_directory_path(user_id);
282 if (!prepare_dir(directory_path, 0700, AID_ROOT, AID_ROOT)) return false;
283 auto const paths = get_ce_key_paths(directory_path);
284 std::string ce_key_path;
285 if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
286 if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp,
287 kEmptyAuthentication, ce_key)) return false;
288 fixate_user_ce_key(directory_path, ce_key_path, paths);
289 // Write DE key second; once this is written, all is good.
290 if (!android::vold::storeKeyAtomically(get_de_key_path(user_id), user_key_temp,
291 kEmptyAuthentication, de_key)) return false;
292 }
293 std::string de_raw_ref;
294 if (!android::vold::installKey(de_key, &de_raw_ref)) return false;
295 s_de_key_raw_refs[user_id] = de_raw_ref;
296 std::string ce_raw_ref;
297 if (!android::vold::installKey(ce_key, &ce_raw_ref)) return false;
298 s_ce_keys[user_id] = ce_key;
299 s_ce_key_raw_refs[user_id] = ce_raw_ref;
300 LOG(DEBUG) << "Created keys for user " << user_id;*/
301 LOG(DEBUG) << "TWRP not doing create_and_install_user_keys\n";
302 return true;
303}
304
305bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t user_id,
306 std::string* raw_ref) {
307 auto refi = key_map.find(user_id);
308 if (refi == key_map.end()) {
309 LOG(ERROR) << "Cannot find key for " << user_id << std::endl;
310 return false;
311 }
312 *raw_ref = refi->second;
313 return true;
314}
315
316static void get_data_file_encryption_modes(PolicyKeyRef* key_ref) {
317 /*struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab_default, DATA_MNT_POINT);
318 char const* contents_mode = strdup("ice");
319 char const* filenames_mode = strdup("aes-256-heh");
320 fs_mgr_get_file_encryption_modes(rec, &contents_mode, &filenames_mode);
321 key_ref->contents_mode = contents_mode;
322 key_ref->filenames_mode = filenames_mode;*/
323 LOG(INFO) << "contents mode '" << android::base::GetProperty("fbe.contents", "aes-256-xts") << "' filenames '" << android::base::GetProperty("fbe.filenames", "aes-256-heh") << "'\n";
324 key_ref->contents_mode =
325 android::base::GetProperty("fbe.contents", "aes-256-xts");
326 key_ref->filenames_mode =
327 android::base::GetProperty("fbe.filenames", "aes-256-heh");
328}
329
bigbiffadc599e2020-05-28 19:36:30 +0000330static bool ensure_policy(const PolicyKeyRef& key_ref, const std::string& path) {
331 return true;
332 /*return e4crypt_policy_ensure(path.c_str(), key_ref.key_raw_ref.data(),
333 key_ref.key_raw_ref.size(), key_ref.contents_mode.c_str(),
334 key_ref.filenames_mode.c_str()) == 0;*/
335}
336
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500337static bool is_numeric(const char* name) {
338 for (const char* p = name; *p != '\0'; p++) {
339 if (!isdigit(*p)) return false;
340 }
341 return true;
342}
343
344static bool load_all_de_keys() {
345 auto de_dir = user_key_dir + "/de";
346 auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(de_dir.c_str()), closedir);
347 if (!dirp) {
348 PLOG(ERROR) << "Unable to read de key directory" << std::endl;
349 return false;
350 }
351 for (;;) {
352 errno = 0;
353 auto entry = readdir(dirp.get());
354 if (!entry) {
355 if (errno) {
356 PLOG(ERROR) << "Unable to read de key directory" << std::endl;
357 return false;
358 }
359 break;
360 }
361 if (entry->d_type != DT_DIR || !is_numeric(entry->d_name)) {
362 LOG(DEBUG) << "Skipping non-de-key " << entry->d_name << std::endl;
363 continue;
364 }
365 userid_t user_id = std::stoi(entry->d_name);
366 if (s_de_key_raw_refs.count(user_id) == 0) {
367 auto key_path = de_dir + "/" + entry->d_name;
368 KeyBuffer key;
369 if (!android::vold::retrieveKey(key_path, kEmptyAuthentication, &key)) return false;
370 std::string raw_ref;
Peter Cai90edd2e2019-05-23 16:32:22 +0800371 if (is_wrapped_key_supported()) {
372 KeyBuffer ephemeral_wrapped_key;
373 if (!getEphemeralWrappedKey(KeyFormat::RAW, key, &ephemeral_wrapped_key)) {
374 LOG(ERROR) << "Failed to export de_key in create_and_install_user_keys";
375 return false;
376 }
377 key = std::move(ephemeral_wrapped_key);
378 }
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500379 if (!android::vold::installKey(key, &raw_ref)) return false;
380 s_de_key_raw_refs[user_id] = raw_ref;
381 LOG(DEBUG) << "Installed de key for user " << user_id << std::endl;
382 }
383 }
384 // ext4enc:TODO: go through all DE directories, ensure that all user dirs have the
385 // correct policy set on them, and that no rogue ones exist.
386 return true;
387}
388
389bool e4crypt_initialize_global_de() {
390 LOG(INFO) << "e4crypt_initialize_global_de" << std::endl;
Peter Cai90edd2e2019-05-23 16:32:22 +0800391 bool wrapped_key_supported = false;
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500392
393 if (s_global_de_initialized) {
394 LOG(INFO) << "Already initialized" << std::endl;
395 return true;
396 }
397
398 PolicyKeyRef device_ref;
Peter Cai90edd2e2019-05-23 16:32:22 +0800399 wrapped_key_supported = is_wrapped_key_supported();
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500400 LOG(INFO) << "calling retrieveAndInstallKey\n";
401 if (!android::vold::retrieveAndInstallKey(true, kEmptyAuthentication, device_key_path,
Peter Cai90edd2e2019-05-23 16:32:22 +0800402 device_key_temp, &device_ref.key_raw_ref, wrapped_key_supported))
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500403 return false;
404 get_data_file_encryption_modes(&device_ref);
405
406 std::string modestring = device_ref.contents_mode + ":" + device_ref.filenames_mode;
407 std::string mode_filename = std::string("/data") + e4crypt_key_mode;
408 if (!android::base::WriteStringToFile(modestring, mode_filename)) {
409 PLOG(ERROR) << "Cannot save type" << std::endl;
410 return false;
411 }
412
413 std::string ref_filename = std::string("/data") + e4crypt_key_ref;
414 if (!android::base::WriteStringToFile(device_ref.key_raw_ref, ref_filename)) {
415 PLOG(ERROR) << "Cannot save key reference to:" << ref_filename << std::endl;
416 return false;
417 }
418 LOG(INFO) << "Wrote system DE key reference to:" << ref_filename << std::endl;
419
420 s_global_de_initialized = true;
421 de_raw_ref = device_ref.key_raw_ref;
422 return true;
423}
424
425bool e4crypt_init_user0() {
426 LOG(DEBUG) << "e4crypt_init_user0\n";
427 if (e4crypt_is_native()) {
428 if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false;
429 if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false;
430 if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false;
431 if (!android::vold::pathExists(get_de_key_path(0))) {
432 if (!create_and_install_user_keys(0, false)) return false;
433 }
434 // TODO: switch to loading only DE_0 here once framework makes
435 // explicit calls to install DE keys for secondary users
436 if (!load_all_de_keys()) return false;
437 }
bigbiffadc599e2020-05-28 19:36:30 +0000438 // We can only safely prepare DE storage here, since CE keys are probably
439 // entangled with user credentials. The framework will always prepare CE
440 // storage once CE keys are installed.
441 if (!e4crypt_prepare_user_storage("", 0, 0, /*android::os::IVold::*/STORAGE_FLAG_DE)) {
442 LOG(ERROR) << "Failed to prepare user 0 storage" << std::endl;
443 return false;
444 }
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500445
446 // If this is a non-FBE device that recently left an emulated mode,
447 // restore user data directories to known-good state.
448 if (!e4crypt_is_native() && !e4crypt_is_emulated()) {
449 e4crypt_unlock_user_key(0, 0, "!", "!");
450 }
451
452 return true;
453}
454
bigbiffadc599e2020-05-28 19:36:30 +0000455/*bool e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
456 LOG(DEBUG) << "TWRP NOT e4crypt_vold_create_user_key for " << user_id << " serial " << serial;
457 return true;
458 if (!e4crypt_is_native()) {
459 return true;
460 }
461 // FIXME test for existence of key that is not loaded yet
462 if (s_ce_key_raw_refs.count(user_id) != 0) {
463 LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for " << user_id
464 << " serial " << serial;
465 // FIXME should we fail the command?
466 return true;
467 }
468 if (!create_and_install_user_keys(user_id, ephemeral)) {
469 return false;
470 }
471 return true;
472}
473
474static void drop_caches() {
475 // Clean any dirty pages (otherwise they won't be dropped).
476 sync();
477 // Drop inode and page caches.
478 if (!WriteStringToFile("3", "/proc/sys/vm/drop_caches")) {
479 PLOG(ERROR) << "Failed to drop caches during key eviction";
480 }
481}
482
483static bool evict_ce_key(userid_t user_id) {
484 LOG(ERROR) << "TWRP NOT evict_ce_key\n";
485 return true;
486 s_ce_keys.erase(user_id);
487 bool success = true;
488 std::string raw_ref;
489 // If we haven't loaded the CE key, no need to evict it.
490 if (lookup_key_ref(s_ce_key_raw_refs, user_id, &raw_ref)) {
491 success &= android::vold::evictKey(raw_ref);
492 drop_caches();
493 }
494 s_ce_key_raw_refs.erase(user_id);
495 return success;
496}
497
498bool e4crypt_destroy_user_key(userid_t user_id) {
499 LOG(DEBUG) << "NOT e4crypt_destroy_user_key(" << user_id << ")";
500 return true;
501 if (!e4crypt_is_native()) {
502 return true;
503 }
504 bool success = true;
505 std::string raw_ref;
506 success &= evict_ce_key(user_id);
507 success &= lookup_key_ref(s_de_key_raw_refs, user_id, &raw_ref)
508 && android::vold::evictKey(raw_ref);
509 s_de_key_raw_refs.erase(user_id);
510 auto it = s_ephemeral_users.find(user_id);
511 if (it != s_ephemeral_users.end()) {
512 s_ephemeral_users.erase(it);
513 } else {
514 for (auto const path: get_ce_key_paths(get_ce_key_directory_path(user_id))) {
515 success &= android::vold::destroyKey(path);
516 }
517 auto de_key_path = get_de_key_path(user_id);
518 if (android::vold::pathExists(de_key_path)) {
519 success &= android::vold::destroyKey(de_key_path);
520 } else {
521 LOG(INFO) << "Not present so not erasing: " << de_key_path;
522 }
523 }
524 return success;
525}
526
527static bool emulated_lock(const std::string& path) {
528 if (chmod(path.c_str(), 0000) != 0) {
529 PLOG(ERROR) << "Failed to chmod " << path;
530 return false;
531 }
532#if EMULATED_USES_SELINUX
533 if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
534 PLOG(WARNING) << "Failed to setfilecon " << path;
535 return false;
536 }
537#endif
538 return true;
539}*/
540
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500541static bool emulated_unlock(const std::string& path, mode_t mode) {
542 if (chmod(path.c_str(), mode) != 0) {
543 PLOG(ERROR) << "Failed to chmod " << path << std::endl;
544 // FIXME temporary workaround for b/26713622
545 if (e4crypt_is_emulated()) return false;
546 }
547#if EMULATED_USES_SELINUX
548 if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
549 PLOG(WARNING) << "Failed to restorecon " << path << std::endl;
550 // FIXME temporary workaround for b/26713622
551 if (e4crypt_is_emulated()) return false;
552 }
553#endif
554 return true;
555}
556
557static bool parse_hex(const std::string& hex, std::string* result) {
558 if (hex == "!") {
559 *result = "";
560 return true;
561 }
562 if (android::vold::HexToStr(hex, *result) != 0) {
563 LOG(ERROR) << "Invalid FBE hex string" << std::endl; // Don't log the string for security reasons
564 return false;
565 }
566 return true;
567}
568
bigbiffadc599e2020-05-28 19:36:30 +0000569static std::string volkey_path(const std::string& misc_path, const std::string& volume_uuid) {
570 return misc_path + "/vold/volume_keys/" + volume_uuid + "/default";
571}
572
573static std::string volume_secdiscardable_path(const std::string& volume_uuid) {
574 return systemwide_volume_key_dir + "/" + volume_uuid + "/secdiscardable";
575}
576
577static bool read_or_create_volkey(const std::string& misc_path, const std::string& volume_uuid,
578 PolicyKeyRef* key_ref) {
579 auto secdiscardable_path = volume_secdiscardable_path(volume_uuid);
580 std::string secdiscardable_hash;
581 bool wrapped_key_supported = false;
582 if (android::vold::pathExists(secdiscardable_path)) {
583 if (!android::vold::readSecdiscardable(secdiscardable_path, &secdiscardable_hash))
584 return false;
585 } else {
586 if (fs_mkdirs(secdiscardable_path.c_str(), 0700) != 0) {
587 PLOG(ERROR) << "Creating directories for: " << secdiscardable_path << std::endl;
588 return false;
589 }
590 if (!android::vold::createSecdiscardable(secdiscardable_path, &secdiscardable_hash))
591 return false;
592 }
593 auto key_path = volkey_path(misc_path, volume_uuid);
594 if (fs_mkdirs(key_path.c_str(), 0700) != 0) {
595 PLOG(ERROR) << "Creating directories for: " << key_path << std::endl;
596 return false;
597 }
598 android::vold::KeyAuthentication auth("", secdiscardable_hash);
599 wrapped_key_supported = is_wrapped_key_supported_external();
600 if (!android::vold::retrieveAndInstallKey(true, auth, key_path, key_path + "_tmp",
601 &key_ref->key_raw_ref, wrapped_key_supported))
602 return false;
603 key_ref->contents_mode =
604 android::base::GetProperty("ro.crypto.volume.contents_mode", "aes-256-xts");
605 key_ref->filenames_mode =
606 android::base::GetProperty("ro.crypto.volume.filenames_mode", "aes-256-heh");
607 return true;
608}
609
610/*static bool destroy_volkey(const std::string& misc_path, const std::string& volume_uuid) {
611 auto path = volkey_path(misc_path, volume_uuid);
612 if (!android::vold::pathExists(path)) return true;
613 return android::vold::destroyKey(path);
614}
615
616bool e4crypt_add_user_key_auth(userid_t user_id, int serial, const std::string& token_hex,
617 const std::string& secret_hex) {
618 LOG(DEBUG) << "e4crypt_add_user_key_auth " << user_id << " serial=" << serial
619 << " token_present=" << (token_hex != "!");
620 if (!e4crypt_is_native()) return true;
621 if (s_ephemeral_users.count(user_id) != 0) return true;
622 std::string token, secret;
623 if (!parse_hex(token_hex, &token)) return false;
624 if (!parse_hex(secret_hex, &secret)) return false;
625 auto auth = secret.empty() ? kEmptyAuthentication
626 : android::vold::KeyAuthentication(token, secret);
627 auto it = s_ce_keys.find(user_id);
628 if (it == s_ce_keys.end()) {
629 LOG(ERROR) << "Key not loaded into memory, can't change for user " << user_id;
630 return false;
631 }
632 const auto &ce_key = it->second;
633 auto const directory_path = get_ce_key_directory_path(user_id);
634 auto const paths = get_ce_key_paths(directory_path);
635 std::string ce_key_path;
636 if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
637 if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, auth, ce_key)) return false;
638 return true;
639}
640
641bool e4crypt_fixate_newest_user_key_auth(userid_t user_id) {
642 LOG(DEBUG) << "e4crypt_fixate_newest_user_key_auth " << user_id;
643 if (!e4crypt_is_native()) return true;
644 if (s_ephemeral_users.count(user_id) != 0) return true;
645 auto const directory_path = get_ce_key_directory_path(user_id);
646 auto const paths = get_ce_key_paths(directory_path);
647 if (paths.empty()) {
648 LOG(ERROR) << "No ce keys present, cannot fixate for user " << user_id;
649 return false;
650 }
651 fixate_user_ce_key(directory_path, paths[0], paths);
652 return true;
653}*/
654
Ethan Yonkere9afc3d2018-08-30 15:16:27 -0500655// TODO: rename to 'install' for consistency, and take flags to know which keys to install
656bool e4crypt_unlock_user_key(userid_t user_id, int serial, const std::string& token_hex,
657 const std::string& secret_hex) {
658 LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " serial=" << serial
659 << " token_present=" << (token_hex != "!") << std::endl;
660 if (e4crypt_is_native()) {
661 if (s_ce_key_raw_refs.count(user_id) != 0) {
662 LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id << std::endl;
663 return true;
664 }
665 std::string token, secret;
666 if (!parse_hex(token_hex, &token)) return false;
667 if (!parse_hex(secret_hex, &secret)) return false;
668 android::vold::KeyAuthentication auth(token, secret);
669 if (!read_and_install_user_ce_key(user_id, auth)) {
670 LOG(ERROR) << "Couldn't read key for " << user_id << std::endl;
671 return false;
672 }
673 } else {
674 // When in emulation mode, we just use chmod. However, we also
675 // unlock directories when not in emulation mode, to bring devices
676 // back into a known-good state.
677 if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
678 !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) ||
679 !emulated_unlock(android::vold::BuildDataMediaCePath("", user_id), 0770) ||
680 !emulated_unlock(android::vold::BuildDataUserCePath("", user_id), 0771)) {
681 LOG(ERROR) << "Failed to unlock user " << user_id << std::endl;
682 return false;
683 }
684 }
685 return true;
686}
bigbiffadc599e2020-05-28 19:36:30 +0000687
688// TODO: rename to 'evict' for consistency
689/*bool e4crypt_lock_user_key(userid_t user_id) {
690 LOG(DEBUG) << "TWRP NOTe4crypt_lock_user_key " << user_id;
691 return true;
692 if (e4crypt_is_native()) {
693 return evict_ce_key(user_id);
694 } else if (e4crypt_is_emulated()) {
695 // When in emulation mode, we just use chmod
696 if (!emulated_lock(android::vold::BuildDataSystemCePath(user_id)) ||
697 !emulated_lock(android::vold::BuildDataMiscCePath(user_id)) ||
698 !emulated_lock(android::vold::BuildDataMediaCePath("", user_id)) ||
699 !emulated_lock(android::vold::BuildDataUserCePath("", user_id))) {
700 LOG(ERROR) << "Failed to lock user " << user_id;
701 return false;
702 }
703 }
704
705 return true;
706}*/
707
708static bool prepare_subdirs(const std::string& action, const std::string& volume_uuid,
709 userid_t user_id, int flags) {
710 LOG(ERROR) << "not actually forking for vold_prepare_subdirs\n";
711 return true;
712 /*if (0 != android::vold::ForkExecvp(
713 std::vector<std::string>{prepare_subdirs_path, action, volume_uuid,
714 std::to_string(user_id), std::to_string(flags)})) {
715 LOG(ERROR) << "vold_prepare_subdirs failed";
716 return false;
717 }
718 return true;*/
719}
720
721bool e4crypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial,
722 int flags) {
723 LOG(DEBUG) << "e4crypt_prepare_user_storage for volume " << escape_empty(volume_uuid)
724 << ", user " << user_id << ", serial " << serial << ", flags " << flags << std::endl;
725
726 if (flags & /*android::os::IVold::*/STORAGE_FLAG_DE) {
727 // DE_sys key
728 auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
729 auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
730 auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
731
732 // DE_n key
733 auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
734 auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
735 auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id);
736 auto user_de_path = android::vold::BuildDataUserDePath(nullptr, user_id);
737
738 if (volume_uuid.empty()) {
739 if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
740#if MANAGE_MISC_DIRS
741 if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM),
742 multiuser_get_uid(user_id, AID_EVERYBODY))) return false;
743#endif
744 if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
745 if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
746 if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false;
747 if (!prepare_dir(vendor_de_path, 0771, AID_ROOT, AID_ROOT)) return false;
748 }
749 if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
750
751 if (e4crypt_is_native()) {
752 PolicyKeyRef de_ref;
753 if (volume_uuid.empty()) {
754 if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_ref.key_raw_ref)) return false;
755 get_data_file_encryption_modes(&de_ref);
756 if (!ensure_policy(de_ref, system_de_path)) return false;
757 if (!ensure_policy(de_ref, misc_de_path)) return false;
758 if (!ensure_policy(de_ref, vendor_de_path)) return false;
759 } else {
760 if (!read_or_create_volkey(misc_de_path, nullptr, &de_ref)) return false;
761 }
762 if (!ensure_policy(de_ref, user_de_path)) return false;
763 }
764 }
765
766 if (flags & /*android::os::IVold::*/STORAGE_FLAG_CE) {
767 // CE_n key
768 auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
769 auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
770 auto vendor_ce_path = android::vold::BuildDataVendorCePath(user_id);
771 auto media_ce_path = android::vold::BuildDataMediaCePath(nullptr, user_id);
772 auto user_ce_path = android::vold::BuildDataUserCePath(nullptr, user_id);
773
774 if (volume_uuid.empty()) {
775 if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
776 if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false;
777 if (!prepare_dir(vendor_ce_path, 0771, AID_ROOT, AID_ROOT)) return false;
778 }
779 if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
780 if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
781
782 if (e4crypt_is_native()) {
783 PolicyKeyRef ce_ref;
784 if (volume_uuid.empty()) {
785 if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_ref.key_raw_ref)) return false;
786 get_data_file_encryption_modes(&ce_ref);
787 if (!ensure_policy(ce_ref, system_ce_path)) return false;
788 if (!ensure_policy(ce_ref, misc_ce_path)) return false;
789 if (!ensure_policy(ce_ref, vendor_ce_path)) return false;
790 } else {
791 if (!read_or_create_volkey(misc_ce_path, nullptr, &ce_ref)) return false;
792 }
793 if (!ensure_policy(ce_ref, media_ce_path)) return false;
794 if (!ensure_policy(ce_ref, user_ce_path)) return false;
795 }
796
797 if (volume_uuid.empty()) {
798 // Now that credentials have been installed, we can run restorecon
799 // over these paths
800 // NOTE: these paths need to be kept in sync with libselinux
801 //android::vold::RestoreconRecursive(system_ce_path);
802 //android::vold::RestoreconRecursive(misc_ce_path);
803 }
804 }
805 if (!prepare_subdirs("prepare", volume_uuid, user_id, flags)) return false;
806 return true;
807}
808
809/*bool e4crypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_id, int flags) {
810 LOG(DEBUG) << "TWRP NOT e4crypt_destroy_user_storage for volume " << escape_empty(volume_uuid)
811 << ", user " << user_id << ", flags " << flags;
812 bool res = true;
813 return res;
814
815 res &= prepare_subdirs("destroy", volume_uuid, user_id, flags);
816
817 if (flags & android::os::IVold::STORAGE_FLAG_CE) {
818 // CE_n key
819 auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
820 auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
821 auto vendor_ce_path = android::vold::BuildDataVendorCePath(user_id);
822 auto media_ce_path = android::vold::BuildDataMediaCePath(nullptr, user_id);
823 auto user_ce_path = android::vold::BuildDataUserCePath(nullptr, user_id);
824
825 res &= destroy_dir(media_ce_path);
826 res &= destroy_dir(user_ce_path);
827 if (volume_uuid.empty()) {
828 res &= destroy_dir(system_ce_path);
829 res &= destroy_dir(misc_ce_path);
830 res &= destroy_dir(vendor_ce_path);
831 } else {
832 if (e4crypt_is_native()) {
833 res &= destroy_volkey(misc_ce_path, volume_uuid);
834 }
835 }
836 }
837
838 if (flags & android::os::IVold::STORAGE_FLAG_DE) {
839 // DE_sys key
840 auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
841 auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
842 auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
843
844 // DE_n key
845 auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
846 auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
847 auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id);
848 auto user_de_path = android::vold::BuildDataUserDePath(nullptr, user_id);
849
850 res &= destroy_dir(user_de_path);
851 if (volume_uuid.empty()) {
852 res &= destroy_dir(system_legacy_path);
853#if MANAGE_MISC_DIRS
854 res &= destroy_dir(misc_legacy_path);
855#endif
856 res &= destroy_dir(profiles_de_path);
857 res &= destroy_dir(system_de_path);
858 res &= destroy_dir(misc_de_path);
859 res &= destroy_dir(vendor_de_path);
860 } else {
861 if (e4crypt_is_native()) {
862 res &= destroy_volkey(misc_de_path, volume_uuid);
863 }
864 }
865 }
866
867 return res;
868}
869
870static bool destroy_volume_keys(const std::string& directory_path, const std::string& volume_uuid) {
871 LOG(ERROR) << "TWRP NOT destroy_volume_keys\n";
872 return true;
873 auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(directory_path.c_str()), closedir);
874 if (!dirp) {
875 PLOG(ERROR) << "Unable to open directory: " + directory_path;
876 return false;
877 }
878 bool res = true;
879 for (;;) {
880 errno = 0;
881 auto const entry = readdir(dirp.get());
882 if (!entry) {
883 if (errno) {
884 PLOG(ERROR) << "Unable to read directory: " + directory_path;
885 return false;
886 }
887 break;
888 }
889 if (entry->d_type != DT_DIR || entry->d_name[0] == '.') {
890 LOG(DEBUG) << "Skipping non-user " << entry->d_name;
891 continue;
892 }
893 res &= destroy_volkey(directory_path + "/" + entry->d_name, volume_uuid);
894 }
895 return res;
896}
897
898bool e4crypt_destroy_volume_keys(const std::string& volume_uuid) {
899 bool res = true;
900 LOG(DEBUG) << "TWRP NOT e4crypt_destroy_volume_keys for volume " << escape_empty(volume_uuid);
901 /*return res;
902 auto secdiscardable_path = volume_secdiscardable_path(volume_uuid);
903 res &= android::vold::runSecdiscardSingle(secdiscardable_path);
904 res &= destroy_volume_keys("/data/misc_ce", volume_uuid);
905 res &= destroy_volume_keys("/data/misc_de", volume_uuid);
906 return res;
907}*/