1 /*
2 * Copyright (C) 2020 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 //
18 // Test that metadata encryption is working, via:
19 //
20 // - Correctness tests. These test the standard metadata encryption formats
21 // supported by Android R and higher via dm-default-key v2.
22 //
23 // - Randomness test. This runs on all devices that use metadata encryption.
24 //
25 // The correctness tests create a temporary default-key mapping over the raw
26 // userdata partition, read from it, and verify that the data got decrypted
27 // correctly. This only tests decryption, since this avoids having to find a
28 // region on disk that can safely be modified. This should be good enough since
29 // the device wouldn't work anyway if decryption didn't invert encryption.
30 //
31 // Note that this temporary default-key mapping will overlap the device's "real"
32 // default-key mapping, if the device has one. The kernel allows this. The
33 // tests don't use a loopback device instead, since dm-default-key over a
34 // loopback device can't use the real inline encryption hardware.
35 //
36 // The correctness tests cover the following settings:
37 //
38 // metadata_encryption=aes-256-xts
39 // metadata_encryption=adiantum
40 // metadata_encryption=aes-256-xts:wrappedkey_v0
41 //
42 // The tests don't check which one of those settings, if any, the device is
43 // actually using; they just try to test everything they can.
44 //
45 // These tests don't specifically test that file contents aren't encrypted
46 // twice. That's already implied by the file-based encryption test cases,
47 // provided that the device actually has metadata encryption enabled.
48 //
49
50 #include <android-base/file.h>
51 #include <android-base/stringprintf.h>
52 #include <android-base/unique_fd.h>
53 #include <asm/byteorder.h>
54 #include <fcntl.h>
55 #include <fstab/fstab.h>
56 #include <gtest/gtest.h>
57 #include <libdm/dm.h>
58 #include <linux/types.h>
59 #include <stdlib.h>
60 #include <unistd.h>
61
62 #include <chrono>
63
64 #include "vts_kernel_encryption.h"
65
66 using namespace android::dm;
67
68 namespace android {
69 namespace kernel {
70
71 #define cpu_to_le64 __cpu_to_le64
72 #define le64_to_cpu __le64_to_cpu
73
74 // Alignment to use for direct I/O reads of block devices
75 static constexpr int kDirectIOAlignment = 4096;
76
77 // Checks whether the kernel supports version 2 or higher of dm-default-key.
IsDmDefaultKeyV2Supported(DeviceMapper & dm)78 static bool IsDmDefaultKeyV2Supported(DeviceMapper &dm) {
79 DmTargetTypeInfo info;
80 if (!dm.GetTargetByName("default-key", &info)) {
81 GTEST_LOG_(INFO) << "dm-default-key not enabled";
82 return false;
83 }
84 if (!info.IsAtLeast(2, 0, 0)) {
85 // The legacy version of dm-default-key (which was never supported by the
86 // Android common kernels) used a vendor-specific on-disk format, so it's
87 // not testable by a vendor-independent test.
88 GTEST_LOG_(INFO) << "Detected legacy dm-default-key";
89 return false;
90 }
91 return true;
92 }
93
94 // Reads |count| bytes from the beginning of |blk_device|, using direct I/O to
95 // avoid getting any stale cached data. Direct I/O requires using a hardware
96 // sector size aligned buffer.
ReadBlockDevice(const std::string & blk_device,size_t count,std::vector<uint8_t> * data)97 static bool ReadBlockDevice(const std::string &blk_device, size_t count,
98 std::vector<uint8_t> *data) {
99 GTEST_LOG_(INFO) << "Reading " << count << " bytes from " << blk_device;
100 std::unique_ptr<void, void (*)(void *)> buf_mem(
101 aligned_alloc(kDirectIOAlignment, count), free);
102 if (buf_mem == nullptr) {
103 ADD_FAILURE() << "out of memory";
104 return false;
105 }
106 uint8_t *buffer = static_cast<uint8_t *>(buf_mem.get());
107
108 android::base::unique_fd fd(
109 open(blk_device.c_str(), O_RDONLY | O_DIRECT | O_CLOEXEC));
110 if (fd < 0) {
111 ADD_FAILURE() << "Failed to open " << blk_device << Errno();
112 return false;
113 }
114 if (!android::base::ReadFully(fd, buffer, count)) {
115 ADD_FAILURE() << "Failed to read from " << blk_device << Errno();
116 return false;
117 }
118
119 *data = std::vector<uint8_t>(buffer, buffer + count);
120 return true;
121 }
122
123 class DmDefaultKeyTest : public ::testing::Test {
124 // Filesystem whose underlying partition the test will use
125 static constexpr const char *kTestMountpoint = "/data";
126
127 // Size of the dm-default-key crypto sector size (data unit size) in bytes
128 static constexpr int kCryptoSectorSize = 4096;
129
130 // Size of the test data in crypto sectors
131 static constexpr int kTestDataSectors = 256;
132
133 // Size of the test data in bytes
134 static constexpr int kTestDataBytes = kTestDataSectors * kCryptoSectorSize;
135
136 // Device-mapper API sector size in bytes.
137 // This is unrelated to the crypto sector size.
138 static constexpr int kDmApiSectorSize = 512;
139
140 protected:
141 void SetUp() override;
142 void TearDown() override;
143 bool CreateTestDevice(const std::string &cipher,
144 const std::vector<uint8_t> &key, bool is_wrapped_key);
145 void VerifyDecryption(const std::vector<uint8_t> &key, const Cipher &cipher);
146 void DoTest(const std::string &cipher_string, const Cipher &cipher);
147 std::string test_dm_device_name_;
148 bool skip_test_ = false;
149 DeviceMapper *dm_ = nullptr;
150 std::string raw_blk_device_;
151 std::string dm_device_path_;
152 };
153
154 // Test setup procedure. Checks for the needed kernel support, finds the raw
155 // partition to use, and does other preparations. skip_test_ is set to true if
156 // the test should be skipped.
SetUp()157 void DmDefaultKeyTest::SetUp() {
158 dm_ = &DeviceMapper::Instance();
159
160 if (!IsDmDefaultKeyV2Supported(*dm_)) {
161 int first_api_level;
162 ASSERT_TRUE(GetFirstApiLevel(&first_api_level));
163 // Devices launching with R or higher must support dm-default-key v2.
164 ASSERT_LE(first_api_level, __ANDROID_API_Q__);
165 GTEST_LOG_(INFO)
166 << "Skipping test because dm-default-key v2 is unsupported";
167 skip_test_ = true;
168 return;
169 }
170 test_dm_device_name_ =
171 android::base::StringPrintf("DmDefaultKeyTest.%d", getpid());
172
173 FilesystemInfo fs_info;
174 ASSERT_TRUE(GetFilesystemInfo(kTestMountpoint, &fs_info));
175 raw_blk_device_ = fs_info.disk_map[0].raw_blk_device;
176
177 dm_->DeleteDevice(test_dm_device_name_.c_str());
178 }
179
TearDown()180 void DmDefaultKeyTest::TearDown() { dm_->DeleteDevice(test_dm_device_name_); }
181
182 // Creates the test dm-default-key mapping using the given key and settings.
183 // If the dm device creation fails, then it is assumed the kernel doesn't
184 // support the given encryption settings, and a failure is not added.
CreateTestDevice(const std::string & cipher,const std::vector<uint8_t> & key,bool is_wrapped_key)185 bool DmDefaultKeyTest::CreateTestDevice(const std::string &cipher,
186 const std::vector<uint8_t> &key,
187 bool is_wrapped_key) {
188 static_assert(kTestDataBytes % kDmApiSectorSize == 0);
189 std::unique_ptr<DmTargetDefaultKey> target =
190 std::make_unique<DmTargetDefaultKey>(0, kTestDataBytes / kDmApiSectorSize,
191 cipher.c_str(), BytesToHex(key),
192 raw_blk_device_, 0);
193 target->SetSetDun();
194 if (is_wrapped_key) target->SetWrappedKeyV0();
195
196 DmTable table;
197 if (!table.AddTarget(std::move(target))) {
198 ADD_FAILURE() << "Failed to add default-key target to table";
199 return false;
200 }
201 if (!table.valid()) {
202 ADD_FAILURE() << "Device-mapper table failed to validate";
203 return false;
204 }
205 if (!dm_->CreateDevice(test_dm_device_name_, table, &dm_device_path_,
206 std::chrono::seconds(5))) {
207 GTEST_LOG_(INFO) << "Unable to create default-key mapping" << Errno()
208 << ". Assuming that the encryption settings cipher=\""
209 << cipher << "\", is_wrapped_key=" << is_wrapped_key
210 << " are unsupported and skipping the test.";
211 return false;
212 }
213 GTEST_LOG_(INFO) << "Created default-key mapping at " << dm_device_path_
214 << " using cipher=\"" << cipher
215 << "\", key=" << BytesToHex(key)
216 << ", is_wrapped_key=" << is_wrapped_key;
217 return true;
218 }
219
VerifyDecryption(const std::vector<uint8_t> & key,const Cipher & cipher)220 void DmDefaultKeyTest::VerifyDecryption(const std::vector<uint8_t> &key,
221 const Cipher &cipher) {
222 std::vector<uint8_t> raw_data;
223 std::vector<uint8_t> decrypted_data;
224
225 ASSERT_TRUE(ReadBlockDevice(raw_blk_device_, kTestDataBytes, &raw_data));
226 ASSERT_TRUE(
227 ReadBlockDevice(dm_device_path_, kTestDataBytes, &decrypted_data));
228
229 // Verify that the decrypted data encrypts to the raw data.
230
231 GTEST_LOG_(INFO) << "Verifying correctness of decrypted data";
232
233 // Initialize the IV for crypto sector 0.
234 ASSERT_GE(cipher.ivsize(), sizeof(__le64));
235 std::unique_ptr<__le64> iv(new (::operator new(cipher.ivsize())) __le64);
236 memset(iv.get(), 0, cipher.ivsize());
237
238 // Encrypt each sector.
239 std::vector<uint8_t> encrypted_data(kTestDataBytes);
240 static_assert(kTestDataBytes % kCryptoSectorSize == 0);
241 for (size_t i = 0; i < kTestDataBytes; i += kCryptoSectorSize) {
242 ASSERT_TRUE(cipher.Encrypt(key, reinterpret_cast<const uint8_t *>(iv.get()),
243 &decrypted_data[i], &encrypted_data[i],
244 kCryptoSectorSize));
245
246 // Update the IV by incrementing the crypto sector number.
247 *iv = cpu_to_le64(le64_to_cpu(*iv) + 1);
248 }
249
250 ASSERT_EQ(encrypted_data, raw_data);
251 }
252
DoTest(const std::string & cipher_string,const Cipher & cipher)253 void DmDefaultKeyTest::DoTest(const std::string &cipher_string,
254 const Cipher &cipher) {
255 if (skip_test_) return;
256
257 std::vector<uint8_t> key = GenerateTestKey(cipher.keysize());
258
259 if (!CreateTestDevice(cipher_string, key, false)) return;
260
261 VerifyDecryption(key, cipher);
262 }
263
264 // Tests dm-default-key parameters matching metadata_encryption=aes-256-xts.
TEST_F(DmDefaultKeyTest,TestAes256Xts)265 TEST_F(DmDefaultKeyTest, TestAes256Xts) {
266 DoTest("aes-xts-plain64", Aes256XtsCipher());
267 }
268
269 // Tests dm-default-key parameters matching metadata_encryption=adiantum.
TEST_F(DmDefaultKeyTest,TestAdiantum)270 TEST_F(DmDefaultKeyTest, TestAdiantum) {
271 DoTest("xchacha12,aes-adiantum-plain64", AdiantumCipher());
272 }
273
274 // Tests dm-default-key parameters matching
275 // metadata_encryption=aes-256-xts:wrappedkey_v0.
TEST_F(DmDefaultKeyTest,TestHwWrappedKey)276 TEST_F(DmDefaultKeyTest, TestHwWrappedKey) {
277 if (skip_test_) return;
278
279 std::vector<uint8_t> master_key, exported_key;
280 if (!CreateHwWrappedKey(&master_key, &exported_key)) return;
281
282 if (!CreateTestDevice("aes-xts-plain64", exported_key, true)) return;
283
284 std::vector<uint8_t> enc_key;
285 ASSERT_TRUE(DeriveHwWrappedEncryptionKey(master_key, &enc_key));
286
287 VerifyDecryption(enc_key, Aes256XtsCipher());
288 }
289
290 // Tests that if the device uses metadata encryption, then the first filesystem
291 // block of the userdata partition appears random. For ext4 and f2fs, this
292 // block should contain the filesystem superblock; it therefore should be
293 // initialized and metadata-encrypted. Ideally we'd check additional blocks
294 // too, but that would require awareness of the filesystem structure.
295 //
296 // This isn't as strong a test as the correctness tests, but it's useful because
297 // it applies regardless of the encryption format and key. Thus it runs even on
298 // old devices, including ones that used a vendor-specific encryption format.
TEST(MetadataEncryptionTest,TestRandomness)299 TEST(MetadataEncryptionTest, TestRandomness) {
300 constexpr const char *mountpoint = "/data";
301
302 android::fs_mgr::Fstab fstab;
303 ASSERT_TRUE(android::fs_mgr::ReadDefaultFstab(&fstab));
304 const fs_mgr::FstabEntry *entry = GetEntryForMountPoint(&fstab, mountpoint);
305 ASSERT_TRUE(entry != nullptr);
306
307 if (entry->metadata_key_dir.empty()) {
308 int first_api_level;
309 ASSERT_TRUE(GetFirstApiLevel(&first_api_level));
310 ASSERT_LE(first_api_level, __ANDROID_API_Q__)
311 << "Metadata encryption is required";
312 GTEST_LOG_(INFO)
313 << "Skipping test because device doesn't use metadata encryption";
314 return;
315 }
316
317 GTEST_LOG_(INFO) << "Verifying randomness of ciphertext";
318 std::vector<uint8_t> raw_data;
319 FilesystemInfo fs_info;
320 ASSERT_TRUE(GetFilesystemInfo(mountpoint, &fs_info));
321 // The first block of the filesystem's main block device should always be
322 // metadata-encrypted.
323 ASSERT_TRUE(ReadBlockDevice(fs_info.disk_map[0].raw_blk_device,
324 fs_info.block_size, &raw_data));
325 ASSERT_TRUE(VerifyDataRandomness(raw_data));
326 }
327
328 } // namespace kernel
329 } // namespace android
330