1d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey/*
2d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * Copyright (C) 2015 The Android Open Source Project
3d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey *
4d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * you may not use this file except in compliance with the License.
6d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * You may obtain a copy of the License at
7d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey *
8d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey *
10d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * See the License for the specific language governing permissions and
14d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey * limitations under the License.
15d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey */
16d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
17731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "Ext4Crypt.h"
18731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
191ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley#include "KeyStorage.h"
20d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include "Utils.h"
21d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
22a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley#include <algorithm>
23fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <iomanip>
24731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include <map>
25b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley#include <set>
26fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <sstream>
27df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <string>
28731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
2995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <dirent.h>
30df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <errno.h>
3195376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley#include <fcntl.h>
32a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley#include <limits.h>
33fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence#include <openssl/sha.h>
347a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#include <selinux/android.h>
35df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <stdio.h>
36df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <sys/mount.h>
37df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <sys/stat.h>
38df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include <sys/types.h>
39731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
40480fcd2750c1d30f3397d1f3152519a11f60990bPaul Crowley#include <private/android_filesystem_config.h>
41480fcd2750c1d30f3397d1f3152519a11f60990bPaul Crowley
42731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence#include "cryptfs.h"
43731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
447a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#define EMULATED_USES_SELINUX 0
45be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#define MANAGE_MISC_DIRS 0
467a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey
47d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include <cutils/fs.h>
48989fec27690758ad1e6c521713f1a88c50c9c857Tao Bao#include <ext4_utils/ext4_crypt.h>
49989fec27690758ad1e6c521713f1a88c50c9c857Tao Bao#include <ext4_utils/key_control.h>
50d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
517e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/file.h>
526bf0547ccce72233bd465178b919fa7f15e48b45Elliott Hughes#include <android-base/logging.h>
537e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/stringprintf.h>
54731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
55d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeyusing android::base::StringPrintf;
560572080814ea5f7456d9feea05f936c858178159Paul Crowleyusing android::vold::kEmptyAuthentication;
57d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
5847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// NOTE: keep in sync with StorageManager
5947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkeystatic constexpr int FLAG_STORAGE_DE = 1 << 0;
6047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkeystatic constexpr int FLAG_STORAGE_CE = 1 << 1;
6147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
62731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrencenamespace {
637ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull
644d2d5244d68e907feb58167b3ee9b40288927247Paul Crowleyconst std::string device_key_dir = std::string() + DATA_MNT_POINT + e4crypt_unencrypted_folder;
65df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string device_key_path = device_key_dir + "/key";
66df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string device_key_temp = device_key_dir + "/temp";
675a06a6481bff8916bf366bf9e951ab5c6a405207Paul Lawrence
68df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys";
69df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string user_key_temp = user_key_dir + "/temp";
70285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley
71df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool s_global_de_initialized = false;
727b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence
73df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// Some users are ephemeral, don't try to wipe their keys from disk
74df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::set<userid_t> s_ephemeral_users;
75aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
76df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// Map user ids to key references
77df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_de_key_raw_refs;
78df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_ce_key_raw_refs;
7999360d76e548dcf4301669ad7763c90347615861Paul Crowley// TODO abolish this map, per b/26948053
80df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_ce_keys;
81731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
82df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// ext4enc:TODO get this const from somewhere good
83df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst int EXT4_KEY_DESCRIPTOR_SIZE = 8;
84fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
85df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// ext4enc:TODO Include structure from somewhere sensible
86df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// MUST be in sync with ext4_crypto.c in kernel
87df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconstexpr int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1;
88df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconstexpr int EXT4_AES_256_XTS_KEY_SIZE = 64;
89df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconstexpr int EXT4_MAX_KEY_SIZE = 64;
90df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystruct ext4_encryption_key {
91df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    uint32_t mode;
92df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    char raw[EXT4_MAX_KEY_SIZE];
93df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    uint32_t size;
94df528a7011b302c91579898c4a37361214ab05bbPaul Crowley};
95731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
96731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
9738132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowleystatic bool e4crypt_is_emulated() {
9838132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    return property_get_bool("persist.sys.emulate_fbe", false);
9938132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley}
10038132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley
10138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowleystatic const char* escape_null(const char* value) {
10238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    return (value == nullptr) ? "null" : value;
103731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
104731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
1059336348200758d067fed164368636521b4e58621Paul Crowley// Get raw keyref - used to make keyname and to pass to ioctl
106df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic std::string generate_key_ref(const char* key, int length) {
107fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_CTX c;
108fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
109fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Init(&c);
110fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Update(&c, key, length);
111285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    unsigned char key_ref1[SHA512_DIGEST_LENGTH];
112fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Final(key_ref1, &c);
113fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
114fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Init(&c);
115285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    SHA512_Update(&c, key_ref1, SHA512_DIGEST_LENGTH);
116285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    unsigned char key_ref2[SHA512_DIGEST_LENGTH];
117fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    SHA512_Final(key_ref2, &c);
118fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
119d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley    static_assert(EXT4_KEY_DESCRIPTOR_SIZE <= SHA512_DIGEST_LENGTH,
120df528a7011b302c91579898c4a37361214ab05bbPaul Crowley                  "Hash too short for descriptor");
121fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE);
122fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence}
123fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
124df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool fill_key(const std::string& key, ext4_encryption_key* ext4_key) {
1252199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley    if (key.size() != EXT4_AES_256_XTS_KEY_SIZE) {
1262199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley        LOG(ERROR) << "Wrong size key " << key.size();
1272199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley        return false;
1282199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley    }
129df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    static_assert(EXT4_AES_256_XTS_KEY_SIZE <= sizeof(ext4_key->raw), "Key too long!");
130a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    ext4_key->mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
131a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    ext4_key->size = key.size();
132a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    memset(ext4_key->raw, 0, sizeof(ext4_key->raw));
133a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    memcpy(ext4_key->raw, key.data(), key.size());
1342199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley    return true;
1359336348200758d067fed164368636521b4e58621Paul Crowley}
136fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence
137df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic std::string keyname(const std::string& raw_ref) {
138fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    std::ostringstream o;
1399336348200758d067fed164368636521b4e58621Paul Crowley    o << "ext4:";
140392c4dbdc1a0220f35d5c34d5c61f8a8197d175fYong Yao    for (unsigned char i : raw_ref) {
141d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley        o << std::hex << std::setw(2) << std::setfill('0') << (int)i;
142fd7db732434eb41fda69a353053bcb7aab259529Paul Lawrence    }
1439336348200758d067fed164368636521b4e58621Paul Crowley    return o.str();
1449336348200758d067fed164368636521b4e58621Paul Crowley}
145731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
1469336348200758d067fed164368636521b4e58621Paul Crowley// Get the keyring we store all keys in
147df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool e4crypt_keyring(key_serial_t* device_keyring) {
148a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "e4crypt", 0);
149a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (*device_keyring == -1) {
150d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley        PLOG(ERROR) << "Unable to find device keyring";
151d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley        return false;
152d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley    }
153d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley    return true;
1549336348200758d067fed164368636521b4e58621Paul Crowley}
155731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
156b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley// Install password into global keyring
157b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley// Return raw key reference for use in policy
158df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool install_key(const std::string& key, std::string* raw_ref) {
1592199069aca9df1064ced73fa5803bba524ab1f0dPaul Crowley    ext4_encryption_key ext4_key;
160a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!fill_key(key, &ext4_key)) return false;
161a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    *raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size);
162a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    auto ref = keyname(*raw_ref);
163d9b9295b8c2f17448f4eb3ea2c6f7d4a5c207c3fPaul Crowley    key_serial_t device_keyring;
164a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!e4crypt_keyring(&device_keyring)) return false;
165df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    key_serial_t key_id =
166df528a7011b302c91579898c4a37361214ab05bbPaul Crowley        add_key("logon", ref.c_str(), (void*)&ext4_key, sizeof(ext4_key), device_keyring);
167731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    if (key_id == -1) {
168285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
169b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        return false;
170731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence    }
171df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
172df528a7011b302c91579898c4a37361214ab05bbPaul Crowley               << " in process " << getpid();
17385e3d8cd50c540b1a4827bd179e3b8b609731e61Paul Lawrence
174b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    return true;
175731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence}
176731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
177b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowleystatic std::string get_de_key_path(userid_t user_id) {
178b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    return StringPrintf("%s/de/%d", user_key_dir.c_str(), user_id);
179b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley}
180b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley
181a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic std::string get_ce_key_directory_path(userid_t user_id) {
182a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    return StringPrintf("%s/ce/%d", user_key_dir.c_str(), user_id);
183a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley}
184a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley
185a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley// Returns the keys newest first
186a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic std::vector<std::string> get_ce_key_paths(const std::string& directory_path) {
187a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(directory_path.c_str()), closedir);
188a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!dirp) {
189a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        PLOG(ERROR) << "Unable to open ce key directory: " + directory_path;
190a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        return std::vector<std::string>();
191a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    }
192a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    std::vector<std::string> result;
193a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    for (;;) {
194a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        errno = 0;
195a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        auto const entry = readdir(dirp.get());
196a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (!entry) {
197a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            if (errno) {
198a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                PLOG(ERROR) << "Unable to read ce key directory: " + directory_path;
199a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                return std::vector<std::string>();
200a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            }
201a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            break;
202a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        }
203a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (entry->d_type != DT_DIR || entry->d_name[0] != 'c') {
204a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            LOG(DEBUG) << "Skipping non-key " << entry->d_name;
205a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            continue;
206a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        }
207a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        result.emplace_back(directory_path + "/" + entry->d_name);
208a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    }
209a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    std::sort(result.begin(), result.end());
210a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    std::reverse(result.begin(), result.end());
211a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    return result;
212a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley}
213a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley
214a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic std::string get_ce_key_current_path(const std::string& directory_path) {
215a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    return directory_path + "/current";
216a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley}
217a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley
218a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic bool get_ce_key_new_path(const std::string& directory_path,
219a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                                const std::vector<std::string>& paths,
220a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                                std::string *ce_key_path) {
221a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (paths.empty()) {
222a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        *ce_key_path = get_ce_key_current_path(directory_path);
223a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        return true;
224a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    }
225a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    for (unsigned int i = 0; i < UINT_MAX; i++) {
226a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        auto const candidate = StringPrintf("%s/cx%010u", directory_path.c_str(), i);
227a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (paths[0] < candidate) {
228a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            *ce_key_path = candidate;
229a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            return true;
230a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        }
231a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    }
232a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    return false;
233a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley}
234a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley
235a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley// Discard all keys but the named one; rename it to canonical name.
236a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley// No point in acting on errors in this; ignore them.
237a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic void fixate_user_ce_key(const std::string& directory_path, const std::string &to_fix,
238a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                               const std::vector<std::string>& paths) {
239a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    for (auto const other_path: paths) {
240a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (other_path != to_fix) {
241a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            android::vold::destroyKey(other_path);
242a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        }
243a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    }
244a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const current_path = get_ce_key_current_path(directory_path);
245a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (to_fix != current_path) {
246a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        LOG(DEBUG) << "Renaming " << to_fix << " to " << current_path;
247a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (rename(to_fix.c_str(), current_path.c_str()) != 0) {
248a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            PLOG(WARNING) << "Unable to rename " << to_fix << " to " << current_path;
249a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        }
250a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    }
251a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley}
252a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley
253a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleystatic bool read_and_fixate_user_ce_key(userid_t user_id,
254a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                                        const android::vold::KeyAuthentication& auth,
255a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                                        std::string *ce_key) {
256a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const directory_path = get_ce_key_directory_path(user_id);
257a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const paths = get_ce_key_paths(directory_path);
258a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    for (auto const ce_key_path: paths) {
259a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        LOG(DEBUG) << "Trying user CE key " << ce_key_path;
260a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (android::vold::retrieveKey(ce_key_path, auth, ce_key)) {
261a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            LOG(DEBUG) << "Successfully retrieved key";
262a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            fixate_user_ce_key(directory_path, ce_key_path, paths);
263a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            return true;
264a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        }
265a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    }
266a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    LOG(ERROR) << "Failed to find working ce key for user " << user_id;
267a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    return false;
268b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley}
269b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley
270df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool read_and_install_user_ce_key(userid_t user_id,
271df528a7011b302c91579898c4a37361214ab05bbPaul Crowley                                         const android::vold::KeyAuthentication& auth) {
272b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    if (s_ce_key_raw_refs.count(user_id) != 0) return true;
2730572080814ea5f7456d9feea05f936c858178159Paul Crowley    std::string ce_key;
274a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!read_and_fixate_user_ce_key(user_id, auth, &ce_key)) return false;
2750572080814ea5f7456d9feea05f936c858178159Paul Crowley    std::string ce_raw_ref;
276a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!install_key(ce_key, &ce_raw_ref)) return false;
2770572080814ea5f7456d9feea05f936c858178159Paul Crowley    s_ce_keys[user_id] = ce_key;
2780572080814ea5f7456d9feea05f936c858178159Paul Crowley    s_ce_key_raw_refs[user_id] = ce_raw_ref;
279b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    LOG(DEBUG) << "Installed ce key for user " << user_id;
2801ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    return true;
281285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley}
282285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley
283df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool prepare_dir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid) {
284b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    LOG(DEBUG) << "Preparing: " << dir;
28513ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley    if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
28613ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley        PLOG(ERROR) << "Failed to prepare " << dir;
287285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        return false;
288285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    }
28913ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley    return true;
29013ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley}
29113ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley
292be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeystatic bool destroy_dir(const std::string& dir) {
293be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    LOG(DEBUG) << "Destroying: " << dir;
294be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    if (rmdir(dir.c_str()) != 0 && errno != ENOENT) {
295be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        PLOG(ERROR) << "Failed to destroy " << dir;
296be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        return false;
297be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    }
298be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    return true;
299be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey}
300be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
301df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool random_key(std::string* key) {
302a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (android::vold::ReadRandomBytes(EXT4_AES_256_XTS_KEY_SIZE, *key) != 0) {
3031ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        // TODO status_t plays badly with PLOG, fix it.
3041ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley        LOG(ERROR) << "Random read failed";
305285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        return false;
306285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    }
307b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    return true;
308b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley}
309b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley
310df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool path_exists(const std::string& path) {
311b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    return access(path.c_str(), F_OK) == 0;
312b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley}
313b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley
314b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley// NB this assumes that there is only one thread listening for crypt commands, because
315b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley// it creates keys in a fixed location.
316df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool store_key(const std::string& key_path, const std::string& tmp_path,
317df528a7011b302c91579898c4a37361214ab05bbPaul Crowley                      const android::vold::KeyAuthentication& auth, const std::string& key) {
318b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    if (path_exists(key_path)) {
319b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        LOG(ERROR) << "Already exists, cannot create key at: " << key_path;
320b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        return false;
321b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    }
32238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (path_exists(tmp_path)) {
323df528a7011b302c91579898c4a37361214ab05bbPaul Crowley        android::vold::destroyKey(tmp_path);  // May be partially created so ignore errors
324b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    }
32538132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (!android::vold::storeKey(tmp_path, auth, key)) return false;
32638132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (rename(tmp_path.c_str(), key_path.c_str()) != 0) {
327b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        PLOG(ERROR) << "Unable to move new key to location: " << key_path;
328b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        return false;
329b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    }
330b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    LOG(DEBUG) << "Created key " << key_path;
331b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    return true;
332b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley}
333b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley
334b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowleystatic bool create_and_install_user_keys(userid_t user_id, bool create_ephemeral) {
335b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    std::string de_key, ce_key;
336a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!random_key(&de_key)) return false;
337a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!random_key(&ce_key)) return false;
338395039f0070abed5f6b3617786956ee3e62fe9b5Lenka Trochtova    if (create_ephemeral) {
339b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        // If the key should be created as ephemeral, don't store it.
340b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        s_ephemeral_users.insert(user_id);
34113ffd8ef7a02a1b4b4d9a74f45d4a5bb6b814313Paul Crowley    } else {
342a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        auto const directory_path = get_ce_key_directory_path(user_id);
343a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (!prepare_dir(directory_path, 0700, AID_ROOT, AID_ROOT)) return false;
344a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        auto const paths = get_ce_key_paths(directory_path);
345a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        std::string ce_key_path;
346a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
347a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (!store_key(ce_key_path, user_key_temp,
348a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                kEmptyAuthentication, ce_key)) return false;
349a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        fixate_user_ce_key(directory_path, ce_key_path, paths);
350a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        // Write DE key second; once this is written, all is good.
35138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley        if (!store_key(get_de_key_path(user_id), user_key_temp,
35238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley                kEmptyAuthentication, de_key)) return false;
35395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
354b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    std::string de_raw_ref;
355a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!install_key(de_key, &de_raw_ref)) return false;
356b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    s_de_key_raw_refs[user_id] = de_raw_ref;
357b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    std::string ce_raw_ref;
358a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!install_key(ce_key, &ce_raw_ref)) return false;
3590572080814ea5f7456d9feea05f936c858178159Paul Crowley    s_ce_keys[user_id] = ce_key;
360b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    s_ce_key_raw_refs[user_id] = ce_raw_ref;
361b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    LOG(DEBUG) << "Created keys for user " << user_id;
362285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    return true;
36395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley}
36495376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley
365df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t user_id,
366df528a7011b302c91579898c4a37361214ab05bbPaul Crowley                           std::string* raw_ref) {
367b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    auto refi = key_map.find(user_id);
368b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    if (refi == key_map.end()) {
369b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        LOG(ERROR) << "Cannot find key for " << user_id;
370b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        return false;
371b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    }
372a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    *raw_ref = refi->second;
373b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    return true;
374b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley}
375b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley
376df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool ensure_policy(const std::string& raw_ref, const std::string& path) {
377b45caafbccbb743c8b01a5287188969883dec377Eric Biggers    const char *contents_mode;
378b45caafbccbb743c8b01a5287188969883dec377Eric Biggers    const char *filenames_mode;
379b45caafbccbb743c8b01a5287188969883dec377Eric Biggers
380b45caafbccbb743c8b01a5287188969883dec377Eric Biggers    cryptfs_get_file_encryption_modes(&contents_mode, &filenames_mode);
381b45caafbccbb743c8b01a5287188969883dec377Eric Biggers
3826e410597343716924ed4943d1eabd3dea614d325Paul Lawrence    if (e4crypt_policy_ensure(path.c_str(),
3836e410597343716924ed4943d1eabd3dea614d325Paul Lawrence                              raw_ref.data(), raw_ref.size(),
384b45caafbccbb743c8b01a5287188969883dec377Eric Biggers                              contents_mode, filenames_mode) != 0) {
385b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        LOG(ERROR) << "Failed to set policy on: " << path;
386b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        return false;
38795376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
388b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    return true;
38995376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley}
39095376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley
391df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool is_numeric(const char* name) {
392df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    for (const char* p = name; *p != '\0'; p++) {
393df528a7011b302c91579898c4a37361214ab05bbPaul Crowley        if (!isdigit(*p)) return false;
394b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    }
395b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    return true;
396b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley}
397b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley
398b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowleystatic bool load_all_de_keys() {
399b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    auto de_dir = user_key_dir + "/de";
400df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(de_dir.c_str()), closedir);
401b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    if (!dirp) {
402b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        PLOG(ERROR) << "Unable to read de key directory";
403b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        return false;
404b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    }
405b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    for (;;) {
406b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        errno = 0;
407b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        auto entry = readdir(dirp.get());
408b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        if (!entry) {
409b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            if (errno) {
410b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley                PLOG(ERROR) << "Unable to read de key directory";
411b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley                return false;
412b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            }
413b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            break;
414b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        }
415b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        if (entry->d_type != DT_DIR || !is_numeric(entry->d_name)) {
416b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            LOG(DEBUG) << "Skipping non-de-key " << entry->d_name;
417b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            continue;
418b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        }
419b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        userid_t user_id = atoi(entry->d_name);
420b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        if (s_de_key_raw_refs.count(user_id) == 0) {
4210572080814ea5f7456d9feea05f936c858178159Paul Crowley            auto key_path = de_dir + "/" + entry->d_name;
4220572080814ea5f7456d9feea05f936c858178159Paul Crowley            std::string key;
423a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley            if (!android::vold::retrieveKey(key_path, kEmptyAuthentication, &key)) return false;
424b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            std::string raw_ref;
425a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley            if (!install_key(key, &raw_ref)) return false;
426b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            s_de_key_raw_refs[user_id] = raw_ref;
427b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            LOG(DEBUG) << "Installed de key for user " << user_id;
428b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        }
429b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    }
430b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    // ext4enc:TODO: go through all DE directories, ensure that all user dirs have the
431b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    // correct policy set on them, and that no rogue ones exist.
432b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    return true;
433b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley}
434b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley
435df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_initialize_global_de() {
43638132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    LOG(INFO) << "e4crypt_initialize_global_de";
437aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
43838132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (s_global_de_initialized) {
43938132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley        LOG(INFO) << "Already initialized";
44076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return true;
441aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    }
442aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
443b45caafbccbb743c8b01a5287188969883dec377Eric Biggers    const char *contents_mode;
444b45caafbccbb743c8b01a5287188969883dec377Eric Biggers    const char *filenames_mode;
445b45caafbccbb743c8b01a5287188969883dec377Eric Biggers    cryptfs_get_file_encryption_modes(&contents_mode, &filenames_mode);
446b45caafbccbb743c8b01a5287188969883dec377Eric Biggers    std::string modestring = std::string(contents_mode) + ":" + filenames_mode;
447b45caafbccbb743c8b01a5287188969883dec377Eric Biggers
4486e410597343716924ed4943d1eabd3dea614d325Paul Lawrence    std::string mode_filename = std::string("/data") + e4crypt_key_mode;
449b45caafbccbb743c8b01a5287188969883dec377Eric Biggers    if (!android::base::WriteStringToFile(modestring, mode_filename)) {
4506e410597343716924ed4943d1eabd3dea614d325Paul Lawrence        PLOG(ERROR) << "Cannot save type";
4516e410597343716924ed4943d1eabd3dea614d325Paul Lawrence        return false;
4526e410597343716924ed4943d1eabd3dea614d325Paul Lawrence    }
4536e410597343716924ed4943d1eabd3dea614d325Paul Lawrence
454aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    std::string device_key;
45538132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (path_exists(device_key_path)) {
45638132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley        if (!android::vold::retrieveKey(device_key_path,
457a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley                kEmptyAuthentication, &device_key)) return false;
45838132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    } else {
459aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence        LOG(INFO) << "Creating new key";
460a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley        if (!random_key(&device_key)) return false;
46138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley        if (!store_key(device_key_path, device_key_temp,
46276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley                kEmptyAuthentication, device_key)) return false;
463aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    }
464aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
465aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    std::string device_key_ref;
466a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!install_key(device_key, &device_key_ref)) {
467aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence        LOG(ERROR) << "Failed to install device key";
46876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
469aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    }
470aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
471f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence    std::string ref_filename = std::string("/data") + e4crypt_key_ref;
472f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence    if (!android::base::WriteStringToFile(device_key_ref, ref_filename)) {
473f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence        PLOG(ERROR) << "Cannot save key reference";
47476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
475aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    }
476aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
47738132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    s_global_de_initialized = true;
47876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
479aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence}
480aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
48176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_init_user0() {
4828fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley    LOG(DEBUG) << "e4crypt_init_user0";
4838fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley    if (e4crypt_is_native()) {
48476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false;
48576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false;
48676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false;
487a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (!path_exists(get_de_key_path(0))) {
48876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!create_and_install_user_keys(0, false)) return false;
4898fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley        }
49047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        // TODO: switch to loading only DE_0 here once framework makes
49147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        // explicit calls to install DE keys for secondary users
49276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!load_all_de_keys()) return false;
4938fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley    }
49447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    // We can only safely prepare DE storage here, since CE keys are probably
49547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    // entangled with user credentials.  The framework will always prepare CE
49647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    // storage once CE keys are installed.
49776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    if (!e4crypt_prepare_user_storage(nullptr, 0, 0, FLAG_STORAGE_DE)) {
49847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        LOG(ERROR) << "Failed to prepare user 0 storage";
49976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
50047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    }
5010754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey
5020754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey    // If this is a non-FBE device that recently left an emulated mode,
5030754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey    // restore user data directories to known-good state.
5040754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey    if (!e4crypt_is_native() && !e4crypt_is_emulated()) {
505695d9282862bac4fb4034ebb2d5b089b8ff9c4a3Jeff Sharkey        e4crypt_unlock_user_key(0, 0, "!", "!");
5060754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey    }
5070754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey
50876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
5098fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley}
5108fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley
51176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
512285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial;
513ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley    if (!e4crypt_is_native()) {
51476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return true;
515ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley    }
516b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    // FIXME test for existence of key that is not loaded yet
517b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    if (s_ce_key_raw_refs.count(user_id) != 0) {
518df528a7011b302c91579898c4a37361214ab05bbPaul Crowley        LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for " << user_id
519df528a7011b302c91579898c4a37361214ab05bbPaul Crowley                   << " serial " << serial;
520285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        // FIXME should we fail the command?
52176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return true;
52295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
523b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    if (!create_and_install_user_keys(user_id, ephemeral)) {
52476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
525d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
52676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
527d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
528d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
529fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggersstatic bool evict_key(const std::string &raw_ref) {
5307ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    auto ref = keyname(raw_ref);
5317ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    key_serial_t device_keyring;
532fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers    if (!e4crypt_keyring(&device_keyring)) return false;
5337ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
5347ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull
535fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers    // Unlink the key from the keyring.  Prefer unlinking to revoking or
536fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers    // invalidating, since unlinking is actually no less secure currently, and
537fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers    // it avoids bugs in certain kernel versions where the keyring key is
538fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers    // referenced from places it shouldn't be.
539fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers    if (keyctl_unlink(key_serial, device_keyring) != 0) {
540fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers        PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
541fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers        return false;
542fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers    }
543fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers    LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref;
544fa4039b1620987d82f119576cbdfaf503cd4e2b5Eric Biggers    return true;
5457ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull}
5467ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull
5477ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scullstatic bool evict_ce_key(userid_t user_id) {
5487ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    s_ce_keys.erase(user_id);
5497ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    bool success = true;
5507ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    std::string raw_ref;
5517ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    // If we haven't loaded the CE key, no need to evict it.
5527ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    if (lookup_key_ref(s_ce_key_raw_refs, user_id, &raw_ref)) {
5537ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull        success &= evict_key(raw_ref);
5547ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    }
5557ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    s_ce_key_raw_refs.erase(user_id);
5567ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    return success;
5577ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull}
5587ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull
55976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_destroy_user_key(userid_t user_id) {
5601ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")";
561ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley    if (!e4crypt_is_native()) {
56276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return true;
563ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley    }
564b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    bool success = true;
565b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    std::string raw_ref;
5667ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    success &= evict_ce_key(user_id);
5677ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    success &= lookup_key_ref(s_de_key_raw_refs, user_id, &raw_ref) && evict_key(raw_ref);
5680572080814ea5f7456d9feea05f936c858178159Paul Crowley    s_de_key_raw_refs.erase(user_id);
569b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    auto it = s_ephemeral_users.find(user_id);
570b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    if (it != s_ephemeral_users.end()) {
571b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        s_ephemeral_users.erase(it);
5721ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    } else {
573a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        for (auto const path: get_ce_key_paths(get_ce_key_directory_path(user_id))) {
574a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            success &= android::vold::destroyKey(path);
575a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        }
576ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley        auto de_key_path = get_de_key_path(user_id);
577ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley        if (path_exists(de_key_path)) {
578ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley            success &= android::vold::destroyKey(de_key_path);
579ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley        } else {
580ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley            LOG(INFO) << "Not present so not erasing: " << de_key_path;
581ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley        }
582b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley    }
58376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return success;
584b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley}
585d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
58676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleystatic bool emulated_lock(const std::string& path) {
5877a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (chmod(path.c_str(), 0000) != 0) {
5887a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(ERROR) << "Failed to chmod " << path;
58976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
5907a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
5917a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX
5927a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
5937a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(WARNING) << "Failed to setfilecon " << path;
59476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
5957a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
5967a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif
59776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
5987a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey}
5997a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey
60076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleystatic bool emulated_unlock(const std::string& path, mode_t mode) {
6017a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (chmod(path.c_str(), mode) != 0) {
6027a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(ERROR) << "Failed to chmod " << path;
603a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley        // FIXME temporary workaround for b/26713622
60476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (e4crypt_is_emulated()) return false;
6057a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
6067a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX
6077a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
6087a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(WARNING) << "Failed to restorecon " << path;
609a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley        // FIXME temporary workaround for b/26713622
61076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (e4crypt_is_emulated()) return false;
6117a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
6127a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif
61376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
6147a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey}
6157a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey
616df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool parse_hex(const char* hex, std::string* result) {
6170572080814ea5f7456d9feea05f936c858178159Paul Crowley    if (strcmp("!", hex) == 0) {
618a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley        *result = "";
6190572080814ea5f7456d9feea05f936c858178159Paul Crowley        return true;
6200572080814ea5f7456d9feea05f936c858178159Paul Crowley    }
621a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (android::vold::HexToStr(hex, *result) != 0) {
622df528a7011b302c91579898c4a37361214ab05bbPaul Crowley        LOG(ERROR) << "Invalid FBE hex string";  // Don't log the string for security reasons
6230572080814ea5f7456d9feea05f936c858178159Paul Crowley        return false;
6240572080814ea5f7456d9feea05f936c858178159Paul Crowley    }
6250572080814ea5f7456d9feea05f936c858178159Paul Crowley    return true;
6260572080814ea5f7456d9feea05f936c858178159Paul Crowley}
6270572080814ea5f7456d9feea05f936c858178159Paul Crowley
628a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleybool e4crypt_add_user_key_auth(userid_t user_id, int serial, const char* token_hex,
629a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                          const char* secret_hex) {
630a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    LOG(DEBUG) << "e4crypt_add_user_key_auth " << user_id << " serial=" << serial
631df528a7011b302c91579898c4a37361214ab05bbPaul Crowley               << " token_present=" << (strcmp(token_hex, "!") != 0);
63276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    if (!e4crypt_is_native()) return true;
63376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    if (s_ephemeral_users.count(user_id) != 0) return true;
634a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    std::string token, secret;
635a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!parse_hex(token_hex, &token)) return false;
636a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!parse_hex(secret_hex, &secret)) return false;
637a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto auth = secret.empty() ? kEmptyAuthentication
638a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                                   : android::vold::KeyAuthentication(token, secret);
6390572080814ea5f7456d9feea05f936c858178159Paul Crowley    auto it = s_ce_keys.find(user_id);
6400572080814ea5f7456d9feea05f936c858178159Paul Crowley    if (it == s_ce_keys.end()) {
6410572080814ea5f7456d9feea05f936c858178159Paul Crowley        LOG(ERROR) << "Key not loaded into memory, can't change for user " << user_id;
64276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
6430572080814ea5f7456d9feea05f936c858178159Paul Crowley    }
6440572080814ea5f7456d9feea05f936c858178159Paul Crowley    auto ce_key = it->second;
645a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const directory_path = get_ce_key_directory_path(user_id);
646a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const paths = get_ce_key_paths(directory_path);
647a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    std::string ce_key_path;
648a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
649a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!store_key(ce_key_path, user_key_temp, auth, ce_key)) return false;
650a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    return true;
651a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley}
652a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley
653a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleybool e4crypt_fixate_newest_user_key_auth(userid_t user_id) {
654a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    LOG(DEBUG) << "e4crypt_fixate_newest_user_key_auth " << user_id;
655a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!e4crypt_is_native()) return true;
65625a713873c8f8d37f7ebbadfbf1ebfaf4bac106bPaul Crowley    if (s_ephemeral_users.count(user_id) != 0) return true;
657a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const directory_path = get_ce_key_directory_path(user_id);
658a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const paths = get_ce_key_paths(directory_path);
659a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (paths.empty()) {
660a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        LOG(ERROR) << "No ce keys present, cannot fixate for user " << user_id;
661a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        return false;
662a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    }
663a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    fixate_user_ce_key(directory_path, paths[0], paths);
66476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
6650572080814ea5f7456d9feea05f936c858178159Paul Crowley}
6660572080814ea5f7456d9feea05f936c858178159Paul Crowley
66747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// TODO: rename to 'install' for consistency, and take flags to know which keys to install
668df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token_hex,
669df528a7011b302c91579898c4a37361214ab05bbPaul Crowley                             const char* secret_hex) {
670df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " serial=" << serial
671df528a7011b302c91579898c4a37361214ab05bbPaul Crowley               << " token_present=" << (strcmp(token_hex, "!") != 0);
672fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    if (e4crypt_is_native()) {
6730572080814ea5f7456d9feea05f936c858178159Paul Crowley        if (s_ce_key_raw_refs.count(user_id) != 0) {
6740572080814ea5f7456d9feea05f936c858178159Paul Crowley            LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id;
67576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            return true;
6760572080814ea5f7456d9feea05f936c858178159Paul Crowley        }
6770572080814ea5f7456d9feea05f936c858178159Paul Crowley        std::string token, secret;
678a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley        if (!parse_hex(token_hex, &token)) return false;
679a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley        if (!parse_hex(secret_hex, &secret)) return false;
6800572080814ea5f7456d9feea05f936c858178159Paul Crowley        android::vold::KeyAuthentication auth(token, secret);
6810572080814ea5f7456d9feea05f936c858178159Paul Crowley        if (!read_and_install_user_ce_key(user_id, auth)) {
6828fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley            LOG(ERROR) << "Couldn't read key for " << user_id;
68376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            return false;
684d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        }
685fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    } else {
686fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // When in emulation mode, we just use chmod. However, we also
687fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // unlock directories when not in emulation mode, to bring devices
688fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // back into a known-good state.
68976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
690df528a7011b302c91579898c4a37361214ab05bbPaul Crowley            !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) ||
691be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            !emulated_unlock(android::vold::BuildDataMediaCePath(nullptr, user_id), 0770) ||
692be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            !emulated_unlock(android::vold::BuildDataUserCePath(nullptr, user_id), 0771)) {
6937a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey            LOG(ERROR) << "Failed to unlock user " << user_id;
69476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            return false;
695fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        }
696d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
69776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
698d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
699d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
70047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// TODO: rename to 'evict' for consistency
70176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_lock_user_key(userid_t user_id) {
7027ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull    LOG(DEBUG) << "e4crypt_lock_user_key " << user_id;
703fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    if (e4crypt_is_native()) {
7047ec25c715f835c741d51a7ec0fd7b28220543364Andrew Scull        return evict_ce_key(user_id);
705fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    } else if (e4crypt_is_emulated()) {
706d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        // When in emulation mode, we just use chmod
70776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!emulated_lock(android::vold::BuildDataSystemCePath(user_id)) ||
708df528a7011b302c91579898c4a37361214ab05bbPaul Crowley            !emulated_lock(android::vold::BuildDataMiscCePath(user_id)) ||
709be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            !emulated_lock(android::vold::BuildDataMediaCePath(nullptr, user_id)) ||
710be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            !emulated_lock(android::vold::BuildDataUserCePath(nullptr, user_id))) {
71157eedbf8cbd21899a3395ce6f153cd0e05898f3bPaul Crowley            LOG(ERROR) << "Failed to lock user " << user_id;
71276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            return false;
713d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        }
714d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
715fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey
71676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
717d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
718d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
719df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial,
720be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        int flags) {
72147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    LOG(DEBUG) << "e4crypt_prepare_user_storage for volume " << escape_null(volume_uuid)
722df528a7011b302c91579898c4a37361214ab05bbPaul Crowley               << ", user " << user_id << ", serial " << serial << ", flags " << flags;
72347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
72447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    if (flags & FLAG_STORAGE_DE) {
725be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // DE_sys key
726be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
727be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
728be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
729be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
730be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // DE_n key
73147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
73247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
73347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
73447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
735be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
736be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#if MANAGE_MISC_DIRS
737be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM),
738be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey                multiuser_get_uid(user_id, AID_EVERYBODY))) return false;
739be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#endif
740be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
741be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
74276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
74376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false;
74476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
745d1ee944f0839d60b014722c7facbb4a66bd4f2c3Calin Juravle
746be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // For now, FBE is only supported on internal storage
747be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (e4crypt_is_native() && volume_uuid == nullptr) {
74847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey            std::string de_raw_ref;
749a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley            if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_raw_ref)) return false;
75076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(de_raw_ref, system_de_path)) return false;
75176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(de_raw_ref, misc_de_path)) return false;
75276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(de_raw_ref, user_de_path)) return false;
75347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        }
75447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    }
75547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
75647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    if (flags & FLAG_STORAGE_CE) {
757be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // CE_n key
75847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
75947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
760be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id);
761be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id);
76247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
76376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
76476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false;
76576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
76676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
76747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
768be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // For now, FBE is only supported on internal storage
769be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (e4crypt_is_native() && volume_uuid == nullptr) {
77047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey            std::string ce_raw_ref;
771a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley            if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_raw_ref)) return false;
77276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(ce_raw_ref, system_ce_path)) return false;
77376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(ce_raw_ref, misc_ce_path)) return false;
77476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(ce_raw_ref, media_ce_path)) return false;
77576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(ce_raw_ref, user_ce_path)) return false;
776d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey
777d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            // Now that credentials have been installed, we can run restorecon
778d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            // over these paths
779d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            // NOTE: these paths need to be kept in sync with libselinux
780d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            android::vold::RestoreconRecursive(system_ce_path);
781d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            android::vold::RestoreconRecursive(misc_ce_path);
78247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        }
783d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
784d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
78576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
786d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
787be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
788be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeybool e4crypt_destroy_user_storage(const char* volume_uuid, userid_t user_id, int flags) {
789be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    LOG(DEBUG) << "e4crypt_destroy_user_storage for volume " << escape_null(volume_uuid)
790be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey               << ", user " << user_id << ", flags " << flags;
791be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    bool res = true;
792be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
793be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    if (flags & FLAG_STORAGE_DE) {
794be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // DE_sys key
795be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
796be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
797be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
798be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
799be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // DE_n key
800be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
801be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
802be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
803be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
804be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (volume_uuid == nullptr) {
805be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(system_legacy_path);
806be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#if MANAGE_MISC_DIRS
807be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(misc_legacy_path);
808be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#endif
809be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(profiles_de_path);
810be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(system_de_path);
811be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(misc_de_path);
812be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        }
813be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        res &= destroy_dir(user_de_path);
814be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    }
815be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
816be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    if (flags & FLAG_STORAGE_CE) {
817be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // CE_n key
818be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
819be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
820be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id);
821be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id);
822be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
823be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (volume_uuid == nullptr) {
824be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(system_ce_path);
825be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(misc_ce_path);
826be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        }
827be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        res &= destroy_dir(media_ce_path);
828be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        res &= destroy_dir(user_ce_path);
829be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    }
830be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
831be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    return res;
832be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey}
833f8d604caf3f9bf0aed9ef070c40933a94016232bRubin Xu
834f8d604caf3f9bf0aed9ef070c40933a94016232bRubin Xubool e4crypt_secdiscard(const char* path) {
835f8d604caf3f9bf0aed9ef070c40933a94016232bRubin Xu    return android::vold::runSecdiscardSingle(std::string(path));
836f8d604caf3f9bf0aed9ef070c40933a94016232bRubin Xu}
837