blob: ab8f3ec18520e95f3c11af89f1d2ef5ba176adc2 [file] [log] [blame]
Ken Sumrall8f869aa2010-12-03 03:47:09 -08001/*
2 * Copyright (C) 2010 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 Biggers0803ba02021-11-08 16:45:58 -080017//
18// This file contains the implementation of the dm-crypt volume metadata
19// encryption method, which is deprecated. Devices that launched with Android
20// 11 or higher use a different method instead. For details, see
21// https://source.android.com/security/encryption/metadata#configuration-on-adoptable-storage
22//
23
Logan Chiend557d762018-05-02 11:36:45 +080024#define LOG_TAG "Cryptfs"
25
26#include "cryptfs.h"
27
Paul Crowley220567c2020-02-07 12:45:20 -080028#include "CryptoType.h"
Paul Crowleycfe39722018-10-30 15:59:24 -070029#include "Utils.h"
Logan Chiend557d762018-05-02 11:36:45 +080030
Eric Biggersed45ec32019-01-25 10:47:55 -080031#include <android-base/parseint.h>
Logan Chien3f2b1222018-05-02 11:39:03 +080032#include <android-base/properties.h>
Logan Chien3f2b1222018-05-02 11:39:03 +080033#include <cutils/properties.h>
David Andersonb9224732019-05-13 13:02:54 -070034#include <libdm/dm.h>
Logan Chien188b0ab2018-04-23 13:37:39 +080035#include <log/log.h>
Logan Chiend557d762018-05-02 11:36:45 +080036
Martijn Coenen26ad7b32020-02-13 16:20:52 +010037#include <chrono>
Mark Salyzyn3e971272014-01-21 13:27:04 -080038
Eric Biggersed45ec32019-01-25 10:47:55 -080039using android::base::ParseUint;
Paul Crowley220567c2020-02-07 12:45:20 -080040using android::vold::CryptoType;
Paul Crowley3d98f5d2020-02-07 11:49:09 -080041using android::vold::KeyBuffer;
Paul Crowleyb3d018a2020-02-12 11:04:05 -080042using android::vold::KeyGeneration;
David Andersonb9224732019-05-13 13:02:54 -070043using namespace android::dm;
Eric Biggers0803ba02021-11-08 16:45:58 -080044using namespace android::vold;
Paul Crowleycfe39722018-10-30 15:59:24 -070045using namespace std::chrono_literals;
46
Paul Crowley73be12d2020-02-03 12:22:03 -080047#define MAX_KEY_LEN 48
Ken Sumrall29d8da82011-05-18 17:20:07 -070048
Ken Sumralle919efe2012-09-29 17:07:41 -070049#define TABLE_LOAD_RETRIES 10
50
Paul Crowley220567c2020-02-07 12:45:20 -080051constexpr CryptoType aes_128_cbc = CryptoType()
52 .set_config_name("AES-128-CBC")
53 .set_kernel_name("aes-cbc-essiv:sha256")
54 .set_keysize(16);
55
56constexpr CryptoType supported_crypto_types[] = {aes_128_cbc, android::vold::adiantum};
57
58static_assert(validateSupportedCryptoTypes(MAX_KEY_LEN, supported_crypto_types,
59 array_length(supported_crypto_types)),
60 "We have a CryptoType with keysize > MAX_KEY_LEN or which was "
61 "incompletely constructed.");
62
63static const CryptoType& get_crypto_type() {
64 // We only want to parse this read-only property once. But we need to wait
65 // until the system is initialized before we can read it. So we use a static
66 // scoped within this function to get it only once.
67 static CryptoType crypto_type =
68 lookup_crypto_algorithm(supported_crypto_types, array_length(supported_crypto_types),
69 aes_128_cbc, "ro.crypto.fde_algorithm");
70 return crypto_type;
71}
72
Paul Crowleyb3d018a2020-02-12 11:04:05 -080073const KeyGeneration cryptfs_get_keygen() {
Paul Crowley249c2fb2020-02-07 12:51:56 -080074 return KeyGeneration{get_crypto_type().get_keysize(), true, false};
Paul Crowleyb3d018a2020-02-12 11:04:05 -080075}
76
Ken Sumrall8f869aa2010-12-03 03:47:09 -080077/* Convert a binary key of specified length into an ascii hex string equivalent,
78 * without the leading 0x and with null termination
79 */
Eric Biggers0803ba02021-11-08 16:45:58 -080080static void convert_key_to_hex_ascii(const KeyBuffer& key, char* key_ascii) {
Paul Lawrence3bd36d52015-06-09 13:37:44 -070081 unsigned int i, a;
82 unsigned char nibble;
Ken Sumrall8f869aa2010-12-03 03:47:09 -080083
Eric Biggers0803ba02021-11-08 16:45:58 -080084 for (i = 0, a = 0; i < key.size(); i++, a += 2) {
Paul Lawrence3bd36d52015-06-09 13:37:44 -070085 /* For each byte, write out two ascii hex digits */
Eric Biggers0803ba02021-11-08 16:45:58 -080086 nibble = (key[i] >> 4) & 0xf;
87 key_ascii[a] = nibble + (nibble > 9 ? 0x37 : 0x30);
Ken Sumrall8f869aa2010-12-03 03:47:09 -080088
Eric Biggers0803ba02021-11-08 16:45:58 -080089 nibble = key[i] & 0xf;
90 key_ascii[a + 1] = nibble + (nibble > 9 ? 0x37 : 0x30);
Paul Lawrence3bd36d52015-06-09 13:37:44 -070091 }
Ken Sumrall8f869aa2010-12-03 03:47:09 -080092
Paul Lawrence3bd36d52015-06-09 13:37:44 -070093 /* Add the null termination */
Eric Biggers0803ba02021-11-08 16:45:58 -080094 key_ascii[a] = '\0';
Ken Sumrall8f869aa2010-12-03 03:47:09 -080095}
96
Eric Biggersed45ec32019-01-25 10:47:55 -080097/*
98 * If the ro.crypto.fde_sector_size system property is set, append the
99 * parameters to make dm-crypt use the specified crypto sector size and round
100 * the crypto device size down to a crypto sector boundary.
101 */
Eric Biggers0803ba02021-11-08 16:45:58 -0800102static int add_sector_size_param(DmTargetCrypt* target, uint64_t* nr_sec) {
Greg Kaiserab1e84a2018-12-11 12:40:51 -0800103 constexpr char DM_CRYPT_SECTOR_SIZE[] = "ro.crypto.fde_sector_size";
Eric Biggersed45ec32019-01-25 10:47:55 -0800104 char value[PROPERTY_VALUE_MAX];
Greg Kaiserab1e84a2018-12-11 12:40:51 -0800105
Eric Biggersed45ec32019-01-25 10:47:55 -0800106 if (property_get(DM_CRYPT_SECTOR_SIZE, value, "") > 0) {
107 unsigned int sector_size;
108
109 if (!ParseUint(value, &sector_size) || sector_size < 512 || sector_size > 4096 ||
110 (sector_size & (sector_size - 1)) != 0) {
111 SLOGE("Invalid value for %s: %s. Must be >= 512, <= 4096, and a power of 2\n",
112 DM_CRYPT_SECTOR_SIZE, value);
113 return -1;
114 }
115
David Andersonb9224732019-05-13 13:02:54 -0700116 target->SetSectorSize(sector_size);
Greg Kaiserab1e84a2018-12-11 12:40:51 -0800117
118 // With this option, IVs will match the sector numbering, instead
119 // of being hard-coded to being based on 512-byte sectors.
David Andersonb9224732019-05-13 13:02:54 -0700120 target->SetIvLargeSectors();
Eric Biggersed45ec32019-01-25 10:47:55 -0800121
122 // Round the crypto device size down to a crypto sector boundary.
Eric Biggers0803ba02021-11-08 16:45:58 -0800123 *nr_sec &= ~((sector_size / 512) - 1);
Greg Kaiserab1e84a2018-12-11 12:40:51 -0800124 }
Eric Biggersed45ec32019-01-25 10:47:55 -0800125 return 0;
Greg Kaiserab1e84a2018-12-11 12:40:51 -0800126}
127
Ken Sumrall29d8da82011-05-18 17:20:07 -0700128/*
Jeff Sharkey9c484982015-03-31 10:35:33 -0700129 * Called by vold when it's asked to mount an encrypted external
130 * storage volume. The incoming partition has no crypto header/footer,
Greg Kaiser57f9af62018-02-16 13:13:58 -0800131 * as any metadata is been stored in a separate, small partition. We
132 * assume it must be using our same crypt type and keysize.
Ken Sumrall29d8da82011-05-18 17:20:07 -0700133 */
Paul Crowley3d98f5d2020-02-07 11:49:09 -0800134int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const KeyBuffer& key,
Paul Crowley81796e92020-02-07 11:27:49 -0800135 std::string* out_crypto_blkdev) {
Paul Crowley220567c2020-02-07 12:45:20 -0800136 auto crypto_type = get_crypto_type();
137 if (key.size() != crypto_type.get_keysize()) {
Paul Crowleya661fb62020-02-11 16:21:54 -0800138 SLOGE("Raw keysize %zu does not match crypt keysize %zu", key.size(),
Paul Crowley220567c2020-02-07 12:45:20 -0800139 crypto_type.get_keysize());
Paul Crowley3d98f5d2020-02-07 11:49:09 -0800140 return -1;
141 }
Oleksiy Avramchenko625dc782018-05-23 10:50:46 +0200142 uint64_t nr_sec = 0;
143 if (android::vold::GetBlockDev512Sectors(real_blkdev, &nr_sec) != android::OK) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700144 SLOGE("Failed to get size of %s: %s", real_blkdev, strerror(errno));
Ken Sumrall29d8da82011-05-18 17:20:07 -0700145 return -1;
146 }
147
Eric Biggers0803ba02021-11-08 16:45:58 -0800148 auto& dm = DeviceMapper::Instance();
149
150 // We need two ASCII characters to represent each byte, and need space for
151 // the '\0' terminator.
152 char key_ascii[MAX_KEY_LEN * 2 + 1];
153 convert_key_to_hex_ascii(key, key_ascii);
154
155 auto target = std::make_unique<DmTargetCrypt>(0, nr_sec, crypto_type.get_kernel_name(),
156 key_ascii, 0, real_blkdev, 0);
157 target->AllowDiscards();
158
Eric Biggersa701c452018-10-23 13:06:55 -0700159 if (fscrypt_is_native() &&
Eric Biggers0803ba02021-11-08 16:45:58 -0800160 android::base::GetBoolProperty("ro.crypto.allow_encrypt_override", false)) {
161 target->AllowEncryptOverride();
162 }
163 if (add_sector_size_param(target.get(), &nr_sec)) {
164 SLOGE("Error processing dm-crypt sector size param\n");
Paul Lawrencef4faa572014-01-29 13:31:03 -0800165 return -1;
166 }
167
Eric Biggers0803ba02021-11-08 16:45:58 -0800168 DmTable table;
169 table.AddTarget(std::move(target));
170
171 int load_count = 1;
172 while (load_count < TABLE_LOAD_RETRIES) {
173 if (dm.CreateDevice(label, table)) {
174 break;
175 }
176 load_count++;
177 }
178
179 if (load_count >= TABLE_LOAD_RETRIES) {
180 SLOGE("Cannot load dm-crypt mapping table.\n");
181 return -1;
182 }
183 if (load_count > 1) {
184 SLOGI("Took %d tries to load dmcrypt table.\n", load_count);
185 }
186
187 if (!dm.GetDmDevicePathByName(label, out_crypto_blkdev)) {
188 SLOGE("Cannot determine dm-crypt path for %s.\n", label);
Paul Lawrencef4faa572014-01-29 13:31:03 -0800189 return -1;
190 }
191
Eric Biggers0803ba02021-11-08 16:45:58 -0800192 /* Ensure the dm device has been created before returning. */
193 if (android::vold::WaitForFile(out_crypto_blkdev->c_str(), 1s) < 0) {
194 // WaitForFile generates a suitable log message
195 return -1;
196 }
Paul Lawrencef4faa572014-01-29 13:31:03 -0800197 return 0;
198}