blob: 5468c1088130bd4b3233259c4157094eccf4a5dc [file] [log] [blame]
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Eric Biggersa701c452018-10-23 13:06:55 -070017#include "FsCrypt.h"
Paul Lawrence731a7a22015-04-28 22:14:15 +000018
Shivaprasad Hongal92292622018-07-05 14:49:12 -070019#include "Keymaster.h"
Paul Crowley1ef25582016-01-21 20:26:12 +000020#include "KeyStorage.h"
Paul Crowleyf71ace32016-06-02 11:01:19 -070021#include "KeyUtil.h"
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080022#include "Utils.h"
Paul Crowleya7ca40b2017-10-06 14:29:33 -070023#include "VoldUtil.h"
24
Paul Crowleya3630362016-05-17 14:17:56 -070025#include <algorithm>
Paul Lawrence731a7a22015-04-28 22:14:15 +000026#include <map>
Paul Crowleyb1f3d242016-01-28 10:09:46 +000027#include <set>
Paul Lawrencefd7db732015-04-10 07:48:51 -070028#include <sstream>
Paul Crowleydf528a72016-03-09 09:31:37 -080029#include <string>
Paul Crowleyf71ace32016-06-02 11:01:19 -070030#include <vector>
Paul Lawrence731a7a22015-04-28 22:14:15 +000031
Paul Crowleydf528a72016-03-09 09:31:37 -080032#include <dirent.h>
33#include <errno.h>
34#include <fcntl.h>
Paul Crowleya3630362016-05-17 14:17:56 -070035#include <limits.h>
Jeff Sharkey7a9dd952016-01-12 16:52:16 -070036#include <selinux/android.h>
Paul Crowleydf528a72016-03-09 09:31:37 -080037#include <sys/mount.h>
38#include <sys/stat.h>
39#include <sys/types.h>
Paul Crowley14c8c072018-09-18 13:30:21 -070040#include <unistd.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000041
Paul Crowley480fcd22015-08-24 14:53:28 +010042#include <private/android_filesystem_config.h>
43
Paul Crowley82b41ff2017-10-20 08:17:54 -070044#include "android/os/IVold.h"
45
Paul Lawrence731a7a22015-04-28 22:14:15 +000046#include "cryptfs.h"
47
Jeff Sharkey7a9dd952016-01-12 16:52:16 -070048#define EMULATED_USES_SELINUX 0
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -060049#define MANAGE_MISC_DIRS 0
Jeff Sharkey7a9dd952016-01-12 16:52:16 -070050
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080051#include <cutils/fs.h>
Paul Crowleyf71ace32016-06-02 11:01:19 -070052#include <cutils/properties.h>
53
Eric Biggersa701c452018-10-23 13:06:55 -070054#include <fscrypt/fscrypt.h>
Elliott Hughesc3bda182017-05-09 17:01:04 -070055#include <keyutils.h>
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080056
Elliott Hughes7e128fb2015-12-04 15:50:53 -080057#include <android-base/file.h>
Elliott Hughes6bf05472015-12-04 17:55:33 -080058#include <android-base/logging.h>
Paul Crowley3aa914d2017-10-09 16:35:51 -070059#include <android-base/properties.h>
Elliott Hughes7e128fb2015-12-04 15:50:53 -080060#include <android-base/stringprintf.h>
Jieb6698d52018-11-12 15:26:02 +080061#include <android-base/unique_fd.h>
Paul Lawrence731a7a22015-04-28 22:14:15 +000062
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080063using android::base::StringPrintf;
Pavel Grafovb350ed02017-07-27 17:34:57 +010064using android::base::WriteStringToFile;
Tom Cherry4c5bde22019-01-29 14:34:01 -080065using android::fs_mgr::GetEntryForMountPoint;
Paul Crowley05720802016-02-08 15:55:41 +000066using android::vold::kEmptyAuthentication;
Pavel Grafove2e2d302017-08-01 17:15:53 +010067using android::vold::KeyBuffer;
Shivaprasad Hongal92292622018-07-05 14:49:12 -070068using android::vold::Keymaster;
69using android::hardware::keymaster::V4_0::KeyFormat;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -080070
Paul Lawrence731a7a22015-04-28 22:14:15 +000071namespace {
Andrew Scull7ec25c72016-10-31 10:28:25 +000072
Paul Crowley3aa914d2017-10-09 16:35:51 -070073struct PolicyKeyRef {
74 std::string contents_mode;
75 std::string filenames_mode;
76 std::string key_raw_ref;
77};
78
Eric Biggersa701c452018-10-23 13:06:55 -070079const std::string device_key_dir = std::string() + DATA_MNT_POINT + fscrypt_unencrypted_folder;
Paul Crowleydf528a72016-03-09 09:31:37 -080080const std::string device_key_path = device_key_dir + "/key";
81const std::string device_key_temp = device_key_dir + "/temp";
Paul Lawrence5a06a642016-02-03 13:39:13 -080082
Paul Crowleydf528a72016-03-09 09:31:37 -080083const std::string user_key_dir = std::string() + DATA_MNT_POINT + "/misc/vold/user_keys";
84const std::string user_key_temp = user_key_dir + "/temp";
Paul Crowley82b41ff2017-10-20 08:17:54 -070085const std::string prepare_subdirs_path = "/system/bin/vold_prepare_subdirs";
Paul Crowley285956f2016-01-20 13:12:38 +000086
Paul Crowley26a53882017-10-26 11:16:39 -070087const std::string systemwide_volume_key_dir =
88 std::string() + DATA_MNT_POINT + "/misc/vold/volume_keys";
89
Paul Crowleydf528a72016-03-09 09:31:37 -080090bool s_global_de_initialized = false;
Paul Lawrence7b6b5652016-02-02 11:14:59 -080091
Paul Crowleydf528a72016-03-09 09:31:37 -080092// Some users are ephemeral, don't try to wipe their keys from disk
93std::set<userid_t> s_ephemeral_users;
Paul Lawrenceaec34df2016-02-03 10:52:41 -080094
Paul Crowleydf528a72016-03-09 09:31:37 -080095// Map user ids to key references
96std::map<userid_t, std::string> s_de_key_raw_refs;
97std::map<userid_t, std::string> s_ce_key_raw_refs;
Paul Crowley99360d72016-10-19 14:00:24 -070098// TODO abolish this map, per b/26948053
Pavel Grafove2e2d302017-08-01 17:15:53 +010099std::map<userid_t, KeyBuffer> s_ce_keys;
Paul Lawrence731a7a22015-04-28 22:14:15 +0000100
Paul Crowley14c8c072018-09-18 13:30:21 -0700101} // namespace
Paul Lawrence731a7a22015-04-28 22:14:15 +0000102
Eric Biggersa701c452018-10-23 13:06:55 -0700103static bool fscrypt_is_emulated() {
Paul Crowley38132a12016-02-09 09:50:32 +0000104 return property_get_bool("persist.sys.emulate_fbe", false);
105}
106
Paul Crowley3b71fc52017-10-09 10:55:21 -0700107static const char* escape_empty(const std::string& value) {
108 return value.empty() ? "null" : value.c_str();
Paul Lawrence731a7a22015-04-28 22:14:15 +0000109}
110
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000111static std::string get_de_key_path(userid_t user_id) {
112 return StringPrintf("%s/de/%d", user_key_dir.c_str(), user_id);
113}
114
Paul Crowleya3630362016-05-17 14:17:56 -0700115static std::string get_ce_key_directory_path(userid_t user_id) {
116 return StringPrintf("%s/ce/%d", user_key_dir.c_str(), user_id);
117}
118
119// Returns the keys newest first
120static std::vector<std::string> get_ce_key_paths(const std::string& directory_path) {
121 auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(directory_path.c_str()), closedir);
122 if (!dirp) {
123 PLOG(ERROR) << "Unable to open ce key directory: " + directory_path;
124 return std::vector<std::string>();
125 }
126 std::vector<std::string> result;
127 for (;;) {
128 errno = 0;
129 auto const entry = readdir(dirp.get());
130 if (!entry) {
131 if (errno) {
132 PLOG(ERROR) << "Unable to read ce key directory: " + directory_path;
133 return std::vector<std::string>();
134 }
135 break;
136 }
137 if (entry->d_type != DT_DIR || entry->d_name[0] != 'c') {
138 LOG(DEBUG) << "Skipping non-key " << entry->d_name;
139 continue;
140 }
141 result.emplace_back(directory_path + "/" + entry->d_name);
142 }
143 std::sort(result.begin(), result.end());
144 std::reverse(result.begin(), result.end());
145 return result;
146}
147
148static std::string get_ce_key_current_path(const std::string& directory_path) {
149 return directory_path + "/current";
150}
151
152static bool get_ce_key_new_path(const std::string& directory_path,
Paul Crowley14c8c072018-09-18 13:30:21 -0700153 const std::vector<std::string>& paths, std::string* ce_key_path) {
Paul Crowleya3630362016-05-17 14:17:56 -0700154 if (paths.empty()) {
155 *ce_key_path = get_ce_key_current_path(directory_path);
156 return true;
157 }
158 for (unsigned int i = 0; i < UINT_MAX; i++) {
159 auto const candidate = StringPrintf("%s/cx%010u", directory_path.c_str(), i);
160 if (paths[0] < candidate) {
161 *ce_key_path = candidate;
162 return true;
163 }
164 }
165 return false;
166}
167
168// Discard all keys but the named one; rename it to canonical name.
169// No point in acting on errors in this; ignore them.
Paul Crowley14c8c072018-09-18 13:30:21 -0700170static void fixate_user_ce_key(const std::string& directory_path, const std::string& to_fix,
Paul Crowleya3630362016-05-17 14:17:56 -0700171 const std::vector<std::string>& paths) {
Paul Crowley14c8c072018-09-18 13:30:21 -0700172 for (auto const other_path : paths) {
Paul Crowleya3630362016-05-17 14:17:56 -0700173 if (other_path != to_fix) {
174 android::vold::destroyKey(other_path);
175 }
176 }
177 auto const current_path = get_ce_key_current_path(directory_path);
178 if (to_fix != current_path) {
179 LOG(DEBUG) << "Renaming " << to_fix << " to " << current_path;
180 if (rename(to_fix.c_str(), current_path.c_str()) != 0) {
181 PLOG(WARNING) << "Unable to rename " << to_fix << " to " << current_path;
Jieb6698d52018-11-12 15:26:02 +0800182 return;
Paul Crowleya3630362016-05-17 14:17:56 -0700183 }
184 }
Paul Crowley621d9b92018-12-07 15:36:09 -0800185 android::vold::FsyncDirectory(directory_path);
Paul Crowleya3630362016-05-17 14:17:56 -0700186}
187
188static bool read_and_fixate_user_ce_key(userid_t user_id,
189 const android::vold::KeyAuthentication& auth,
Paul Crowley14c8c072018-09-18 13:30:21 -0700190 KeyBuffer* ce_key) {
Paul Crowleya3630362016-05-17 14:17:56 -0700191 auto const directory_path = get_ce_key_directory_path(user_id);
192 auto const paths = get_ce_key_paths(directory_path);
Paul Crowley14c8c072018-09-18 13:30:21 -0700193 for (auto const ce_key_path : paths) {
Paul Crowleya3630362016-05-17 14:17:56 -0700194 LOG(DEBUG) << "Trying user CE key " << ce_key_path;
195 if (android::vold::retrieveKey(ce_key_path, auth, ce_key)) {
196 LOG(DEBUG) << "Successfully retrieved key";
197 fixate_user_ce_key(directory_path, ce_key_path, paths);
198 return true;
199 }
200 }
201 LOG(ERROR) << "Failed to find working ce key for user " << user_id;
202 return false;
Paul Crowleyb33e8872015-05-19 12:34:09 +0100203}
204
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700205bool is_wrapped_key_supported() {
Yifan Hong804afe12019-02-07 12:56:47 -0800206 return GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT)->fs_mgr_flags.wrapped_key;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700207}
208
209bool is_wrapped_key_supported_external() {
210 return false;
211}
212
Neeraj Sonic480f912018-12-14 15:18:15 +0530213bool is_metadata_wrapped_key_supported() {
214 return GetEntryForMountPoint(&fstab_default, METADATA_MNT_POINT)->fs_mgr_flags.wrapped_key;
215}
216
Paul Crowleydf528a72016-03-09 09:31:37 -0800217static bool read_and_install_user_ce_key(userid_t user_id,
218 const android::vold::KeyAuthentication& auth) {
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000219 if (s_ce_key_raw_refs.count(user_id) != 0) return true;
Pavel Grafove2e2d302017-08-01 17:15:53 +0100220 KeyBuffer ce_key;
Paul Crowleya3630362016-05-17 14:17:56 -0700221 if (!read_and_fixate_user_ce_key(user_id, auth, &ce_key)) return false;
Paul Crowley05720802016-02-08 15:55:41 +0000222 std::string ce_raw_ref;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700223
224 if (is_wrapped_key_supported()) {
225 KeyBuffer ephemeral_wrapped_key;
226 if (!getEphemeralWrappedKey(KeyFormat::RAW, ce_key, &ephemeral_wrapped_key)) {
227 LOG(ERROR) << "Failed to export ce key";
228 return false;
229 }
230 ce_key = std::move(ephemeral_wrapped_key);
231 }
Paul Crowleyf71ace32016-06-02 11:01:19 -0700232 if (!android::vold::installKey(ce_key, &ce_raw_ref)) return false;
Pavel Grafove2e2d302017-08-01 17:15:53 +0100233 s_ce_keys[user_id] = std::move(ce_key);
Paul Crowley05720802016-02-08 15:55:41 +0000234 s_ce_key_raw_refs[user_id] = ce_raw_ref;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000235 LOG(DEBUG) << "Installed ce key for user " << user_id;
Paul Crowley1ef25582016-01-21 20:26:12 +0000236 return true;
Paul Crowley285956f2016-01-20 13:12:38 +0000237}
238
Paul Crowleydf528a72016-03-09 09:31:37 -0800239static bool prepare_dir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid) {
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000240 LOG(DEBUG) << "Preparing: " << dir;
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000241 if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
242 PLOG(ERROR) << "Failed to prepare " << dir;
Paul Crowley285956f2016-01-20 13:12:38 +0000243 return false;
244 }
Paul Crowley13ffd8e2016-01-27 14:30:22 +0000245 return true;
246}
247
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600248static bool destroy_dir(const std::string& dir) {
249 LOG(DEBUG) << "Destroying: " << dir;
250 if (rmdir(dir.c_str()) != 0 && errno != ENOENT) {
251 PLOG(ERROR) << "Failed to destroy " << dir;
252 return false;
253 }
254 return true;
255}
256
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000257// NB this assumes that there is only one thread listening for crypt commands, because
258// it creates keys in a fixed location.
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000259static bool create_and_install_user_keys(userid_t user_id, bool create_ephemeral) {
Pavel Grafove2e2d302017-08-01 17:15:53 +0100260 KeyBuffer de_key, ce_key;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700261
262 if(is_wrapped_key_supported()) {
263 if (!generateWrappedKey(user_id, android::vold::KeyType::DE_USER, &de_key)) return false;
264 if (!generateWrappedKey(user_id, android::vold::KeyType::CE_USER, &ce_key)) return false;
265 } else {
266 if (!android::vold::randomKey(&de_key)) return false;
267 if (!android::vold::randomKey(&ce_key)) return false;
268 }
269
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000270 if (create_ephemeral) {
271 // If the key should be created as ephemeral, don't store it.
272 s_ephemeral_users.insert(user_id);
273 } else {
Paul Crowleya3630362016-05-17 14:17:56 -0700274 auto const directory_path = get_ce_key_directory_path(user_id);
275 if (!prepare_dir(directory_path, 0700, AID_ROOT, AID_ROOT)) return false;
276 auto const paths = get_ce_key_paths(directory_path);
277 std::string ce_key_path;
278 if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
Paul Crowley14c8c072018-09-18 13:30:21 -0700279 if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, kEmptyAuthentication,
280 ce_key))
281 return false;
Paul Crowleya3630362016-05-17 14:17:56 -0700282 fixate_user_ce_key(directory_path, ce_key_path, paths);
283 // Write DE key second; once this is written, all is good.
Paul Crowleyf71ace32016-06-02 11:01:19 -0700284 if (!android::vold::storeKeyAtomically(get_de_key_path(user_id), user_key_temp,
Paul Crowley14c8c072018-09-18 13:30:21 -0700285 kEmptyAuthentication, de_key))
286 return false;
Paul Crowley95376d62015-05-06 15:04:43 +0100287 }
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700288
289 /* Install the DE keys */
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000290 std::string de_raw_ref;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000291 std::string ce_raw_ref;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700292
293 if (is_wrapped_key_supported()) {
294 KeyBuffer ephemeral_wrapped_de_key;
295 KeyBuffer ephemeral_wrapped_ce_key;
296
297 /* Export and install the DE keys */
298 if (!getEphemeralWrappedKey(KeyFormat::RAW, de_key, &ephemeral_wrapped_de_key)) {
299 LOG(ERROR) << "Failed to export de_key";
300 return false;
301 }
302 /* Export and install the CE keys */
303 if (!getEphemeralWrappedKey(KeyFormat::RAW, ce_key, &ephemeral_wrapped_ce_key)) {
304 LOG(ERROR) << "Failed to export de_key";
305 return false;
306 }
307
308 de_key = std::move(ephemeral_wrapped_de_key);
309 ce_key = std::move(ephemeral_wrapped_ce_key);
310 }
311 if (!android::vold::installKey(de_key, &de_raw_ref)) return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700312 if (!android::vold::installKey(ce_key, &ce_raw_ref)) return false;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700313 s_ce_keys[user_id] = std::move(ce_key);
314
315 s_de_key_raw_refs[user_id] = de_raw_ref;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000316 s_ce_key_raw_refs[user_id] = ce_raw_ref;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700317
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000318 LOG(DEBUG) << "Created keys for user " << user_id;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000319 return true;
320}
321
Paul Crowleydf528a72016-03-09 09:31:37 -0800322static bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t user_id,
323 std::string* raw_ref) {
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000324 auto refi = key_map.find(user_id);
325 if (refi == key_map.end()) {
326 LOG(ERROR) << "Cannot find key for " << user_id;
327 return false;
328 }
Paul Crowleya051eb72016-03-08 16:08:32 -0800329 *raw_ref = refi->second;
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000330 return true;
331}
332
Paul Crowley3aa914d2017-10-09 16:35:51 -0700333static void get_data_file_encryption_modes(PolicyKeyRef* key_ref) {
Tom Cherry4c5bde22019-01-29 14:34:01 -0800334 auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
335 if (entry == nullptr) {
336 return;
337 }
338 key_ref->contents_mode = entry->file_contents_mode;
339 key_ref->filenames_mode = entry->file_names_mode;
Paul Crowleya7ca40b2017-10-06 14:29:33 -0700340}
341
Paul Crowley3aa914d2017-10-09 16:35:51 -0700342static bool ensure_policy(const PolicyKeyRef& key_ref, const std::string& path) {
Eric Biggersa701c452018-10-23 13:06:55 -0700343 return fscrypt_policy_ensure(path.c_str(), key_ref.key_raw_ref.data(),
Paul Crowley3aa914d2017-10-09 16:35:51 -0700344 key_ref.key_raw_ref.size(), key_ref.contents_mode.c_str(),
345 key_ref.filenames_mode.c_str()) == 0;
Paul Crowley95376d62015-05-06 15:04:43 +0100346}
Paul Crowleyb33e8872015-05-19 12:34:09 +0100347
Paul Crowleydf528a72016-03-09 09:31:37 -0800348static bool is_numeric(const char* name) {
349 for (const char* p = name; *p != '\0'; p++) {
350 if (!isdigit(*p)) return false;
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000351 }
352 return true;
353}
354
355static bool load_all_de_keys() {
356 auto de_dir = user_key_dir + "/de";
Paul Crowleydf528a72016-03-09 09:31:37 -0800357 auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(de_dir.c_str()), closedir);
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000358 if (!dirp) {
359 PLOG(ERROR) << "Unable to read de key directory";
360 return false;
361 }
362 for (;;) {
363 errno = 0;
364 auto entry = readdir(dirp.get());
365 if (!entry) {
366 if (errno) {
367 PLOG(ERROR) << "Unable to read de key directory";
368 return false;
369 }
370 break;
371 }
372 if (entry->d_type != DT_DIR || !is_numeric(entry->d_name)) {
373 LOG(DEBUG) << "Skipping non-de-key " << entry->d_name;
374 continue;
375 }
Jeff Sharkey95440eb2017-09-18 18:19:28 -0600376 userid_t user_id = std::stoi(entry->d_name);
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000377 if (s_de_key_raw_refs.count(user_id) == 0) {
Paul Crowley05720802016-02-08 15:55:41 +0000378 auto key_path = de_dir + "/" + entry->d_name;
Pavel Grafove2e2d302017-08-01 17:15:53 +0100379 KeyBuffer key;
Paul Crowleya051eb72016-03-08 16:08:32 -0800380 if (!android::vold::retrieveKey(key_path, kEmptyAuthentication, &key)) return false;
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000381 std::string raw_ref;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700382 if (is_wrapped_key_supported()) {
383 KeyBuffer ephemeral_wrapped_key;
384 if (!getEphemeralWrappedKey(KeyFormat::RAW, key, &ephemeral_wrapped_key)) {
385 LOG(ERROR) << "Failed to export de_key in create_and_install_user_keys";
386 return false;
387 }
388 key = std::move(ephemeral_wrapped_key);
389 }
Paul Crowleyf71ace32016-06-02 11:01:19 -0700390 if (!android::vold::installKey(key, &raw_ref)) return false;
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000391 s_de_key_raw_refs[user_id] = raw_ref;
392 LOG(DEBUG) << "Installed de key for user " << user_id;
393 }
394 }
Eric Biggersa701c452018-10-23 13:06:55 -0700395 // fscrypt:TODO: go through all DE directories, ensure that all user dirs have the
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000396 // correct policy set on them, and that no rogue ones exist.
397 return true;
398}
399
Eric Biggersa701c452018-10-23 13:06:55 -0700400bool fscrypt_initialize_global_de() {
401 LOG(INFO) << "fscrypt_initialize_global_de";
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700402 bool wrapped_key_supported = false;
Paul Lawrenceaec34df2016-02-03 10:52:41 -0800403
Paul Crowley38132a12016-02-09 09:50:32 +0000404 if (s_global_de_initialized) {
405 LOG(INFO) << "Already initialized";
Paul Crowley76107cb2016-02-09 10:04:39 +0000406 return true;
Paul Lawrenceaec34df2016-02-03 10:52:41 -0800407 }
408
Paul Crowley3aa914d2017-10-09 16:35:51 -0700409 PolicyKeyRef device_ref;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700410 wrapped_key_supported = is_wrapped_key_supported();
411
412 if (!android::vold::retrieveAndInstallKey(true, kEmptyAuthentication,
413 device_key_path, device_key_temp,
414 &device_ref.key_raw_ref, wrapped_key_supported))
Paul Crowley3aa914d2017-10-09 16:35:51 -0700415 return false;
416 get_data_file_encryption_modes(&device_ref);
Eric Biggersb45caaf2017-02-02 14:52:12 -0800417
Paul Crowley3aa914d2017-10-09 16:35:51 -0700418 std::string modestring = device_ref.contents_mode + ":" + device_ref.filenames_mode;
Eric Biggersa701c452018-10-23 13:06:55 -0700419 std::string mode_filename = std::string("/data") + fscrypt_key_mode;
Eric Biggersb45caaf2017-02-02 14:52:12 -0800420 if (!android::base::WriteStringToFile(modestring, mode_filename)) {
Paul Lawrence6e410592016-05-24 14:20:38 -0700421 PLOG(ERROR) << "Cannot save type";
422 return false;
423 }
424
Eric Biggersa701c452018-10-23 13:06:55 -0700425 std::string ref_filename = std::string("/data") + fscrypt_key_ref;
Paul Crowley3aa914d2017-10-09 16:35:51 -0700426 if (!android::base::WriteStringToFile(device_ref.key_raw_ref, ref_filename)) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700427 PLOG(ERROR) << "Cannot save key reference to:" << ref_filename;
Paul Crowley76107cb2016-02-09 10:04:39 +0000428 return false;
Paul Lawrenceaec34df2016-02-03 10:52:41 -0800429 }
Paul Crowleyf71ace32016-06-02 11:01:19 -0700430 LOG(INFO) << "Wrote system DE key reference to:" << ref_filename;
Paul Lawrenceaec34df2016-02-03 10:52:41 -0800431
Paul Crowley38132a12016-02-09 09:50:32 +0000432 s_global_de_initialized = true;
Paul Crowley76107cb2016-02-09 10:04:39 +0000433 return true;
Paul Lawrenceaec34df2016-02-03 10:52:41 -0800434}
435
Eric Biggersa701c452018-10-23 13:06:55 -0700436bool fscrypt_init_user0() {
437 LOG(DEBUG) << "fscrypt_init_user0";
438 if (fscrypt_is_native()) {
Paul Crowley76107cb2016-02-09 10:04:39 +0000439 if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false;
440 if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false;
441 if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700442 if (!android::vold::pathExists(get_de_key_path(0))) {
Paul Crowley76107cb2016-02-09 10:04:39 +0000443 if (!create_and_install_user_keys(0, false)) return false;
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000444 }
Jeff Sharkey47695b22016-02-01 17:02:29 -0700445 // TODO: switch to loading only DE_0 here once framework makes
446 // explicit calls to install DE keys for secondary users
Paul Crowley76107cb2016-02-09 10:04:39 +0000447 if (!load_all_de_keys()) return false;
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000448 }
Jeff Sharkey47695b22016-02-01 17:02:29 -0700449 // We can only safely prepare DE storage here, since CE keys are probably
450 // entangled with user credentials. The framework will always prepare CE
451 // storage once CE keys are installed.
Eric Biggersa701c452018-10-23 13:06:55 -0700452 if (!fscrypt_prepare_user_storage("", 0, 0, android::os::IVold::STORAGE_FLAG_DE)) {
Jeff Sharkey47695b22016-02-01 17:02:29 -0700453 LOG(ERROR) << "Failed to prepare user 0 storage";
Paul Crowley76107cb2016-02-09 10:04:39 +0000454 return false;
Jeff Sharkey47695b22016-02-01 17:02:29 -0700455 }
Jeff Sharkey0754a452016-02-08 12:21:42 -0700456
457 // If this is a non-FBE device that recently left an emulated mode,
458 // restore user data directories to known-good state.
Eric Biggersa701c452018-10-23 13:06:55 -0700459 if (!fscrypt_is_native() && !fscrypt_is_emulated()) {
460 fscrypt_unlock_user_key(0, 0, "!", "!");
Jeff Sharkey0754a452016-02-08 12:21:42 -0700461 }
462
Paul Crowley76107cb2016-02-09 10:04:39 +0000463 return true;
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000464}
465
Eric Biggersa701c452018-10-23 13:06:55 -0700466bool fscrypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
467 LOG(DEBUG) << "fscrypt_vold_create_user_key for " << user_id << " serial " << serial;
468 if (!fscrypt_is_native()) {
Paul Crowley76107cb2016-02-09 10:04:39 +0000469 return true;
Paul Crowleyea62e262016-01-28 12:23:53 +0000470 }
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000471 // FIXME test for existence of key that is not loaded yet
472 if (s_ce_key_raw_refs.count(user_id) != 0) {
Eric Biggersa701c452018-10-23 13:06:55 -0700473 LOG(ERROR) << "Already exists, can't fscrypt_vold_create_user_key for " << user_id
Paul Crowleydf528a72016-03-09 09:31:37 -0800474 << " serial " << serial;
Paul Crowley285956f2016-01-20 13:12:38 +0000475 // FIXME should we fail the command?
Paul Crowley76107cb2016-02-09 10:04:39 +0000476 return true;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800477 }
Paul Crowleyb92f83c2016-02-01 14:10:43 +0000478 if (!create_and_install_user_keys(user_id, ephemeral)) {
Paul Crowley76107cb2016-02-09 10:04:39 +0000479 return false;
Paul Crowley285956f2016-01-20 13:12:38 +0000480 }
Paul Crowley76107cb2016-02-09 10:04:39 +0000481 return true;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800482}
483
Pavel Grafovb350ed02017-07-27 17:34:57 +0100484static void drop_caches() {
485 // Clean any dirty pages (otherwise they won't be dropped).
486 sync();
487 // Drop inode and page caches.
488 if (!WriteStringToFile("3", "/proc/sys/vm/drop_caches")) {
489 PLOG(ERROR) << "Failed to drop caches during key eviction";
490 }
491}
492
Andrew Scull7ec25c72016-10-31 10:28:25 +0000493static bool evict_ce_key(userid_t user_id) {
Andrew Scull7ec25c72016-10-31 10:28:25 +0000494 bool success = true;
495 std::string raw_ref;
496 // If we haven't loaded the CE key, no need to evict it.
497 if (lookup_key_ref(s_ce_key_raw_refs, user_id, &raw_ref)) {
Paul Crowleyf71ace32016-06-02 11:01:19 -0700498 success &= android::vold::evictKey(raw_ref);
Pavel Grafovb350ed02017-07-27 17:34:57 +0100499 drop_caches();
Andrew Scull7ec25c72016-10-31 10:28:25 +0000500 }
Shivaprasad Hongala8ae0122018-10-10 16:05:33 -0700501
502 if(is_wrapped_key_supported()) {
503 KeyBuffer key;
504 key = s_ce_keys[user_id];
505
506 std::string keystr(key.data(), key.size());
507 Keymaster keymaster;
508
509 if (!keymaster) {
510 s_ce_keys.erase(user_id);
511 s_ce_key_raw_refs.erase(user_id);
512 return false;
513 }
514 keymaster.deleteKey(keystr);
515 }
516
517 s_ce_keys.erase(user_id);
Andrew Scull7ec25c72016-10-31 10:28:25 +0000518 s_ce_key_raw_refs.erase(user_id);
519 return success;
520}
521
Eric Biggersa701c452018-10-23 13:06:55 -0700522bool fscrypt_destroy_user_key(userid_t user_id) {
523 LOG(DEBUG) << "fscrypt_destroy_user_key(" << user_id << ")";
524 if (!fscrypt_is_native()) {
Paul Crowley76107cb2016-02-09 10:04:39 +0000525 return true;
Paul Crowleyea62e262016-01-28 12:23:53 +0000526 }
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000527 bool success = true;
528 std::string raw_ref;
Andrew Scull7ec25c72016-10-31 10:28:25 +0000529 success &= evict_ce_key(user_id);
Paul Crowley14c8c072018-09-18 13:30:21 -0700530 success &=
531 lookup_key_ref(s_de_key_raw_refs, user_id, &raw_ref) && android::vold::evictKey(raw_ref);
Paul Crowley05720802016-02-08 15:55:41 +0000532 s_de_key_raw_refs.erase(user_id);
Paul Crowleyb1f3d242016-01-28 10:09:46 +0000533 auto it = s_ephemeral_users.find(user_id);
534 if (it != s_ephemeral_users.end()) {
535 s_ephemeral_users.erase(it);
Paul Crowley1ef25582016-01-21 20:26:12 +0000536 } else {
Paul Crowley14c8c072018-09-18 13:30:21 -0700537 for (auto const path : get_ce_key_paths(get_ce_key_directory_path(user_id))) {
Paul Crowleya3630362016-05-17 14:17:56 -0700538 success &= android::vold::destroyKey(path);
539 }
Paul Crowleyab0b56a2016-07-19 15:29:53 -0700540 auto de_key_path = get_de_key_path(user_id);
Paul Crowleyf71ace32016-06-02 11:01:19 -0700541 if (android::vold::pathExists(de_key_path)) {
Paul Crowleyab0b56a2016-07-19 15:29:53 -0700542 success &= android::vold::destroyKey(de_key_path);
543 } else {
544 LOG(INFO) << "Not present so not erasing: " << de_key_path;
545 }
Lenka Trochtova395039f2015-11-25 10:13:03 +0100546 }
Paul Crowley76107cb2016-02-09 10:04:39 +0000547 return success;
Paul Crowleyb33e8872015-05-19 12:34:09 +0100548}
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800549
Paul Crowley76107cb2016-02-09 10:04:39 +0000550static bool emulated_lock(const std::string& path) {
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700551 if (chmod(path.c_str(), 0000) != 0) {
552 PLOG(ERROR) << "Failed to chmod " << path;
Paul Crowley76107cb2016-02-09 10:04:39 +0000553 return false;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700554 }
555#if EMULATED_USES_SELINUX
556 if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
557 PLOG(WARNING) << "Failed to setfilecon " << path;
Paul Crowley76107cb2016-02-09 10:04:39 +0000558 return false;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700559 }
560#endif
Paul Crowley76107cb2016-02-09 10:04:39 +0000561 return true;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700562}
563
Paul Crowley76107cb2016-02-09 10:04:39 +0000564static bool emulated_unlock(const std::string& path, mode_t mode) {
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700565 if (chmod(path.c_str(), mode) != 0) {
566 PLOG(ERROR) << "Failed to chmod " << path;
Paul Crowleya042cb52016-01-21 17:24:49 +0000567 // FIXME temporary workaround for b/26713622
Eric Biggersa701c452018-10-23 13:06:55 -0700568 if (fscrypt_is_emulated()) return false;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700569 }
570#if EMULATED_USES_SELINUX
571 if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
572 PLOG(WARNING) << "Failed to restorecon " << path;
Paul Crowleya042cb52016-01-21 17:24:49 +0000573 // FIXME temporary workaround for b/26713622
Eric Biggersa701c452018-10-23 13:06:55 -0700574 if (fscrypt_is_emulated()) return false;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700575 }
576#endif
Paul Crowley76107cb2016-02-09 10:04:39 +0000577 return true;
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700578}
579
Paul Crowley3b71fc52017-10-09 10:55:21 -0700580static bool parse_hex(const std::string& hex, std::string* result) {
581 if (hex == "!") {
Paul Crowleya051eb72016-03-08 16:08:32 -0800582 *result = "";
Paul Crowley05720802016-02-08 15:55:41 +0000583 return true;
584 }
Paul Crowleya051eb72016-03-08 16:08:32 -0800585 if (android::vold::HexToStr(hex, *result) != 0) {
Paul Crowleydf528a72016-03-09 09:31:37 -0800586 LOG(ERROR) << "Invalid FBE hex string"; // Don't log the string for security reasons
Paul Crowley05720802016-02-08 15:55:41 +0000587 return false;
588 }
589 return true;
590}
591
Paul Crowley3aa914d2017-10-09 16:35:51 -0700592static std::string volkey_path(const std::string& misc_path, const std::string& volume_uuid) {
593 return misc_path + "/vold/volume_keys/" + volume_uuid + "/default";
594}
595
Paul Crowley26a53882017-10-26 11:16:39 -0700596static std::string volume_secdiscardable_path(const std::string& volume_uuid) {
597 return systemwide_volume_key_dir + "/" + volume_uuid + "/secdiscardable";
598}
599
Paul Crowley3aa914d2017-10-09 16:35:51 -0700600static bool read_or_create_volkey(const std::string& misc_path, const std::string& volume_uuid,
601 PolicyKeyRef* key_ref) {
Paul Crowley26a53882017-10-26 11:16:39 -0700602 auto secdiscardable_path = volume_secdiscardable_path(volume_uuid);
603 std::string secdiscardable_hash;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700604 bool wrapped_key_supported = false;
Paul Crowley26a53882017-10-26 11:16:39 -0700605 if (android::vold::pathExists(secdiscardable_path)) {
606 if (!android::vold::readSecdiscardable(secdiscardable_path, &secdiscardable_hash))
607 return false;
608 } else {
609 if (fs_mkdirs(secdiscardable_path.c_str(), 0700) != 0) {
610 PLOG(ERROR) << "Creating directories for: " << secdiscardable_path;
611 return false;
612 }
613 if (!android::vold::createSecdiscardable(secdiscardable_path, &secdiscardable_hash))
614 return false;
615 }
Paul Crowley3aa914d2017-10-09 16:35:51 -0700616 auto key_path = volkey_path(misc_path, volume_uuid);
617 if (fs_mkdirs(key_path.c_str(), 0700) != 0) {
618 PLOG(ERROR) << "Creating directories for: " << key_path;
619 return false;
620 }
Paul Crowley26a53882017-10-26 11:16:39 -0700621 android::vold::KeyAuthentication auth("", secdiscardable_hash);
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700622 wrapped_key_supported = is_wrapped_key_supported_external();
623
Paul Crowley26a53882017-10-26 11:16:39 -0700624 if (!android::vold::retrieveAndInstallKey(true, auth, key_path, key_path + "_tmp",
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700625 &key_ref->key_raw_ref, wrapped_key_supported))
Paul Crowley3aa914d2017-10-09 16:35:51 -0700626 return false;
627 key_ref->contents_mode =
628 android::base::GetProperty("ro.crypto.volume.contents_mode", "aes-256-xts");
629 key_ref->filenames_mode =
630 android::base::GetProperty("ro.crypto.volume.filenames_mode", "aes-256-heh");
631 return true;
632}
633
634static bool destroy_volkey(const std::string& misc_path, const std::string& volume_uuid) {
Paul Crowleyc6433a22017-10-24 14:54:43 -0700635 auto path = volkey_path(misc_path, volume_uuid);
636 if (!android::vold::pathExists(path)) return true;
637 return android::vold::destroyKey(path);
Paul Crowley3aa914d2017-10-09 16:35:51 -0700638}
639
Eric Biggersa701c452018-10-23 13:06:55 -0700640bool fscrypt_add_user_key_auth(userid_t user_id, int serial, const std::string& token_hex,
Paul Crowley3b71fc52017-10-09 10:55:21 -0700641 const std::string& secret_hex) {
Eric Biggersa701c452018-10-23 13:06:55 -0700642 LOG(DEBUG) << "fscrypt_add_user_key_auth " << user_id << " serial=" << serial
Paul Crowley3b71fc52017-10-09 10:55:21 -0700643 << " token_present=" << (token_hex != "!");
Eric Biggersa701c452018-10-23 13:06:55 -0700644 if (!fscrypt_is_native()) return true;
Paul Crowley76107cb2016-02-09 10:04:39 +0000645 if (s_ephemeral_users.count(user_id) != 0) return true;
Paul Crowleya3630362016-05-17 14:17:56 -0700646 std::string token, secret;
Paul Crowleya051eb72016-03-08 16:08:32 -0800647 if (!parse_hex(token_hex, &token)) return false;
Paul Crowleya3630362016-05-17 14:17:56 -0700648 if (!parse_hex(secret_hex, &secret)) return false;
Paul Crowley14c8c072018-09-18 13:30:21 -0700649 auto auth =
650 secret.empty() ? kEmptyAuthentication : android::vold::KeyAuthentication(token, secret);
Paul Crowleya3630362016-05-17 14:17:56 -0700651 auto const directory_path = get_ce_key_directory_path(user_id);
652 auto const paths = get_ce_key_paths(directory_path);
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700653
654 KeyBuffer ce_key;
655 if(is_wrapped_key_supported()) {
656 std::string ce_key_current_path = get_ce_key_current_path(directory_path);
657 if (android::vold::retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key)) {
658 LOG(DEBUG) << "Successfully retrieved key";
659 } else {
660 if (android::vold::retrieveKey(ce_key_current_path, auth, &ce_key)) {
661 LOG(DEBUG) << "Successfully retrieved key";
662 }
663 }
664 } else {
665 auto it = s_ce_keys.find(user_id);
666 if (it == s_ce_keys.end()) {
667 LOG(ERROR) << "Key not loaded into memory, can't change for user " << user_id;
668 return false;
669 }
670 ce_key = it->second;
671 }
672
Paul Crowleya3630362016-05-17 14:17:56 -0700673 std::string ce_key_path;
674 if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
Paul Crowleyf71ace32016-06-02 11:01:19 -0700675 if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, auth, ce_key)) return false;
Paul Crowley621d9b92018-12-07 15:36:09 -0800676 if (!android::vold::FsyncDirectory(directory_path)) return false;
Paul Crowleya3630362016-05-17 14:17:56 -0700677 return true;
678}
679
Diego Wilsondd0a81e2018-11-20 11:38:50 -0800680bool fscrypt_clear_user_key_auth(userid_t user_id, int serial, const std::string& token_hex,
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700681 const std::string& secret_hex) {
Diego Wilsondd0a81e2018-11-20 11:38:50 -0800682 LOG(DEBUG) << "fscrypt_clear_user_key_auth " << user_id << " serial=" << serial
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700683 << " token_present=" << (token_hex != "!");
Diego Wilsondd0a81e2018-11-20 11:38:50 -0800684 if (!fscrypt_is_native()) return true;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700685 if (s_ephemeral_users.count(user_id) != 0) return true;
686 std::string token, secret;
687
688 if (!parse_hex(token_hex, &token)) return false;
689 if (!parse_hex(secret_hex, &secret)) return false;
690
691 if (is_wrapped_key_supported()) {
692 auto const directory_path = get_ce_key_directory_path(user_id);
693 auto const paths = get_ce_key_paths(directory_path);
694
695 KeyBuffer ce_key;
696 std::string ce_key_current_path = get_ce_key_current_path(directory_path);
697
698 auto auth = android::vold::KeyAuthentication(token, secret);
699 /* Retrieve key while removing a pin. A secret is needed */
700 if (android::vold::retrieveKey(ce_key_current_path, auth, &ce_key)) {
701 LOG(DEBUG) << "Successfully retrieved key";
702 } else {
703 /* Retrieve key when going None to swipe and vice versa when a
704 synthetic password is present */
705 if (android::vold::retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key)) {
706 LOG(DEBUG) << "Successfully retrieved key";
707 }
708 }
709
710 std::string ce_key_path;
711 if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
712 if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, kEmptyAuthentication, ce_key))
713 return false;
714 } else {
Diego Wilsondd0a81e2018-11-20 11:38:50 -0800715 if(!fscrypt_add_user_key_auth(user_id, serial, "!", "!")) return false;
Shivaprasad Hongal92292622018-07-05 14:49:12 -0700716 }
717 return true;
718}
719
Eric Biggersa701c452018-10-23 13:06:55 -0700720bool fscrypt_fixate_newest_user_key_auth(userid_t user_id) {
721 LOG(DEBUG) << "fscrypt_fixate_newest_user_key_auth " << user_id;
722 if (!fscrypt_is_native()) return true;
Paul Crowley25a71382016-07-25 15:55:36 -0700723 if (s_ephemeral_users.count(user_id) != 0) return true;
Paul Crowleya3630362016-05-17 14:17:56 -0700724 auto const directory_path = get_ce_key_directory_path(user_id);
725 auto const paths = get_ce_key_paths(directory_path);
726 if (paths.empty()) {
727 LOG(ERROR) << "No ce keys present, cannot fixate for user " << user_id;
728 return false;
Paul Crowleyad2eb642016-02-10 17:56:05 +0000729 }
Paul Crowleya3630362016-05-17 14:17:56 -0700730 fixate_user_ce_key(directory_path, paths[0], paths);
Paul Crowley76107cb2016-02-09 10:04:39 +0000731 return true;
Paul Crowley05720802016-02-08 15:55:41 +0000732}
733
Jeff Sharkey47695b22016-02-01 17:02:29 -0700734// TODO: rename to 'install' for consistency, and take flags to know which keys to install
Eric Biggersa701c452018-10-23 13:06:55 -0700735bool fscrypt_unlock_user_key(userid_t user_id, int serial, const std::string& token_hex,
Paul Crowley3b71fc52017-10-09 10:55:21 -0700736 const std::string& secret_hex) {
Eric Biggersa701c452018-10-23 13:06:55 -0700737 LOG(DEBUG) << "fscrypt_unlock_user_key " << user_id << " serial=" << serial
Paul Crowley3b71fc52017-10-09 10:55:21 -0700738 << " token_present=" << (token_hex != "!");
Eric Biggersa701c452018-10-23 13:06:55 -0700739 if (fscrypt_is_native()) {
Paul Crowley05720802016-02-08 15:55:41 +0000740 if (s_ce_key_raw_refs.count(user_id) != 0) {
741 LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id;
Paul Crowley76107cb2016-02-09 10:04:39 +0000742 return true;
Paul Crowley05720802016-02-08 15:55:41 +0000743 }
744 std::string token, secret;
Paul Crowleya051eb72016-03-08 16:08:32 -0800745 if (!parse_hex(token_hex, &token)) return false;
746 if (!parse_hex(secret_hex, &secret)) return false;
Paul Crowley05720802016-02-08 15:55:41 +0000747 android::vold::KeyAuthentication auth(token, secret);
748 if (!read_and_install_user_ce_key(user_id, auth)) {
Paul Crowley8fb12fd2016-02-01 14:28:12 +0000749 LOG(ERROR) << "Couldn't read key for " << user_id;
Paul Crowley76107cb2016-02-09 10:04:39 +0000750 return false;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800751 }
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700752 } else {
753 // When in emulation mode, we just use chmod. However, we also
754 // unlock directories when not in emulation mode, to bring devices
755 // back into a known-good state.
Paul Crowley76107cb2016-02-09 10:04:39 +0000756 if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
Paul Crowleydf528a72016-03-09 09:31:37 -0800757 !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) ||
Paul Crowley3b71fc52017-10-09 10:55:21 -0700758 !emulated_unlock(android::vold::BuildDataMediaCePath("", user_id), 0770) ||
759 !emulated_unlock(android::vold::BuildDataUserCePath("", user_id), 0771)) {
Jeff Sharkey7a9dd952016-01-12 16:52:16 -0700760 LOG(ERROR) << "Failed to unlock user " << user_id;
Paul Crowley76107cb2016-02-09 10:04:39 +0000761 return false;
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700762 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800763 }
Paul Crowley76107cb2016-02-09 10:04:39 +0000764 return true;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800765}
766
Jeff Sharkey47695b22016-02-01 17:02:29 -0700767// TODO: rename to 'evict' for consistency
Eric Biggersa701c452018-10-23 13:06:55 -0700768bool fscrypt_lock_user_key(userid_t user_id) {
769 LOG(DEBUG) << "fscrypt_lock_user_key " << user_id;
770 if (fscrypt_is_native()) {
Andrew Scull7ec25c72016-10-31 10:28:25 +0000771 return evict_ce_key(user_id);
Eric Biggersa701c452018-10-23 13:06:55 -0700772 } else if (fscrypt_is_emulated()) {
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800773 // When in emulation mode, we just use chmod
Paul Crowley76107cb2016-02-09 10:04:39 +0000774 if (!emulated_lock(android::vold::BuildDataSystemCePath(user_id)) ||
Paul Crowleydf528a72016-03-09 09:31:37 -0800775 !emulated_lock(android::vold::BuildDataMiscCePath(user_id)) ||
Paul Crowley3b71fc52017-10-09 10:55:21 -0700776 !emulated_lock(android::vold::BuildDataMediaCePath("", user_id)) ||
777 !emulated_lock(android::vold::BuildDataUserCePath("", user_id))) {
Paul Crowley57eedbf2016-02-09 09:30:23 +0000778 LOG(ERROR) << "Failed to lock user " << user_id;
Paul Crowley76107cb2016-02-09 10:04:39 +0000779 return false;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800780 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800781 }
Jeff Sharkeyfc505c32015-12-07 17:27:01 -0700782
Paul Crowley76107cb2016-02-09 10:04:39 +0000783 return true;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800784}
785
Paul Crowley82b41ff2017-10-20 08:17:54 -0700786static bool prepare_subdirs(const std::string& action, const std::string& volume_uuid,
787 userid_t user_id, int flags) {
788 if (0 != android::vold::ForkExecvp(
789 std::vector<std::string>{prepare_subdirs_path, action, volume_uuid,
790 std::to_string(user_id), std::to_string(flags)})) {
791 LOG(ERROR) << "vold_prepare_subdirs failed";
Paul Crowley8e550662017-10-16 17:01:44 -0700792 return false;
793 }
794 return true;
795}
796
Eric Biggersa701c452018-10-23 13:06:55 -0700797bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial,
Paul Crowley3b71fc52017-10-09 10:55:21 -0700798 int flags) {
Eric Biggersa701c452018-10-23 13:06:55 -0700799 LOG(DEBUG) << "fscrypt_prepare_user_storage for volume " << escape_empty(volume_uuid)
Paul Crowleydf528a72016-03-09 09:31:37 -0800800 << ", user " << user_id << ", serial " << serial << ", flags " << flags;
Jeff Sharkey47695b22016-02-01 17:02:29 -0700801
Paul Crowley82b41ff2017-10-20 08:17:54 -0700802 if (flags & android::os::IVold::STORAGE_FLAG_DE) {
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600803 // DE_sys key
804 auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
805 auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
806 auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600807
808 // DE_n key
Jeff Sharkey47695b22016-02-01 17:02:29 -0700809 auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
810 auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
Andreas Huber71cd43f2018-01-22 11:25:29 -0800811 auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id);
Jeff Sharkey47695b22016-02-01 17:02:29 -0700812 auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
813
Paul Crowley3b71fc52017-10-09 10:55:21 -0700814 if (volume_uuid.empty()) {
Paul Crowley6b756ce2017-10-05 14:07:09 -0700815 if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600816#if MANAGE_MISC_DIRS
Paul Crowley6b756ce2017-10-05 14:07:09 -0700817 if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM),
Paul Crowley14c8c072018-09-18 13:30:21 -0700818 multiuser_get_uid(user_id, AID_EVERYBODY)))
819 return false;
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600820#endif
Paul Crowley6b756ce2017-10-05 14:07:09 -0700821 if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600822
Paul Crowley6b756ce2017-10-05 14:07:09 -0700823 if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
824 if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false;
Andreas Huber71cd43f2018-01-22 11:25:29 -0800825 if (!prepare_dir(vendor_de_path, 0771, AID_ROOT, AID_ROOT)) return false;
Paul Crowley6b756ce2017-10-05 14:07:09 -0700826 }
Paul Crowley76107cb2016-02-09 10:04:39 +0000827 if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
Calin Juravled1ee9442016-03-02 18:36:50 +0000828
Eric Biggersa701c452018-10-23 13:06:55 -0700829 if (fscrypt_is_native()) {
Paul Crowley3aa914d2017-10-09 16:35:51 -0700830 PolicyKeyRef de_ref;
Paul Crowley3b71fc52017-10-09 10:55:21 -0700831 if (volume_uuid.empty()) {
Paul Crowley3aa914d2017-10-09 16:35:51 -0700832 if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_ref.key_raw_ref)) return false;
833 get_data_file_encryption_modes(&de_ref);
834 if (!ensure_policy(de_ref, system_de_path)) return false;
835 if (!ensure_policy(de_ref, misc_de_path)) return false;
Andreas Huber71cd43f2018-01-22 11:25:29 -0800836 if (!ensure_policy(de_ref, vendor_de_path)) return false;
Paul Crowley3aa914d2017-10-09 16:35:51 -0700837 } else {
838 if (!read_or_create_volkey(misc_de_path, volume_uuid, &de_ref)) return false;
Paul Crowley6b756ce2017-10-05 14:07:09 -0700839 }
Paul Crowley3aa914d2017-10-09 16:35:51 -0700840 if (!ensure_policy(de_ref, user_de_path)) return false;
Jeff Sharkey47695b22016-02-01 17:02:29 -0700841 }
Paul Crowley285956f2016-01-20 13:12:38 +0000842 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800843
Paul Crowley82b41ff2017-10-20 08:17:54 -0700844 if (flags & android::os::IVold::STORAGE_FLAG_CE) {
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600845 // CE_n key
Jeff Sharkey47695b22016-02-01 17:02:29 -0700846 auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
847 auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
Andreas Huber71cd43f2018-01-22 11:25:29 -0800848 auto vendor_ce_path = android::vold::BuildDataVendorCePath(user_id);
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600849 auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id);
850 auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id);
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800851
Paul Crowley3b71fc52017-10-09 10:55:21 -0700852 if (volume_uuid.empty()) {
Paul Crowley6b756ce2017-10-05 14:07:09 -0700853 if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
854 if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false;
Andreas Huber71cd43f2018-01-22 11:25:29 -0800855 if (!prepare_dir(vendor_ce_path, 0771, AID_ROOT, AID_ROOT)) return false;
Paul Crowley6b756ce2017-10-05 14:07:09 -0700856 }
Paul Crowley76107cb2016-02-09 10:04:39 +0000857 if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
858 if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
Jeff Sharkey47695b22016-02-01 17:02:29 -0700859
Eric Biggersa701c452018-10-23 13:06:55 -0700860 if (fscrypt_is_native()) {
Paul Crowley3aa914d2017-10-09 16:35:51 -0700861 PolicyKeyRef ce_ref;
Paul Crowley3b71fc52017-10-09 10:55:21 -0700862 if (volume_uuid.empty()) {
Paul Crowley3aa914d2017-10-09 16:35:51 -0700863 if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_ref.key_raw_ref)) return false;
864 get_data_file_encryption_modes(&ce_ref);
865 if (!ensure_policy(ce_ref, system_ce_path)) return false;
866 if (!ensure_policy(ce_ref, misc_ce_path)) return false;
Andreas Huber71cd43f2018-01-22 11:25:29 -0800867 if (!ensure_policy(ce_ref, vendor_ce_path)) return false;
Paul Crowley6b756ce2017-10-05 14:07:09 -0700868
Paul Crowley3aa914d2017-10-09 16:35:51 -0700869 } else {
870 if (!read_or_create_volkey(misc_ce_path, volume_uuid, &ce_ref)) return false;
Paul Crowley6b756ce2017-10-05 14:07:09 -0700871 }
Paul Crowley3aa914d2017-10-09 16:35:51 -0700872 if (!ensure_policy(ce_ref, media_ce_path)) return false;
873 if (!ensure_policy(ce_ref, user_ce_path)) return false;
Jeff Sharkey47695b22016-02-01 17:02:29 -0700874 }
Paul Crowley1a965262017-10-13 13:49:50 -0700875
876 if (volume_uuid.empty()) {
Paul Crowley8e550662017-10-16 17:01:44 -0700877 // Now that credentials have been installed, we can run restorecon
878 // over these paths
879 // NOTE: these paths need to be kept in sync with libselinux
880 android::vold::RestoreconRecursive(system_ce_path);
881 android::vold::RestoreconRecursive(misc_ce_path);
Paul Crowley1a965262017-10-13 13:49:50 -0700882 }
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800883 }
Paul Crowley82b41ff2017-10-20 08:17:54 -0700884 if (!prepare_subdirs("prepare", volume_uuid, user_id, flags)) return false;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800885
Paul Crowley76107cb2016-02-09 10:04:39 +0000886 return true;
Jeff Sharkeyd2c96e72015-11-08 17:56:23 -0800887}
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600888
Eric Biggersa701c452018-10-23 13:06:55 -0700889bool fscrypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_id, int flags) {
890 LOG(DEBUG) << "fscrypt_destroy_user_storage for volume " << escape_empty(volume_uuid)
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600891 << ", user " << user_id << ", flags " << flags;
892 bool res = true;
893
Paul Crowley82b41ff2017-10-20 08:17:54 -0700894 res &= prepare_subdirs("destroy", volume_uuid, user_id, flags);
895
896 if (flags & android::os::IVold::STORAGE_FLAG_CE) {
Paul Crowley8e550662017-10-16 17:01:44 -0700897 // CE_n key
898 auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
899 auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
Andreas Huber71cd43f2018-01-22 11:25:29 -0800900 auto vendor_ce_path = android::vold::BuildDataVendorCePath(user_id);
Paul Crowley8e550662017-10-16 17:01:44 -0700901 auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id);
902 auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id);
903
904 res &= destroy_dir(media_ce_path);
905 res &= destroy_dir(user_ce_path);
906 if (volume_uuid.empty()) {
Paul Crowley8e550662017-10-16 17:01:44 -0700907 res &= destroy_dir(system_ce_path);
908 res &= destroy_dir(misc_ce_path);
Andreas Huber71cd43f2018-01-22 11:25:29 -0800909 res &= destroy_dir(vendor_ce_path);
Paul Crowley3aa914d2017-10-09 16:35:51 -0700910 } else {
Eric Biggersa701c452018-10-23 13:06:55 -0700911 if (fscrypt_is_native()) {
Paul Crowley3aa914d2017-10-09 16:35:51 -0700912 res &= destroy_volkey(misc_ce_path, volume_uuid);
913 }
Paul Crowley8e550662017-10-16 17:01:44 -0700914 }
915 }
916
Paul Crowley82b41ff2017-10-20 08:17:54 -0700917 if (flags & android::os::IVold::STORAGE_FLAG_DE) {
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600918 // DE_sys key
919 auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
920 auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
921 auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600922
923 // DE_n key
924 auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
925 auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
Andreas Huber71cd43f2018-01-22 11:25:29 -0800926 auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id);
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600927 auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
928
Paul Crowley8e550662017-10-16 17:01:44 -0700929 res &= destroy_dir(user_de_path);
Paul Crowley3b71fc52017-10-09 10:55:21 -0700930 if (volume_uuid.empty()) {
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600931 res &= destroy_dir(system_legacy_path);
932#if MANAGE_MISC_DIRS
933 res &= destroy_dir(misc_legacy_path);
934#endif
935 res &= destroy_dir(profiles_de_path);
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600936 res &= destroy_dir(system_de_path);
937 res &= destroy_dir(misc_de_path);
Andreas Huber71cd43f2018-01-22 11:25:29 -0800938 res &= destroy_dir(vendor_de_path);
Paul Crowley3aa914d2017-10-09 16:35:51 -0700939 } else {
Eric Biggersa701c452018-10-23 13:06:55 -0700940 if (fscrypt_is_native()) {
Paul Crowley3aa914d2017-10-09 16:35:51 -0700941 res &= destroy_volkey(misc_de_path, volume_uuid);
942 }
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600943 }
Jeff Sharkeybe70c9a2016-04-14 20:45:16 -0600944 }
945
946 return res;
947}
Rubin Xu2436e272017-04-27 20:43:10 +0100948
Paul Crowleyc6433a22017-10-24 14:54:43 -0700949static bool destroy_volume_keys(const std::string& directory_path, const std::string& volume_uuid) {
950 auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(directory_path.c_str()), closedir);
951 if (!dirp) {
952 PLOG(ERROR) << "Unable to open directory: " + directory_path;
953 return false;
954 }
955 bool res = true;
956 for (;;) {
957 errno = 0;
958 auto const entry = readdir(dirp.get());
959 if (!entry) {
960 if (errno) {
961 PLOG(ERROR) << "Unable to read directory: " + directory_path;
962 return false;
963 }
964 break;
965 }
966 if (entry->d_type != DT_DIR || entry->d_name[0] == '.') {
967 LOG(DEBUG) << "Skipping non-user " << entry->d_name;
968 continue;
969 }
970 res &= destroy_volkey(directory_path + "/" + entry->d_name, volume_uuid);
971 }
972 return res;
973}
974
Eric Biggersa701c452018-10-23 13:06:55 -0700975bool fscrypt_destroy_volume_keys(const std::string& volume_uuid) {
Paul Crowleyc6433a22017-10-24 14:54:43 -0700976 bool res = true;
Eric Biggersa701c452018-10-23 13:06:55 -0700977 LOG(DEBUG) << "fscrypt_destroy_volume_keys for volume " << escape_empty(volume_uuid);
Paul Crowley26a53882017-10-26 11:16:39 -0700978 auto secdiscardable_path = volume_secdiscardable_path(volume_uuid);
979 res &= android::vold::runSecdiscardSingle(secdiscardable_path);
Paul Crowleyc6433a22017-10-24 14:54:43 -0700980 res &= destroy_volume_keys("/data/misc_ce", volume_uuid);
981 res &= destroy_volume_keys("/data/misc_de", volume_uuid);
982 return res;
983}