1*f40fafd4SAndroid Build Coastguard Worker /*
2*f40fafd4SAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project
3*f40fafd4SAndroid Build Coastguard Worker *
4*f40fafd4SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*f40fafd4SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*f40fafd4SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*f40fafd4SAndroid Build Coastguard Worker *
8*f40fafd4SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*f40fafd4SAndroid Build Coastguard Worker *
10*f40fafd4SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*f40fafd4SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*f40fafd4SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*f40fafd4SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*f40fafd4SAndroid Build Coastguard Worker * limitations under the License.
15*f40fafd4SAndroid Build Coastguard Worker */
16*f40fafd4SAndroid Build Coastguard Worker
17*f40fafd4SAndroid Build Coastguard Worker //
18*f40fafd4SAndroid Build Coastguard Worker // This file contains the implementation of the dm-crypt volume metadata
19*f40fafd4SAndroid Build Coastguard Worker // encryption method, which is deprecated. Devices that launched with Android
20*f40fafd4SAndroid Build Coastguard Worker // 11 or higher use a different method instead. For details, see
21*f40fafd4SAndroid Build Coastguard Worker // https://source.android.com/security/encryption/metadata#configuration-on-adoptable-storage
22*f40fafd4SAndroid Build Coastguard Worker //
23*f40fafd4SAndroid Build Coastguard Worker
24*f40fafd4SAndroid Build Coastguard Worker #define LOG_TAG "Cryptfs"
25*f40fafd4SAndroid Build Coastguard Worker
26*f40fafd4SAndroid Build Coastguard Worker #include "cryptfs.h"
27*f40fafd4SAndroid Build Coastguard Worker
28*f40fafd4SAndroid Build Coastguard Worker #include "CryptoType.h"
29*f40fafd4SAndroid Build Coastguard Worker #include "Utils.h"
30*f40fafd4SAndroid Build Coastguard Worker
31*f40fafd4SAndroid Build Coastguard Worker #include <android-base/parseint.h>
32*f40fafd4SAndroid Build Coastguard Worker #include <android-base/properties.h>
33*f40fafd4SAndroid Build Coastguard Worker #include <cutils/properties.h>
34*f40fafd4SAndroid Build Coastguard Worker #include <libdm/dm.h>
35*f40fafd4SAndroid Build Coastguard Worker #include <log/log.h>
36*f40fafd4SAndroid Build Coastguard Worker
37*f40fafd4SAndroid Build Coastguard Worker #include <chrono>
38*f40fafd4SAndroid Build Coastguard Worker
39*f40fafd4SAndroid Build Coastguard Worker using android::base::ParseUint;
40*f40fafd4SAndroid Build Coastguard Worker using android::vold::CryptoType;
41*f40fafd4SAndroid Build Coastguard Worker using android::vold::KeyBuffer;
42*f40fafd4SAndroid Build Coastguard Worker using android::vold::KeyGeneration;
43*f40fafd4SAndroid Build Coastguard Worker using namespace android::dm;
44*f40fafd4SAndroid Build Coastguard Worker using namespace android::vold;
45*f40fafd4SAndroid Build Coastguard Worker using namespace std::chrono_literals;
46*f40fafd4SAndroid Build Coastguard Worker
47*f40fafd4SAndroid Build Coastguard Worker #define MAX_KEY_LEN 48
48*f40fafd4SAndroid Build Coastguard Worker
49*f40fafd4SAndroid Build Coastguard Worker #define TABLE_LOAD_RETRIES 10
50*f40fafd4SAndroid Build Coastguard Worker
51*f40fafd4SAndroid Build Coastguard Worker constexpr CryptoType aes_128_cbc = CryptoType()
52*f40fafd4SAndroid Build Coastguard Worker .set_config_name("AES-128-CBC")
53*f40fafd4SAndroid Build Coastguard Worker .set_kernel_name("aes-cbc-essiv:sha256")
54*f40fafd4SAndroid Build Coastguard Worker .set_keysize(16);
55*f40fafd4SAndroid Build Coastguard Worker
56*f40fafd4SAndroid Build Coastguard Worker constexpr CryptoType supported_crypto_types[] = {aes_128_cbc, android::vold::adiantum};
57*f40fafd4SAndroid Build Coastguard Worker
58*f40fafd4SAndroid Build Coastguard Worker static_assert(validateSupportedCryptoTypes(MAX_KEY_LEN, supported_crypto_types,
59*f40fafd4SAndroid Build Coastguard Worker array_length(supported_crypto_types)),
60*f40fafd4SAndroid Build Coastguard Worker "We have a CryptoType with keysize > MAX_KEY_LEN or which was "
61*f40fafd4SAndroid Build Coastguard Worker "incompletely constructed.");
62*f40fafd4SAndroid Build Coastguard Worker
get_crypto_type()63*f40fafd4SAndroid Build Coastguard Worker static const CryptoType& get_crypto_type() {
64*f40fafd4SAndroid Build Coastguard Worker // We only want to parse this read-only property once. But we need to wait
65*f40fafd4SAndroid Build Coastguard Worker // until the system is initialized before we can read it. So we use a static
66*f40fafd4SAndroid Build Coastguard Worker // scoped within this function to get it only once.
67*f40fafd4SAndroid Build Coastguard Worker static CryptoType crypto_type =
68*f40fafd4SAndroid Build Coastguard Worker lookup_crypto_algorithm(supported_crypto_types, array_length(supported_crypto_types),
69*f40fafd4SAndroid Build Coastguard Worker aes_128_cbc, "ro.crypto.fde_algorithm");
70*f40fafd4SAndroid Build Coastguard Worker return crypto_type;
71*f40fafd4SAndroid Build Coastguard Worker }
72*f40fafd4SAndroid Build Coastguard Worker
cryptfs_get_keygen()73*f40fafd4SAndroid Build Coastguard Worker const KeyGeneration cryptfs_get_keygen() {
74*f40fafd4SAndroid Build Coastguard Worker return KeyGeneration{get_crypto_type().get_keysize(), true, false};
75*f40fafd4SAndroid Build Coastguard Worker }
76*f40fafd4SAndroid Build Coastguard Worker
77*f40fafd4SAndroid Build Coastguard Worker /* Convert a binary key of specified length into an ascii hex string equivalent,
78*f40fafd4SAndroid Build Coastguard Worker * without the leading 0x and with null termination
79*f40fafd4SAndroid Build Coastguard Worker */
convert_key_to_hex_ascii(const KeyBuffer & key,char * key_ascii)80*f40fafd4SAndroid Build Coastguard Worker static void convert_key_to_hex_ascii(const KeyBuffer& key, char* key_ascii) {
81*f40fafd4SAndroid Build Coastguard Worker unsigned int i, a;
82*f40fafd4SAndroid Build Coastguard Worker unsigned char nibble;
83*f40fafd4SAndroid Build Coastguard Worker
84*f40fafd4SAndroid Build Coastguard Worker for (i = 0, a = 0; i < key.size(); i++, a += 2) {
85*f40fafd4SAndroid Build Coastguard Worker /* For each byte, write out two ascii hex digits */
86*f40fafd4SAndroid Build Coastguard Worker nibble = (key[i] >> 4) & 0xf;
87*f40fafd4SAndroid Build Coastguard Worker key_ascii[a] = nibble + (nibble > 9 ? 0x37 : 0x30);
88*f40fafd4SAndroid Build Coastguard Worker
89*f40fafd4SAndroid Build Coastguard Worker nibble = key[i] & 0xf;
90*f40fafd4SAndroid Build Coastguard Worker key_ascii[a + 1] = nibble + (nibble > 9 ? 0x37 : 0x30);
91*f40fafd4SAndroid Build Coastguard Worker }
92*f40fafd4SAndroid Build Coastguard Worker
93*f40fafd4SAndroid Build Coastguard Worker /* Add the null termination */
94*f40fafd4SAndroid Build Coastguard Worker key_ascii[a] = '\0';
95*f40fafd4SAndroid Build Coastguard Worker }
96*f40fafd4SAndroid Build Coastguard Worker
97*f40fafd4SAndroid Build Coastguard Worker /*
98*f40fafd4SAndroid Build Coastguard Worker * Called by vold when it's asked to mount an encrypted external
99*f40fafd4SAndroid Build Coastguard Worker * storage volume. The incoming partition has no crypto header/footer,
100*f40fafd4SAndroid Build Coastguard Worker * as any metadata is been stored in a separate, small partition. We
101*f40fafd4SAndroid Build Coastguard Worker * assume it must be using our same crypt type and keysize.
102*f40fafd4SAndroid Build Coastguard Worker */
cryptfs_setup_ext_volume(const char * label,const char * real_blkdev,const KeyBuffer & key,std::string * out_crypto_blkdev)103*f40fafd4SAndroid Build Coastguard Worker int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const KeyBuffer& key,
104*f40fafd4SAndroid Build Coastguard Worker std::string* out_crypto_blkdev) {
105*f40fafd4SAndroid Build Coastguard Worker auto crypto_type = get_crypto_type();
106*f40fafd4SAndroid Build Coastguard Worker if (key.size() != crypto_type.get_keysize()) {
107*f40fafd4SAndroid Build Coastguard Worker SLOGE("Raw keysize %zu does not match crypt keysize %zu", key.size(),
108*f40fafd4SAndroid Build Coastguard Worker crypto_type.get_keysize());
109*f40fafd4SAndroid Build Coastguard Worker return -1;
110*f40fafd4SAndroid Build Coastguard Worker }
111*f40fafd4SAndroid Build Coastguard Worker uint64_t nr_sec = 0;
112*f40fafd4SAndroid Build Coastguard Worker if (android::vold::GetBlockDev512Sectors(real_blkdev, &nr_sec) != android::OK) {
113*f40fafd4SAndroid Build Coastguard Worker SLOGE("Failed to get size of %s: %s", real_blkdev, strerror(errno));
114*f40fafd4SAndroid Build Coastguard Worker return -1;
115*f40fafd4SAndroid Build Coastguard Worker }
116*f40fafd4SAndroid Build Coastguard Worker
117*f40fafd4SAndroid Build Coastguard Worker constexpr char DM_CRYPT_SECTOR_SIZE[] = "ro.crypto.fde_sector_size";
118*f40fafd4SAndroid Build Coastguard Worker char value[PROPERTY_VALUE_MAX];
119*f40fafd4SAndroid Build Coastguard Worker unsigned int sector_size = 0;
120*f40fafd4SAndroid Build Coastguard Worker
121*f40fafd4SAndroid Build Coastguard Worker if (property_get(DM_CRYPT_SECTOR_SIZE, value, "") > 0) {
122*f40fafd4SAndroid Build Coastguard Worker if (!ParseUint(value, §or_size) || sector_size < 512 || sector_size > 4096 ||
123*f40fafd4SAndroid Build Coastguard Worker (sector_size & (sector_size - 1)) != 0) {
124*f40fafd4SAndroid Build Coastguard Worker SLOGE("Invalid value for %s: %s. Must be >= 512, <= 4096, and a power of 2\n",
125*f40fafd4SAndroid Build Coastguard Worker DM_CRYPT_SECTOR_SIZE, value);
126*f40fafd4SAndroid Build Coastguard Worker return -1;
127*f40fafd4SAndroid Build Coastguard Worker }
128*f40fafd4SAndroid Build Coastguard Worker }
129*f40fafd4SAndroid Build Coastguard Worker
130*f40fafd4SAndroid Build Coastguard Worker // Round the crypto device size down to a crypto sector boundary.
131*f40fafd4SAndroid Build Coastguard Worker if (sector_size > 0) {
132*f40fafd4SAndroid Build Coastguard Worker nr_sec &= ~((sector_size / 512) - 1);
133*f40fafd4SAndroid Build Coastguard Worker }
134*f40fafd4SAndroid Build Coastguard Worker
135*f40fafd4SAndroid Build Coastguard Worker auto& dm = DeviceMapper::Instance();
136*f40fafd4SAndroid Build Coastguard Worker // We need two ASCII characters to represent each byte, and need space for
137*f40fafd4SAndroid Build Coastguard Worker // the '\0' terminator.
138*f40fafd4SAndroid Build Coastguard Worker char key_ascii[MAX_KEY_LEN * 2 + 1];
139*f40fafd4SAndroid Build Coastguard Worker convert_key_to_hex_ascii(key, key_ascii);
140*f40fafd4SAndroid Build Coastguard Worker
141*f40fafd4SAndroid Build Coastguard Worker auto target = std::make_unique<DmTargetCrypt>(0, nr_sec, crypto_type.get_kernel_name(),
142*f40fafd4SAndroid Build Coastguard Worker key_ascii, 0, real_blkdev, 0);
143*f40fafd4SAndroid Build Coastguard Worker target->AllowDiscards();
144*f40fafd4SAndroid Build Coastguard Worker
145*f40fafd4SAndroid Build Coastguard Worker if (IsFbeEnabled() &&
146*f40fafd4SAndroid Build Coastguard Worker android::base::GetBoolProperty("ro.crypto.allow_encrypt_override", false)) {
147*f40fafd4SAndroid Build Coastguard Worker target->AllowEncryptOverride();
148*f40fafd4SAndroid Build Coastguard Worker }
149*f40fafd4SAndroid Build Coastguard Worker
150*f40fafd4SAndroid Build Coastguard Worker // Append the parameters to make dm-crypt use the specified crypto sector size.
151*f40fafd4SAndroid Build Coastguard Worker if (sector_size > 0) {
152*f40fafd4SAndroid Build Coastguard Worker target->SetSectorSize(sector_size);
153*f40fafd4SAndroid Build Coastguard Worker // With this option, IVs will match the sector numbering, instead
154*f40fafd4SAndroid Build Coastguard Worker // of being hard-coded to being based on 512-byte sectors.
155*f40fafd4SAndroid Build Coastguard Worker target->SetIvLargeSectors();
156*f40fafd4SAndroid Build Coastguard Worker }
157*f40fafd4SAndroid Build Coastguard Worker
158*f40fafd4SAndroid Build Coastguard Worker DmTable table;
159*f40fafd4SAndroid Build Coastguard Worker table.AddTarget(std::move(target));
160*f40fafd4SAndroid Build Coastguard Worker
161*f40fafd4SAndroid Build Coastguard Worker int load_count = 1;
162*f40fafd4SAndroid Build Coastguard Worker while (load_count < TABLE_LOAD_RETRIES) {
163*f40fafd4SAndroid Build Coastguard Worker if (dm.CreateDevice(label, table)) {
164*f40fafd4SAndroid Build Coastguard Worker break;
165*f40fafd4SAndroid Build Coastguard Worker }
166*f40fafd4SAndroid Build Coastguard Worker load_count++;
167*f40fafd4SAndroid Build Coastguard Worker }
168*f40fafd4SAndroid Build Coastguard Worker
169*f40fafd4SAndroid Build Coastguard Worker if (load_count >= TABLE_LOAD_RETRIES) {
170*f40fafd4SAndroid Build Coastguard Worker SLOGE("Cannot load dm-crypt mapping table.\n");
171*f40fafd4SAndroid Build Coastguard Worker return -1;
172*f40fafd4SAndroid Build Coastguard Worker }
173*f40fafd4SAndroid Build Coastguard Worker if (load_count > 1) {
174*f40fafd4SAndroid Build Coastguard Worker SLOGI("Took %d tries to load dmcrypt table.\n", load_count);
175*f40fafd4SAndroid Build Coastguard Worker }
176*f40fafd4SAndroid Build Coastguard Worker
177*f40fafd4SAndroid Build Coastguard Worker if (!dm.GetDmDevicePathByName(label, out_crypto_blkdev)) {
178*f40fafd4SAndroid Build Coastguard Worker SLOGE("Cannot determine dm-crypt path for %s.\n", label);
179*f40fafd4SAndroid Build Coastguard Worker return -1;
180*f40fafd4SAndroid Build Coastguard Worker }
181*f40fafd4SAndroid Build Coastguard Worker
182*f40fafd4SAndroid Build Coastguard Worker /* Ensure the dm device has been created before returning. */
183*f40fafd4SAndroid Build Coastguard Worker if (android::vold::WaitForFile(out_crypto_blkdev->c_str(), 1s) < 0) {
184*f40fafd4SAndroid Build Coastguard Worker // WaitForFile generates a suitable log message
185*f40fafd4SAndroid Build Coastguard Worker return -1;
186*f40fafd4SAndroid Build Coastguard Worker }
187*f40fafd4SAndroid Build Coastguard Worker return 0;
188*f40fafd4SAndroid Build Coastguard Worker }
189