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"
4347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey#include "ext4_crypt.h"
44df528a7011b302c91579898c4a37361214ab05bbPaul Crowley#include "key_control.h"
45731a7a242df6cc3441ac82b4f9521546fac5ac2dPaul Lawrence
467a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#define EMULATED_USES_SELINUX 0
47be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#define MANAGE_MISC_DIRS 0
487a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey
49d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey#include <cutils/fs.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 {
634d2d5244d68e907feb58167b3ee9b40288927247Paul Crowleyconst std::string device_key_dir = std::string() + DATA_MNT_POINT + e4crypt_unencrypted_folder;
64df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string device_key_path = device_key_dir + "/key";
65df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string device_key_temp = device_key_dir + "/temp";
665a06a6481bff8916bf366bf9e951ab5c6a405207Paul Lawrence
67df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys";
68df528a7011b302c91579898c4a37361214ab05bbPaul Crowleyconst std::string user_key_temp = user_key_dir + "/temp";
69285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley
70df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool s_global_de_initialized = false;
717b6b565fa0d3658be8dc021f1beee5024d54b8c0Paul Lawrence
72df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// Some users are ephemeral, don't try to wipe their keys from disk
73df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::set<userid_t> s_ephemeral_users;
74aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
75df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// Map user ids to key references
76df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_de_key_raw_refs;
77df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystd::map<userid_t, std::string> s_ce_key_raw_refs;
78df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// TODO abolish this map. Keys should not be long-lived in user memory, only kernel memory.
79df528a7011b302c91579898c4a37361214ab05bbPaul Crowley// See 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:";
140df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    for (auto 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) {
3776e410597343716924ed4943d1eabd3dea614d325Paul Lawrence    if (e4crypt_policy_ensure(path.c_str(),
3786e410597343716924ed4943d1eabd3dea614d325Paul Lawrence                              raw_ref.data(), raw_ref.size(),
3796e410597343716924ed4943d1eabd3dea614d325Paul Lawrence                              cryptfs_get_file_encryption_mode()) != 0) {
380b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        LOG(ERROR) << "Failed to set policy on: " << path;
381b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        return false;
38295376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
383b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    return true;
38495376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley}
38595376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley
386df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool is_numeric(const char* name) {
387df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    for (const char* p = name; *p != '\0'; p++) {
388df528a7011b302c91579898c4a37361214ab05bbPaul Crowley        if (!isdigit(*p)) return false;
389b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    }
390b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    return true;
391b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley}
392b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley
393b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowleystatic bool load_all_de_keys() {
394b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    auto de_dir = user_key_dir + "/de";
395df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(de_dir.c_str()), closedir);
396b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    if (!dirp) {
397b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        PLOG(ERROR) << "Unable to read de key directory";
398b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        return false;
399b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    }
400b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    for (;;) {
401b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        errno = 0;
402b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        auto entry = readdir(dirp.get());
403b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        if (!entry) {
404b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            if (errno) {
405b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley                PLOG(ERROR) << "Unable to read de key directory";
406b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley                return false;
407b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            }
408b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            break;
409b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        }
410b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        if (entry->d_type != DT_DIR || !is_numeric(entry->d_name)) {
411b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            LOG(DEBUG) << "Skipping non-de-key " << entry->d_name;
412b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            continue;
413b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        }
414b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        userid_t user_id = atoi(entry->d_name);
415b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        if (s_de_key_raw_refs.count(user_id) == 0) {
4160572080814ea5f7456d9feea05f936c858178159Paul Crowley            auto key_path = de_dir + "/" + entry->d_name;
4170572080814ea5f7456d9feea05f936c858178159Paul Crowley            std::string key;
418a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley            if (!android::vold::retrieveKey(key_path, kEmptyAuthentication, &key)) return false;
419b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            std::string raw_ref;
420a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley            if (!install_key(key, &raw_ref)) return false;
421b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            s_de_key_raw_refs[user_id] = raw_ref;
422b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley            LOG(DEBUG) << "Installed de key for user " << user_id;
423b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley        }
424b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    }
425b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    // ext4enc:TODO: go through all DE directories, ensure that all user dirs have the
426b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    // correct policy set on them, and that no rogue ones exist.
427b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    return true;
428b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley}
429b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley
430df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_initialize_global_de() {
43138132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    LOG(INFO) << "e4crypt_initialize_global_de";
432aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
43338132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (s_global_de_initialized) {
43438132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley        LOG(INFO) << "Already initialized";
43576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return true;
436aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    }
437aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
4386e410597343716924ed4943d1eabd3dea614d325Paul Lawrence    std::string mode_filename = std::string("/data") + e4crypt_key_mode;
4396e410597343716924ed4943d1eabd3dea614d325Paul Lawrence    std::string mode = cryptfs_get_file_encryption_mode();
4406e410597343716924ed4943d1eabd3dea614d325Paul Lawrence    if (!android::base::WriteStringToFile(mode, mode_filename)) {
4416e410597343716924ed4943d1eabd3dea614d325Paul Lawrence        PLOG(ERROR) << "Cannot save type";
4426e410597343716924ed4943d1eabd3dea614d325Paul Lawrence        return false;
4436e410597343716924ed4943d1eabd3dea614d325Paul Lawrence    }
4446e410597343716924ed4943d1eabd3dea614d325Paul Lawrence
445aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    std::string device_key;
44638132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    if (path_exists(device_key_path)) {
44738132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley        if (!android::vold::retrieveKey(device_key_path,
448a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley                kEmptyAuthentication, &device_key)) return false;
44938132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    } else {
450aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence        LOG(INFO) << "Creating new key";
451a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley        if (!random_key(&device_key)) return false;
45238132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley        if (!store_key(device_key_path, device_key_temp,
45376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley                kEmptyAuthentication, device_key)) return false;
454aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    }
455aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
456aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    std::string device_key_ref;
457a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!install_key(device_key, &device_key_ref)) {
458aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence        LOG(ERROR) << "Failed to install device key";
45976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
460aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    }
461aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
462f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence    std::string ref_filename = std::string("/data") + e4crypt_key_ref;
463f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence    if (!android::base::WriteStringToFile(device_key_ref, ref_filename)) {
464f10544df96652ebe457c93a91075da0b3bc6b550Paul Lawrence        PLOG(ERROR) << "Cannot save key reference";
46576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
466aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence    }
467aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
46838132a1f667412d6b08ae90cc64a011d76906cc0Paul Crowley    s_global_de_initialized = true;
46976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
470aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence}
471aec34dfb1d3988c1154534a24aacd950193f8f9fPaul Lawrence
47276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_init_user0() {
4738fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley    LOG(DEBUG) << "e4crypt_init_user0";
4748fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley    if (e4crypt_is_native()) {
47576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false;
47676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false;
47776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false;
478a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        if (!path_exists(get_de_key_path(0))) {
47976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!create_and_install_user_keys(0, false)) return false;
4808fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley        }
48147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        // TODO: switch to loading only DE_0 here once framework makes
48247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        // explicit calls to install DE keys for secondary users
48376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!load_all_de_keys()) return false;
4848fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley    }
48547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    // We can only safely prepare DE storage here, since CE keys are probably
48647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    // entangled with user credentials.  The framework will always prepare CE
48747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    // storage once CE keys are installed.
48876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    if (!e4crypt_prepare_user_storage(nullptr, 0, 0, FLAG_STORAGE_DE)) {
48947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        LOG(ERROR) << "Failed to prepare user 0 storage";
49076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
49147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    }
4920754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey
4930754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey    // If this is a non-FBE device that recently left an emulated mode,
4940754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey    // restore user data directories to known-good state.
4950754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey    if (!e4crypt_is_native() && !e4crypt_is_emulated()) {
496695d9282862bac4fb4034ebb2d5b089b8ff9c4a3Jeff Sharkey        e4crypt_unlock_user_key(0, 0, "!", "!");
4970754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey    }
4980754a45539de941e278c82898d83d26b6ba95b5eJeff Sharkey
49976107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
5008fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley}
5018fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley
50276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
503285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley    LOG(DEBUG) << "e4crypt_vold_create_user_key for " << user_id << " serial " << serial;
504ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley    if (!e4crypt_is_native()) {
50576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return true;
506ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley    }
507b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    // FIXME test for existence of key that is not loaded yet
508b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    if (s_ce_key_raw_refs.count(user_id) != 0) {
509df528a7011b302c91579898c4a37361214ab05bbPaul Crowley        LOG(ERROR) << "Already exists, can't e4crypt_vold_create_user_key for " << user_id
510df528a7011b302c91579898c4a37361214ab05bbPaul Crowley                   << " serial " << serial;
511285956fe11de221f850e5bf63b071bd8f53bfd10Paul Crowley        // FIXME should we fail the command?
51276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return true;
51395376d612c91236c8cd751b9af02c9aa57f4870fPaul Crowley    }
514b92f83c0512bfb93e85d6cd8d6efd6681017664cPaul Crowley    if (!create_and_install_user_keys(user_id, ephemeral)) {
51576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
516d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
51776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
518d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
519d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
52076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_destroy_user_key(userid_t user_id) {
5211ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")";
522ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley    if (!e4crypt_is_native()) {
52376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return true;
524ea62e26ad3cc3e6a522cb4a711f34848ba65385aPaul Crowley    }
525b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    bool success = true;
5260572080814ea5f7456d9feea05f936c858178159Paul Crowley    s_ce_keys.erase(user_id);
527b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    std::string raw_ref;
5280572080814ea5f7456d9feea05f936c858178159Paul Crowley    s_ce_key_raw_refs.erase(user_id);
5290572080814ea5f7456d9feea05f936c858178159Paul Crowley    s_de_key_raw_refs.erase(user_id);
530b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    auto it = s_ephemeral_users.find(user_id);
531b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley    if (it != s_ephemeral_users.end()) {
532b1f3d242dd095b307a756fda2798e441e791e039Paul Crowley        s_ephemeral_users.erase(it);
5331ef255816c50e462acc23383a9ff747c5f55c4ffPaul Crowley    } else {
534a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        for (auto const path: get_ce_key_paths(get_ce_key_directory_path(user_id))) {
535a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley            success &= android::vold::destroyKey(path);
536a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        }
537ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley        auto de_key_path = get_de_key_path(user_id);
538ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley        if (path_exists(de_key_path)) {
539ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley            success &= android::vold::destroyKey(de_key_path);
540ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley        } else {
541ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley            LOG(INFO) << "Not present so not erasing: " << de_key_path;
542ab0b56aef33f04f4d7a352d5790b2d9cd9e7d6d3Paul Crowley        }
543b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley    }
54476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return success;
545b33e8873ea78b92e536aa33f48130a91ca150f0cPaul Crowley}
546d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
54776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleystatic bool emulated_lock(const std::string& path) {
5487a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (chmod(path.c_str(), 0000) != 0) {
5497a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(ERROR) << "Failed to chmod " << path;
55076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
5517a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
5527a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX
5537a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
5547a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(WARNING) << "Failed to setfilecon " << path;
55576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
5567a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
5577a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif
55876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
5597a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey}
5607a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey
56176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleystatic bool emulated_unlock(const std::string& path, mode_t mode) {
5627a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (chmod(path.c_str(), mode) != 0) {
5637a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(ERROR) << "Failed to chmod " << path;
564a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley        // FIXME temporary workaround for b/26713622
56576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (e4crypt_is_emulated()) return false;
5667a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
5677a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#if EMULATED_USES_SELINUX
5687a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
5697a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey        PLOG(WARNING) << "Failed to restorecon " << path;
570a042cb5761f4bf954645b404ae5bb0a0d5b583fdPaul Crowley        // FIXME temporary workaround for b/26713622
57176107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (e4crypt_is_emulated()) return false;
5727a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey    }
5737a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey#endif
57476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
5757a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey}
5767a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey
577df528a7011b302c91579898c4a37361214ab05bbPaul Crowleystatic bool parse_hex(const char* hex, std::string* result) {
5780572080814ea5f7456d9feea05f936c858178159Paul Crowley    if (strcmp("!", hex) == 0) {
579a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley        *result = "";
5800572080814ea5f7456d9feea05f936c858178159Paul Crowley        return true;
5810572080814ea5f7456d9feea05f936c858178159Paul Crowley    }
582a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (android::vold::HexToStr(hex, *result) != 0) {
583df528a7011b302c91579898c4a37361214ab05bbPaul Crowley        LOG(ERROR) << "Invalid FBE hex string";  // Don't log the string for security reasons
5840572080814ea5f7456d9feea05f936c858178159Paul Crowley        return false;
5850572080814ea5f7456d9feea05f936c858178159Paul Crowley    }
5860572080814ea5f7456d9feea05f936c858178159Paul Crowley    return true;
5870572080814ea5f7456d9feea05f936c858178159Paul Crowley}
5880572080814ea5f7456d9feea05f936c858178159Paul Crowley
589a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleybool e4crypt_add_user_key_auth(userid_t user_id, int serial, const char* token_hex,
590a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                          const char* secret_hex) {
591a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    LOG(DEBUG) << "e4crypt_add_user_key_auth " << user_id << " serial=" << serial
592df528a7011b302c91579898c4a37361214ab05bbPaul Crowley               << " token_present=" << (strcmp(token_hex, "!") != 0);
59376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    if (!e4crypt_is_native()) return true;
59476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    if (s_ephemeral_users.count(user_id) != 0) return true;
595a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    std::string token, secret;
596a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley    if (!parse_hex(token_hex, &token)) return false;
597a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!parse_hex(secret_hex, &secret)) return false;
598a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto auth = secret.empty() ? kEmptyAuthentication
599a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley                                   : android::vold::KeyAuthentication(token, secret);
6000572080814ea5f7456d9feea05f936c858178159Paul Crowley    auto it = s_ce_keys.find(user_id);
6010572080814ea5f7456d9feea05f936c858178159Paul Crowley    if (it == s_ce_keys.end()) {
6020572080814ea5f7456d9feea05f936c858178159Paul Crowley        LOG(ERROR) << "Key not loaded into memory, can't change for user " << user_id;
60376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        return false;
6040572080814ea5f7456d9feea05f936c858178159Paul Crowley    }
6050572080814ea5f7456d9feea05f936c858178159Paul Crowley    auto ce_key = it->second;
606a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const directory_path = get_ce_key_directory_path(user_id);
607a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const paths = get_ce_key_paths(directory_path);
608a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    std::string ce_key_path;
609a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
610a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!store_key(ce_key_path, user_key_temp, auth, ce_key)) return false;
611a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    return true;
612a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley}
613a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley
614a363036b44f7f140aa9a943578f56abff5880a60Paul Crowleybool e4crypt_fixate_newest_user_key_auth(userid_t user_id) {
615a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    LOG(DEBUG) << "e4crypt_fixate_newest_user_key_auth " << user_id;
616a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (!e4crypt_is_native()) return true;
61725a713873c8f8d37f7ebbadfbf1ebfaf4bac106bPaul Crowley    if (s_ephemeral_users.count(user_id) != 0) return true;
618a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const directory_path = get_ce_key_directory_path(user_id);
619a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    auto const paths = get_ce_key_paths(directory_path);
620a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    if (paths.empty()) {
621a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        LOG(ERROR) << "No ce keys present, cannot fixate for user " << user_id;
622a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley        return false;
623a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    }
624a363036b44f7f140aa9a943578f56abff5880a60Paul Crowley    fixate_user_ce_key(directory_path, paths[0], paths);
62576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
6260572080814ea5f7456d9feea05f936c858178159Paul Crowley}
6270572080814ea5f7456d9feea05f936c858178159Paul Crowley
62847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// TODO: rename to 'install' for consistency, and take flags to know which keys to install
629df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token_hex,
630df528a7011b302c91579898c4a37361214ab05bbPaul Crowley                             const char* secret_hex) {
631df528a7011b302c91579898c4a37361214ab05bbPaul Crowley    LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " serial=" << serial
632df528a7011b302c91579898c4a37361214ab05bbPaul Crowley               << " token_present=" << (strcmp(token_hex, "!") != 0);
633fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    if (e4crypt_is_native()) {
6340572080814ea5f7456d9feea05f936c858178159Paul Crowley        if (s_ce_key_raw_refs.count(user_id) != 0) {
6350572080814ea5f7456d9feea05f936c858178159Paul Crowley            LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id;
63676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            return true;
6370572080814ea5f7456d9feea05f936c858178159Paul Crowley        }
6380572080814ea5f7456d9feea05f936c858178159Paul Crowley        std::string token, secret;
639a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley        if (!parse_hex(token_hex, &token)) return false;
640a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley        if (!parse_hex(secret_hex, &secret)) return false;
6410572080814ea5f7456d9feea05f936c858178159Paul Crowley        android::vold::KeyAuthentication auth(token, secret);
6420572080814ea5f7456d9feea05f936c858178159Paul Crowley        if (!read_and_install_user_ce_key(user_id, auth)) {
6438fb12fd8359a9af7228e05a37cf0ef59f43d6991Paul Crowley            LOG(ERROR) << "Couldn't read key for " << user_id;
64476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            return false;
645d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        }
646fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    } else {
647fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // When in emulation mode, we just use chmod. However, we also
648fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // unlock directories when not in emulation mode, to bring devices
649fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // back into a known-good state.
65076107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
651df528a7011b302c91579898c4a37361214ab05bbPaul Crowley            !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) ||
652be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            !emulated_unlock(android::vold::BuildDataMediaCePath(nullptr, user_id), 0770) ||
653be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            !emulated_unlock(android::vold::BuildDataUserCePath(nullptr, user_id), 0771)) {
6547a9dd95cbc969fa21dfe4c1bbcac3315e47d81a4Jeff Sharkey            LOG(ERROR) << "Failed to unlock user " << user_id;
65576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            return false;
656fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        }
657d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
65876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
659d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
660d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
66147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey// TODO: rename to 'evict' for consistency
66276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowleybool e4crypt_lock_user_key(userid_t user_id) {
663fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    if (e4crypt_is_native()) {
664fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey        // TODO: remove from kernel keyring
665fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    } else if (e4crypt_is_emulated()) {
666d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        // When in emulation mode, we just use chmod
66776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!emulated_lock(android::vold::BuildDataSystemCePath(user_id)) ||
668df528a7011b302c91579898c4a37361214ab05bbPaul Crowley            !emulated_lock(android::vold::BuildDataMiscCePath(user_id)) ||
669be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            !emulated_lock(android::vold::BuildDataMediaCePath(nullptr, user_id)) ||
670be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            !emulated_lock(android::vold::BuildDataUserCePath(nullptr, user_id))) {
67157eedbf8cbd21899a3395ce6f153cd0e05898f3bPaul Crowley            LOG(ERROR) << "Failed to lock user " << user_id;
67276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            return false;
673d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        }
674d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
675fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey
67676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
677d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
678d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
679df528a7011b302c91579898c4a37361214ab05bbPaul Crowleybool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial,
680be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        int flags) {
68147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    LOG(DEBUG) << "e4crypt_prepare_user_storage for volume " << escape_null(volume_uuid)
682df528a7011b302c91579898c4a37361214ab05bbPaul Crowley               << ", user " << user_id << ", serial " << serial << ", flags " << flags;
68347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
68447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    if (flags & FLAG_STORAGE_DE) {
685be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // DE_sys key
686be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
687be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
688be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
689be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto foreign_de_path = android::vold::BuildDataProfilesForeignDexDePath(user_id);
690be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
691be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // DE_n key
69247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
69347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
69447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
69547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
696be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
697be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#if MANAGE_MISC_DIRS
698be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM),
699be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey                multiuser_get_uid(user_id, AID_EVERYBODY))) return false;
700be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#endif
701be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
702be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (!prepare_dir(foreign_de_path, 0773, AID_SYSTEM, AID_SYSTEM)) return false;
703be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
70476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
70576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false;
70676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
707d1ee944f0839d60b014722c7facbb4a66bd4f2c3Calin Juravle
708be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // For now, FBE is only supported on internal storage
709be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (e4crypt_is_native() && volume_uuid == nullptr) {
71047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey            std::string de_raw_ref;
711a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley            if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_raw_ref)) return false;
71276107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(de_raw_ref, system_de_path)) return false;
71376107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(de_raw_ref, misc_de_path)) return false;
71476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(de_raw_ref, user_de_path)) return false;
71547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        }
71647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    }
71747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
71847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    if (flags & FLAG_STORAGE_CE) {
719be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // CE_n key
72047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
72147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
722be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id);
723be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id);
72447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
72576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
72676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false;
72776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
72876107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley        if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
72947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
730be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // For now, FBE is only supported on internal storage
731be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (e4crypt_is_native() && volume_uuid == nullptr) {
73247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey            std::string ce_raw_ref;
733a051eb7a22b7cd97e66d2f22b64884f8ebc73952Paul Crowley            if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_raw_ref)) return false;
73476107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(ce_raw_ref, system_ce_path)) return false;
73576107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(ce_raw_ref, misc_ce_path)) return false;
73676107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(ce_raw_ref, media_ce_path)) return false;
73776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley            if (!ensure_policy(ce_raw_ref, user_ce_path)) return false;
738d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey
739d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            // Now that credentials have been installed, we can run restorecon
740d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            // over these paths
741d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            // NOTE: these paths need to be kept in sync with libselinux
742d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            android::vold::RestoreconRecursive(system_ce_path);
743d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            android::vold::RestoreconRecursive(misc_ce_path);
74447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey        }
745d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
746d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
74776107cb3f4845b1a51a1a291c70ea3e12f9c14d0Paul Crowley    return true;
748d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
749be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
750be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeybool e4crypt_destroy_user_storage(const char* volume_uuid, userid_t user_id, int flags) {
751be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    LOG(DEBUG) << "e4crypt_destroy_user_storage for volume " << escape_null(volume_uuid)
752be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey               << ", user " << user_id << ", flags " << flags;
753be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    bool res = true;
754be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
755be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    if (flags & FLAG_STORAGE_DE) {
756be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // DE_sys key
757be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
758be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
759be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
760be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto foreign_de_path = android::vold::BuildDataProfilesForeignDexDePath(user_id);
761be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
762be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // DE_n key
763be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
764be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
765be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
766be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
767be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (volume_uuid == nullptr) {
768be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(system_legacy_path);
769be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#if MANAGE_MISC_DIRS
770be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(misc_legacy_path);
771be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey#endif
772be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(profiles_de_path);
773be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(foreign_de_path);
774be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(system_de_path);
775be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(misc_de_path);
776be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        }
777be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        res &= destroy_dir(user_de_path);
778be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    }
779be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
780be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    if (flags & FLAG_STORAGE_CE) {
781be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        // CE_n key
782be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
783be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
784be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id);
785be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id);
786be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
787be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        if (volume_uuid == nullptr) {
788be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(system_ce_path);
789be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey            res &= destroy_dir(misc_ce_path);
790be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        }
791be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        res &= destroy_dir(media_ce_path);
792be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey        res &= destroy_dir(user_ce_path);
793be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    }
794be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
795be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    return res;
796be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey}
797