blob: b53ecd416166edacf6941d76481fce03f1c50c11 [file] [log] [blame]
bigbiff7ba75002020-04-11 20:47:09 -04001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "MetadataCrypt.h"
18#include "KeyBuffer.h"
19
20#include <algorithm>
21#include <string>
22#include <thread>
23#include <vector>
24
25#include <fcntl.h>
bigbiff7ba75002020-04-11 20:47:09 -040026#include <sys/param.h>
27#include <sys/stat.h>
28#include <sys/types.h>
29
bigbiff7ba75002020-04-11 20:47:09 -040030#include <android-base/file.h>
31#include <android-base/logging.h>
32#include <android-base/properties.h>
bigbiffa957f072021-03-07 18:20:29 -050033#include <android-base/strings.h>
bigbiff7ba75002020-04-11 20:47:09 -040034#include <android-base/unique_fd.h>
35#include <cutils/fs.h>
36#include <fs_mgr.h>
bigbiffa957f072021-03-07 18:20:29 -050037#include <libdm/dm.h>
bigbiff7ba75002020-04-11 20:47:09 -040038
39#include "Checkpoint.h"
bigbiffa957f072021-03-07 18:20:29 -050040#include "CryptoType.h"
bigbiff7ba75002020-04-11 20:47:09 -040041#include "EncryptInplace.h"
bigbiffbcd23d32021-09-22 18:22:13 -040042#include "FsCrypt.h"
bigbiff7ba75002020-04-11 20:47:09 -040043#include "KeyStorage.h"
44#include "KeyUtil.h"
45#include "Keymaster.h"
46#include "Utils.h"
47#include "VoldUtil.h"
48
bigbiff7ba75002020-04-11 20:47:09 -040049#define TABLE_LOAD_RETRIES 10
bigbiffa957f072021-03-07 18:20:29 -050050
bigbiff7ba75002020-04-11 20:47:09 -040051
52using android::fs_mgr::FstabEntry;
53using android::fs_mgr::GetEntryForMountPoint;
bigbiffa957f072021-03-07 18:20:29 -050054using ::KeyBuffer;
55using namespace android::dm;
56
57// Parsed from metadata options
58struct CryptoOptions {
59 struct CryptoType cipher = invalid_crypto_type;
60 bool use_legacy_options_format = false;
61 bool set_dun = true; // Non-legacy driver always sets DUN
62 bool use_hw_wrapped_key = false;
63};
bigbiff7ba75002020-04-11 20:47:09 -040064
65static const std::string kDmNameUserdata = "userdata";
66
67static const char* kFn_keymaster_key_blob = "keymaster_key_blob";
68static const char* kFn_keymaster_key_blob_upgraded = "keymaster_key_blob_upgraded";
69
bigbiffa957f072021-03-07 18:20:29 -050070// The first entry in this table is the default crypto type.
71constexpr CryptoType supported_crypto_types[] = {aes_256_xts, adiantum};
72
73static_assert(validateSupportedCryptoTypes(64, supported_crypto_types,
74 array_length(supported_crypto_types)),
75 "We have a CryptoType which was incompletely constructed.");
76
77constexpr CryptoType legacy_aes_256_xts =
78 CryptoType().set_config_name("aes-256-xts").set_kernel_name("AES-256-XTS").set_keysize(64);
79
80static_assert(isValidCryptoType(64, legacy_aes_256_xts),
81 "We have a CryptoType which was incompletely constructed.");
82
83// Returns KeyGeneration suitable for key as described in CryptoOptions
84const KeyGeneration makeGen(const CryptoOptions& options) {
85 return KeyGeneration{options.cipher.get_keysize(), true, options.use_hw_wrapped_key};
86}
87
bigbiff7ba75002020-04-11 20:47:09 -040088static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
bigbiffa957f072021-03-07 18:20:29 -050089 // We're about to mount data not verified by verified boot. Tell Keymaster instances that early
90 // boot has ended.
91 ::Keymaster::earlyBootEnded();
92
bigbiff7ba75002020-04-11 20:47:09 -040093 // fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
94 // partitions in the fsck domain.
bigbiffa957f072021-03-07 18:20:29 -050095 if (setexeccon(::sFsckContext)) {
bigbiff7ba75002020-04-11 20:47:09 -040096 PLOG(ERROR) << "Failed to setexeccon";
97 return false;
98 }
bigbiffa957f072021-03-07 18:20:29 -050099
100 if (!ReadDefaultFstab(&fstab_default)) {
101 PLOG(ERROR) << "Failed to open default fstab";
102 return -1;
103 }
bigbiff7ba75002020-04-11 20:47:09 -0400104 auto mount_rc = fs_mgr_do_mount(&fstab_default, const_cast<char*>(mount_point),
105 const_cast<char*>(blk_device), nullptr,
bigbiffa957f072021-03-07 18:20:29 -0500106 ::cp_needsCheckpoint(), true);
bigbiff7ba75002020-04-11 20:47:09 -0400107 if (setexeccon(nullptr)) {
108 PLOG(ERROR) << "Failed to clear setexeccon";
109 return false;
110 }
111 if (mount_rc != 0) {
112 LOG(ERROR) << "fs_mgr_do_mount failed with rc " << mount_rc;
113 return false;
114 }
bigbiffa957f072021-03-07 18:20:29 -0500115 LOG(INFO) << "mount_via_fs_mgr::Mounted " << mount_point;
bigbiff7ba75002020-04-11 20:47:09 -0400116 return true;
117}
118
bigbiff7ba75002020-04-11 20:47:09 -0400119// Note: It is possible to orphan a key if it is removed before deleting
120// Update this once keymaster APIs change, and we have a proper commit.
121static void commit_key(const std::string& dir) {
122 while (!android::base::WaitForProperty("vold.checkpoint_committed", "1")) {
123 LOG(ERROR) << "Wait for boot timed out";
124 }
125 Keymaster keymaster;
126 auto keyPath = dir + "/" + kFn_keymaster_key_blob;
127 auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
128 std::string key;
129
130 if (!android::base::ReadFileToString(keyPath, &key)) {
131 LOG(ERROR) << "Failed to read old key: " << dir;
132 return;
133 }
134 if (rename(newKeyPath.c_str(), keyPath.c_str()) != 0) {
135 PLOG(ERROR) << "Unable to move upgraded key to location: " << keyPath;
136 return;
137 }
138 if (!keymaster.deleteKey(key)) {
139 LOG(ERROR) << "Key deletion failed during upgrade, continuing anyway: " << dir;
140 }
141 LOG(INFO) << "Old Key deleted: " << dir;
142}
143
bigbiffa957f072021-03-07 18:20:29 -0500144static bool read_key(const std::string& metadata_key_dir, const KeyGeneration& gen,
145 KeyBuffer* key) {
146 if (metadata_key_dir.empty()) {
147 LOG(ERROR) << "Failed to get metadata_key_dir";
bigbiff7ba75002020-04-11 20:47:09 -0400148 return false;
149 }
bigbiff7ba75002020-04-11 20:47:09 -0400150 std::string sKey;
bigbiffa957f072021-03-07 18:20:29 -0500151 auto dir = metadata_key_dir + "/key";
152 LOG(INFO) << "metadata_key_dir/key: " << dir;
bigbiff7ba75002020-04-11 20:47:09 -0400153 if (fs_mkdirs(dir.c_str(), 0700)) {
154 PLOG(ERROR) << "Creating directories: " << dir;
155 return false;
156 }
bigbiffa957f072021-03-07 18:20:29 -0500157 auto temp = metadata_key_dir + "/tmp";
bigbiff7ba75002020-04-11 20:47:09 -0400158 auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
159 /* If we have a leftover upgraded key, delete it.
160 * We either failed an update and must return to the old key,
161 * or we rebooted before commiting the keys in a freak accident.
162 * Either way, we can re-upgrade the key if we need to.
163 */
bigbiffbbbfe172021-05-30 15:52:41 -0400164
bigbiff7ba75002020-04-11 20:47:09 -0400165 Keymaster keymaster;
166 if (pathExists(newKeyPath)) {
167 if (!android::base::ReadFileToString(newKeyPath, &sKey))
bigbiffa957f072021-03-07 18:20:29 -0500168 LOG(ERROR) << "Failed to read incomplete key: " << dir;
bigbiff7ba75002020-04-11 20:47:09 -0400169 else if (!keymaster.deleteKey(sKey))
bigbiffa957f072021-03-07 18:20:29 -0500170 LOG(ERROR) << "Incomplete key deletion failed, continuing anyway: " << dir;
bigbiff7ba75002020-04-11 20:47:09 -0400171 else
172 unlink(newKeyPath.c_str());
173 }
bigbiffa957f072021-03-07 18:20:29 -0500174 bool needs_cp = cp_needsCheckpoint();
bigbiffbbbfe172021-05-30 15:52:41 -0400175 if (!retrieveOrGenerateKey(dir, temp, kEmptyAuthentication, gen, key, true)) return false;
bigbiff7ba75002020-04-11 20:47:09 -0400176 if (needs_cp && pathExists(newKeyPath)) std::thread(commit_key, dir).detach();
177 return true;
178}
179
bigbiff7ba75002020-04-11 20:47:09 -0400180static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_sec) {
bigbiffa957f072021-03-07 18:20:29 -0500181 if (::GetBlockDev512Sectors(real_blkdev, nr_sec) != android::OK) {
bigbiff7ba75002020-04-11 20:47:09 -0400182 PLOG(ERROR) << "Unable to measure size of " << real_blkdev;
183 return false;
184 }
185 return true;
186}
187
bigbiffa957f072021-03-07 18:20:29 -0500188static bool create_crypto_blk_dev(const std::string& dm_name, const std::string& blk_device,
189 const KeyBuffer& key, const CryptoOptions& options,
190 std::string* crypto_blkdev, uint64_t* nr_sec) {
191 if (!get_number_of_sectors(blk_device, nr_sec)) return false;
192 // TODO(paulcrowley): don't hardcode that DmTargetDefaultKey uses 4096-byte
193 // sectors
194 *nr_sec &= ~7;
195
196 KeyBuffer module_key;
197 if (options.use_hw_wrapped_key) {
198 if (!exportWrappedStorageKey(key, &module_key)) {
199 LOG(ERROR) << "Failed to get ephemeral wrapped key";
200 return false;
201 }
202 } else {
203 module_key = key;
bigbiff7ba75002020-04-11 20:47:09 -0400204 }
205
bigbiffa957f072021-03-07 18:20:29 -0500206 KeyBuffer hex_key_buffer;
207 if (::StrToHex(module_key, hex_key_buffer) != android::OK) {
208 LOG(ERROR) << "Failed to turn key to hex";
bigbiff7ba75002020-04-11 20:47:09 -0400209 return false;
210 }
bigbiffa957f072021-03-07 18:20:29 -0500211 std::string hex_key(hex_key_buffer.data(), hex_key_buffer.size());
bigbiff7ba75002020-04-11 20:47:09 -0400212
bigbiffa957f072021-03-07 18:20:29 -0500213 auto target = std::make_unique<DmTargetDefaultKey>(0, *nr_sec, options.cipher.get_kernel_name(),
214 hex_key, blk_device, 0);
215 if (options.use_legacy_options_format) target->SetUseLegacyOptionsFormat();
216 if (options.set_dun) target->SetSetDun();
217 if (options.use_hw_wrapped_key) target->SetWrappedKeyV0();
bigbiff7ba75002020-04-11 20:47:09 -0400218
bigbiffa957f072021-03-07 18:20:29 -0500219 DmTable table;
220 table.AddTarget(std::move(target));
bigbiff7ba75002020-04-11 20:47:09 -0400221
bigbiffa957f072021-03-07 18:20:29 -0500222 auto& dm = DeviceMapper::Instance();
bigbiff7ba75002020-04-11 20:47:09 -0400223 for (int i = 0;; i++) {
bigbiffa957f072021-03-07 18:20:29 -0500224 if (dm.CreateDevice(dm_name, table)) {
bigbiff7ba75002020-04-11 20:47:09 -0400225 break;
226 }
227 if (i + 1 >= TABLE_LOAD_RETRIES) {
bigbiffa957f072021-03-07 18:20:29 -0500228 PLOG(ERROR) << "Could not create default-key device " << dm_name;
bigbiff7ba75002020-04-11 20:47:09 -0400229 return false;
230 }
bigbiffa957f072021-03-07 18:20:29 -0500231 PLOG(INFO) << "Could not create default-key device, retrying";
bigbiff7ba75002020-04-11 20:47:09 -0400232 usleep(500000);
233 }
234
bigbiffa957f072021-03-07 18:20:29 -0500235 if (!dm.GetDmDevicePathByName(dm_name, crypto_blkdev)) {
236 LOG(ERROR) << "Cannot retrieve default-key device status " << dm_name;
bigbiff7ba75002020-04-11 20:47:09 -0400237 return false;
238 }
bigbiffa957f072021-03-07 18:20:29 -0500239 std::stringstream ss;
240 ss << *crypto_blkdev;
241 LOG(INFO) << "Created device: " << ss.str();
242 return true;
243}
244
245static const CryptoType& lookup_cipher(const std::string& cipher_name) {
246 if (cipher_name.empty()) return supported_crypto_types[0];
247 for (size_t i = 0; i < array_length(supported_crypto_types); i++) {
248 if (cipher_name == supported_crypto_types[i].get_config_name()) {
249 return supported_crypto_types[i];
250 }
251 }
252 return invalid_crypto_type;
253}
254
255static bool parse_options(const std::string& options_string, CryptoOptions* options) {
256 auto parts = android::base::Split(options_string, ":");
257 if (parts.size() < 1 || parts.size() > 2) {
258 LOG(ERROR) << "Invalid metadata encryption option: " << options_string;
259 return false;
260 }
261 std::string cipher_name = parts[0];
262 options->cipher = lookup_cipher(cipher_name);
263 if (options->cipher.get_kernel_name() == nullptr) {
264 LOG(ERROR) << "No metadata cipher named " << cipher_name << " found";
265 return false;
266 }
267
268 if (parts.size() == 2) {
269 if (parts[1] == "wrappedkey_v0") {
270 options->use_hw_wrapped_key = true;
271 } else {
272 LOG(ERROR) << "Invalid metadata encryption flag: " << parts[1];
273 return false;
274 }
275 }
bigbiff7ba75002020-04-11 20:47:09 -0400276 return true;
277}
278
279bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::string& mount_point,
280 bool needs_encrypt) {
bigbiffa957f072021-03-07 18:20:29 -0500281 LOG(INFO) << "fscrypt_mount_metadata_encrypted: " << mount_point << " " << needs_encrypt;
282 auto encrypted_state = android::base::GetProperty("ro.crypto.state", "");
283 if (encrypted_state != "" && encrypted_state != "encrypted") {
284 LOG(ERROR) << "fscrypt_enable_crypto got unexpected starting state: " << encrypted_state;
285 return false;
286 }
bigbiff7ba75002020-04-11 20:47:09 -0400287 if (!ReadDefaultFstab(&fstab_default)) {
288 PLOG(ERROR) << "Failed to open default fstab";
289 return -1;
290 }
bigbiff7ba75002020-04-11 20:47:09 -0400291 auto data_rec = GetEntryForMountPoint(&fstab_default, mount_point);
292 if (!data_rec) {
bigbiffa957f072021-03-07 18:20:29 -0500293 LOG(ERROR) << "Failed to get data_rec for " << mount_point;
bigbiff7ba75002020-04-11 20:47:09 -0400294 return false;
295 }
bigbiffa957f072021-03-07 18:20:29 -0500296
297 constexpr unsigned int pre_gki_level = 29;
298 unsigned int options_format_version = android::base::GetUintProperty<unsigned int>(
299 "ro.crypto.dm_default_key.options_format.version",
300 (GetFirstApiLevel() <= pre_gki_level ? 1 : 2));
301
302 CryptoOptions options;
303 if (options_format_version == 1) {
304 if (!data_rec->metadata_encryption.empty()) {
305 LOG(ERROR) << "metadata_encryption options cannot be set in legacy mode";
306 return false;
307 }
308 options.cipher = legacy_aes_256_xts;
309 options.use_legacy_options_format = true;
bigbiffbcd23d32021-09-22 18:22:13 -0400310 if (is_metadata_wrapped_key_supported()) {
311 options.use_hw_wrapped_key = true;
312 LOG(INFO) << "metadata_wrapped_key_true";
313 }
bigbiffa957f072021-03-07 18:20:29 -0500314 options.set_dun = android::base::GetBoolProperty("ro.crypto.set_dun", false);
315 if (!options.set_dun && data_rec->fs_mgr_flags.checkpoint_blk) {
316 LOG(ERROR)
317 << "Block checkpoints and metadata encryption require ro.crypto.set_dun option";
318 return false;
319 }
320 } else if (options_format_version == 2) {
321 if (!parse_options(data_rec->metadata_encryption, &options)) return false;
322 } else {
323 LOG(ERROR) << "Unknown options_format_version: " << options_format_version;
bigbiff7ba75002020-04-11 20:47:09 -0400324 return false;
bigbiffa957f072021-03-07 18:20:29 -0500325 }
326
327 auto gen = needs_encrypt ? makeGen(options) : neverGen();
328 KeyBuffer key;
329 if (!read_key(data_rec->metadata_key_dir, gen, &key)) return false;
330
331 std::string crypto_blkdev;
332 uint64_t nr_sec;
333 if (!create_crypto_blk_dev(kDmNameUserdata, blk_device, key, options, &crypto_blkdev, &nr_sec))
334 return false;
335
bigbiff7ba75002020-04-11 20:47:09 -0400336 // FIXME handle the corrupt case
337 if (needs_encrypt) {
338 LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec;
339 off64_t size_already_done = 0;
340 auto rc = cryptfs_enable_inplace(crypto_blkdev.data(), blk_device.data(), nr_sec,
341 &size_already_done, nr_sec, 0, false);
342 if (rc != 0) {
343 LOG(ERROR) << "Inplace crypto failed with code: " << rc;
344 return false;
345 }
346 if (static_cast<uint64_t>(size_already_done) != nr_sec) {
347 LOG(ERROR) << "Inplace crypto only got up to sector: " << size_already_done;
348 return false;
349 }
350 LOG(INFO) << "Inplace encryption complete";
351 }
352
bigbiffa957f072021-03-07 18:20:29 -0500353 LOG(INFO) << "Mounting metadata-encrypted filesystem:" << mount_point;
354 mount_via_fs_mgr(mount_point.c_str(), crypto_blkdev.c_str());
bigbiff7ba75002020-04-11 20:47:09 -0400355 android::base::SetProperty("ro.crypto.fs_crypto_blkdev", crypto_blkdev);
bigbiffa957f072021-03-07 18:20:29 -0500356
357 // Record that there's at least one fstab entry with metadata encryption
358 if (!android::base::SetProperty("ro.crypto.metadata.enabled", "true")) {
359 LOG(WARNING) << "failed to set ro.crypto.metadata.enabled"; // This isn't fatal
360 }
bigbiff7ba75002020-04-11 20:47:09 -0400361 return true;
362}
bigbiffa957f072021-03-07 18:20:29 -0500363
364static bool get_volume_options(CryptoOptions* options) {
365 return parse_options(android::base::GetProperty("ro.crypto.volume.metadata.encryption", ""),
366 options);
367}
368
369bool defaultkey_volume_keygen(KeyGeneration* gen) {
370 CryptoOptions options;
371 if (!get_volume_options(&options)) return false;
372 *gen = makeGen(options);
373 return true;
374}
375
376bool defaultkey_setup_ext_volume(const std::string& label, const std::string& blk_device,
377 const KeyBuffer& key, std::string* out_crypto_blkdev) {
378 LOG(ERROR) << "defaultkey_setup_ext_volume: " << label << " " << blk_device;
379
380 CryptoOptions options;
381 if (!get_volume_options(&options)) return false;
382 uint64_t nr_sec;
383 return create_crypto_blk_dev(label, blk_device, key, options, out_crypto_blkdev, &nr_sec);
384}