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 file contents encryption is working, via:
19 //
20 // - Correctness tests. These test the standard FBE settings supported by
21 // Android R and higher.
22 //
23 // - Randomness test. This runs on all devices that use FBE, even old ones.
24 //
25 // The correctness tests cover the following settings:
26 //
27 // fileencryption=aes-256-xts:aes-256-cts:v2
28 // fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized
29 // fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized+wrappedkey_v0
30 // fileencryption=aes-256-xts:aes-256-cts:v2+emmc_optimized
31 // fileencryption=aes-256-xts:aes-256-cts:v2+emmc_optimized+wrappedkey_v0
32 // fileencryption=adiantum:adiantum:v2
33 //
34 // On devices launching with R or higher those are equivalent to simply:
35 //
36 // fileencryption=
37 // fileencryption=::inlinecrypt_optimized
38 // fileencryption=::inlinecrypt_optimized+wrappedkey_v0
39 // fileencryption=::emmc_optimized
40 // fileencryption=::emmc_optimized+wrappedkey_v0
41 // fileencryption=adiantum
42 //
43 // The tests don't check which one of those settings, if any, the device is
44 // actually using; they just try to test everything they can.
45 // "fileencryption=aes-256-xts" is guaranteed to be available if the kernel
46 // supports any "fscrypt v2" features at all. The others may not be available,
47 // so the tests take that into account and skip testing them when unavailable.
48 //
49 // None of these tests should ever fail. In particular, vendors must not break
50 // any standard FBE settings, regardless of what the device actually uses. If
51 // any test fails, make sure to check things like the byte order of keys.
52 //
53
54 #include <android-base/file.h>
55 #include <android-base/properties.h>
56 #include <android-base/stringprintf.h>
57 #include <android-base/unique_fd.h>
58 #include <asm/byteorder.h>
59 #include <errno.h>
60 #include <fcntl.h>
61 #include <gtest/gtest.h>
62 #include <limits.h>
63 #include <linux/fiemap.h>
64 #include <linux/fs.h>
65 #include <linux/fscrypt.h>
66 #include <openssl/evp.h>
67 #include <openssl/hkdf.h>
68 #include <openssl/siphash.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <sys/ioctl.h>
72 #include <unistd.h>
73
74 #include "vts_kernel_encryption.h"
75
76 #ifndef F2FS_IOCTL_MAGIC
77 #define F2FS_IOCTL_MAGIC 0xf5
78 #endif
79 #ifndef F2FS_IOC_SET_PIN_FILE
80 #define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32)
81 #endif
82
83 namespace android {
84 namespace kernel {
85
86 // Assumed size of filesystem blocks, in bytes
87 constexpr int kFilesystemBlockSize = 4096;
88
89 // Size of the test file in filesystem blocks
90 constexpr int kTestFileBlocks = 256;
91
92 // Size of the test file in bytes
93 constexpr int kTestFileBytes = kFilesystemBlockSize * kTestFileBlocks;
94
95 // fscrypt master key size in bytes
96 constexpr int kFscryptMasterKeySize = 64;
97
98 // fscrypt maximum IV size in bytes
99 constexpr int kFscryptMaxIVSize = 32;
100
101 // fscrypt per-file nonce size in bytes
102 constexpr int kFscryptFileNonceSize = 16;
103
104 // fscrypt HKDF context bytes, from kernel fs/crypto/fscrypt_private.h
105 enum FscryptHkdfContext {
106 HKDF_CONTEXT_KEY_IDENTIFIER = 1,
107 HKDF_CONTEXT_PER_FILE_ENC_KEY = 2,
108 HKDF_CONTEXT_DIRECT_KEY = 3,
109 HKDF_CONTEXT_IV_INO_LBLK_64_KEY = 4,
110 HKDF_CONTEXT_DIRHASH_KEY = 5,
111 HKDF_CONTEXT_IV_INO_LBLK_32_KEY = 6,
112 HKDF_CONTEXT_INODE_HASH_KEY = 7,
113 };
114
115 struct FscryptFileNonce {
116 uint8_t bytes[kFscryptFileNonceSize];
117 };
118
119 // Format of the initialization vector
120 union FscryptIV {
121 struct {
122 __le32 lblk_num; // file logical block number, starts at 0
123 __le32 inode_number; // only used for IV_INO_LBLK_64
124 uint8_t file_nonce[kFscryptFileNonceSize]; // only used for DIRECT_KEY
125 };
126 uint8_t bytes[kFscryptMaxIVSize];
127 };
128
129 struct TestFileInfo {
130 std::vector<uint8_t> plaintext;
131 std::vector<uint8_t> actual_ciphertext;
132 uint64_t inode_number;
133 FscryptFileNonce nonce;
134 };
135
GetInodeNumber(const std::string & path,uint64_t * inode_number)136 static bool GetInodeNumber(const std::string &path, uint64_t *inode_number) {
137 struct stat stbuf;
138 if (stat(path.c_str(), &stbuf) != 0) {
139 ADD_FAILURE() << "Failed to stat " << path << Errno();
140 return false;
141 }
142 *inode_number = stbuf.st_ino;
143 return true;
144 }
145
146 //
147 // Checks whether the kernel has support for the following fscrypt features:
148 //
149 // - Filesystem-level keyring (FS_IOC_ADD_ENCRYPTION_KEY and
150 // FS_IOC_REMOVE_ENCRYPTION_KEY)
151 // - v2 encryption policies
152 // - The IV_INO_LBLK_64 encryption policy flag
153 // - The FS_IOC_GET_ENCRYPTION_NONCE ioctl
154 // - The IV_INO_LBLK_32 encryption policy flag
155 //
156 // To do this it's sufficient to just check whether FS_IOC_ADD_ENCRYPTION_KEY is
157 // available, as the other features were added in the same AOSP release.
158 //
159 // The easiest way to do this is to just execute the ioctl with a NULL argument.
160 // If available it will fail with EFAULT; otherwise it will fail with ENOTTY (or
161 // EOPNOTSUPP if encryption isn't enabled on the filesystem; that happens on old
162 // devices that aren't using FBE and are upgraded to a new kernel).
163 //
IsFscryptV2Supported(const std::string & mountpoint)164 static bool IsFscryptV2Supported(const std::string &mountpoint) {
165 android::base::unique_fd fd(
166 open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
167 if (fd < 0) {
168 ADD_FAILURE() << "Failed to open " << mountpoint << Errno();
169 return false;
170 }
171
172 if (ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, nullptr) == 0) {
173 ADD_FAILURE()
174 << "FS_IOC_ADD_ENCRYPTION_KEY(nullptr) unexpectedly succeeded on "
175 << mountpoint;
176 return false;
177 }
178 switch (errno) {
179 case EFAULT:
180 return true;
181 case EOPNOTSUPP:
182 case ENOTTY:
183 GTEST_LOG_(INFO) << "No support for FS_IOC_ADD_ENCRYPTION_KEY on "
184 << mountpoint;
185 return false;
186 default:
187 ADD_FAILURE()
188 << "Unexpected error from FS_IOC_ADD_ENCRYPTION_KEY(nullptr) on "
189 << mountpoint << Errno();
190 return false;
191 }
192 }
193
194 // Helper class to pin / unpin a file on f2fs, to prevent f2fs from moving the
195 // file's blocks while the test is accessing them via the underlying device.
196 //
197 // This can be used without checking the filesystem type, since on other
198 // filesystem types F2FS_IOC_SET_PIN_FILE will just fail and do nothing.
199 class ScopedF2fsFilePinning {
200 public:
ScopedF2fsFilePinning(int fd)201 explicit ScopedF2fsFilePinning(int fd) : fd_(fd) {
202 __u32 set = 1;
203 ioctl(fd_, F2FS_IOC_SET_PIN_FILE, &set);
204 }
205
~ScopedF2fsFilePinning()206 ~ScopedF2fsFilePinning() {
207 __u32 set = 0;
208 ioctl(fd_, F2FS_IOC_SET_PIN_FILE, &set);
209 }
210
211 private:
212 int fd_;
213 };
214
215 // Reads the raw data of the file specified by |fd| from its underlying block
216 // device |blk_device|. The file has |expected_data_size| bytes of initialized
217 // data; this must be a multiple of the filesystem block size
218 // kFilesystemBlockSize. The file may contain holes, in which case only the
219 // non-holes are read; the holes are not counted in |expected_data_size|.
ReadRawDataOfFile(int fd,const std::string & blk_device,int expected_data_size,std::vector<uint8_t> * raw_data)220 static bool ReadRawDataOfFile(int fd, const std::string &blk_device,
221 int expected_data_size,
222 std::vector<uint8_t> *raw_data) {
223 int max_extents = expected_data_size / kFilesystemBlockSize;
224
225 EXPECT_TRUE(expected_data_size % kFilesystemBlockSize == 0);
226
227 // It's not entirely clear how F2FS_IOC_SET_PIN_FILE interacts with dirty
228 // data, so do an extra sync here and don't just rely on FIEMAP_FLAG_SYNC.
229 if (fsync(fd) != 0) {
230 ADD_FAILURE() << "Failed to sync file" << Errno();
231 return false;
232 }
233
234 ScopedF2fsFilePinning pinned_file(fd); // no-op on non-f2fs
235
236 // Query the file's extents.
237 size_t allocsize = offsetof(struct fiemap, fm_extents[max_extents]);
238 std::unique_ptr<struct fiemap> map(
239 new (::operator new(allocsize)) struct fiemap);
240 memset(map.get(), 0, allocsize);
241 map->fm_flags = FIEMAP_FLAG_SYNC;
242 map->fm_length = UINT64_MAX;
243 map->fm_extent_count = max_extents;
244 if (ioctl(fd, FS_IOC_FIEMAP, map.get()) != 0) {
245 ADD_FAILURE() << "Failed to get extents of file" << Errno();
246 return false;
247 }
248
249 // Read the raw data, using direct I/O to avoid getting any stale cached data.
250 // Direct I/O requires using a block size aligned buffer.
251
252 std::unique_ptr<void, void (*)(void *)> buf_mem(
253 aligned_alloc(kFilesystemBlockSize, expected_data_size), free);
254 if (buf_mem == nullptr) {
255 ADD_FAILURE() << "Out of memory";
256 return false;
257 }
258 uint8_t *buf = static_cast<uint8_t *>(buf_mem.get());
259 int offset = 0;
260
261 android::base::unique_fd blk_fd(
262 open(blk_device.c_str(), O_RDONLY | O_DIRECT | O_CLOEXEC));
263 if (blk_fd < 0) {
264 ADD_FAILURE() << "Failed to open raw block device " << blk_device
265 << Errno();
266 return false;
267 }
268
269 for (int i = 0; i < map->fm_mapped_extents; i++) {
270 const struct fiemap_extent &extent = map->fm_extents[i];
271
272 GTEST_LOG_(INFO) << "Extent " << i + 1 << " of " << map->fm_mapped_extents
273 << " is logical offset " << extent.fe_logical
274 << ", physical offset " << extent.fe_physical
275 << ", length " << extent.fe_length << ", flags 0x"
276 << std::hex << extent.fe_flags << std::dec;
277 // Make sure the flags indicate that fe_physical is actually valid.
278 if (extent.fe_flags & (FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_UNWRITTEN)) {
279 ADD_FAILURE() << "Unsupported extent flags: 0x" << std::hex
280 << extent.fe_flags << std::dec;
281 return false;
282 }
283 if (extent.fe_length % kFilesystemBlockSize != 0) {
284 ADD_FAILURE() << "Extent is not aligned to filesystem block size";
285 return false;
286 }
287 if (extent.fe_length > expected_data_size - offset) {
288 ADD_FAILURE() << "File is longer than expected";
289 return false;
290 }
291 if (pread(blk_fd, &buf[offset], extent.fe_length, extent.fe_physical) !=
292 extent.fe_length) {
293 ADD_FAILURE() << "Error reading raw data from block device" << Errno();
294 return false;
295 }
296 offset += extent.fe_length;
297 }
298 if (offset != expected_data_size) {
299 ADD_FAILURE() << "File is shorter than expected";
300 return false;
301 }
302 *raw_data = std::vector<uint8_t>(&buf[0], &buf[offset]);
303 return true;
304 }
305
306 // Writes |plaintext| to a file |path| located on the block device |blk_device|.
307 // Returns in |ciphertext| the file's raw ciphertext read from |blk_device|.
WriteTestFile(const std::vector<uint8_t> & plaintext,const std::string & path,const std::string & blk_device,std::vector<uint8_t> * ciphertext)308 static bool WriteTestFile(const std::vector<uint8_t> &plaintext,
309 const std::string &path,
310 const std::string &blk_device,
311 std::vector<uint8_t> *ciphertext) {
312 GTEST_LOG_(INFO) << "Creating test file " << path << " containing "
313 << plaintext.size() << " bytes of data";
314 android::base::unique_fd fd(
315 open(path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600));
316 if (fd < 0) {
317 ADD_FAILURE() << "Failed to create " << path << Errno();
318 return false;
319 }
320 if (!android::base::WriteFully(fd, plaintext.data(), plaintext.size())) {
321 ADD_FAILURE() << "Error writing to " << path << Errno();
322 return false;
323 }
324
325 GTEST_LOG_(INFO) << "Reading the raw ciphertext of " << path << " from disk";
326 if (!ReadRawDataOfFile(fd, blk_device, plaintext.size(), ciphertext)) {
327 ADD_FAILURE() << "Failed to read the raw ciphertext of " << path;
328 return false;
329 }
330 return true;
331 }
332
333 class FBEPolicyTest : public ::testing::Test {
334 protected:
335 // Location of the test directory and file. Since it's not possible to
336 // override an existing encryption policy, in order for these tests to set
337 // their own encryption policy the parent directory must be unencrypted.
338 static constexpr const char *kTestMountpoint = "/data";
339 static constexpr const char *kTestDir = "/data/unencrypted/vts-test-dir";
340 static constexpr const char *kTestFile =
341 "/data/unencrypted/vts-test-dir/file";
342
343 void SetUp() override;
344 void TearDown() override;
345 bool SetMasterKey(const std::vector<uint8_t> &master_key, uint32_t flags = 0,
346 bool required = true);
347 bool CreateAndSetHwWrappedKey(std::vector<uint8_t> *enc_key,
348 std::vector<uint8_t> *sw_secret);
349 int GetSkipFlagsForInoBasedEncryption();
350 bool SetEncryptionPolicy(int contents_mode, int filenames_mode, int flags,
351 int skip_flags);
352 bool GenerateTestFile(TestFileInfo *info);
353 bool VerifyKeyIdentifier(const std::vector<uint8_t> &master_key);
354 bool DerivePerModeEncryptionKey(const std::vector<uint8_t> &master_key,
355 int mode, FscryptHkdfContext context,
356 std::vector<uint8_t> &enc_key);
357 bool DerivePerFileEncryptionKey(const std::vector<uint8_t> &master_key,
358 const FscryptFileNonce &nonce,
359 std::vector<uint8_t> &enc_key);
360 void VerifyCiphertext(const std::vector<uint8_t> &enc_key,
361 const FscryptIV &starting_iv, const Cipher &cipher,
362 const TestFileInfo &file_info);
363 void TestEmmcOptimizedDunWraparound(const std::vector<uint8_t> &master_key,
364 const std::vector<uint8_t> &enc_key);
365 struct fscrypt_key_specifier master_key_specifier_;
366 bool skip_test_ = false;
367 bool key_added_ = false;
368 FilesystemInfo fs_info_;
369 };
370
371 // Test setup procedure. Creates a test directory kTestDir and does other
372 // preparations. skip_test_ is set to true if the test should be skipped.
SetUp()373 void FBEPolicyTest::SetUp() {
374 if (!IsFscryptV2Supported(kTestMountpoint)) {
375 int first_api_level;
376 ASSERT_TRUE(GetFirstApiLevel(&first_api_level));
377 // Devices launching with R or higher must support fscrypt v2.
378 ASSERT_LE(first_api_level, __ANDROID_API_Q__);
379 GTEST_LOG_(INFO) << "Skipping test because fscrypt v2 is unsupported";
380 skip_test_ = true;
381 return;
382 }
383
384 ASSERT_TRUE(GetFilesystemInfo(kTestMountpoint, &fs_info_));
385
386 DeleteRecursively(kTestDir);
387 if (mkdir(kTestDir, 0700) != 0) {
388 FAIL() << "Failed to create " << kTestDir << Errno();
389 }
390 }
391
TearDown()392 void FBEPolicyTest::TearDown() {
393 DeleteRecursively(kTestDir);
394
395 // Remove the test key from kTestMountpoint.
396 if (key_added_) {
397 android::base::unique_fd mntfd(
398 open(kTestMountpoint, O_RDONLY | O_DIRECTORY | O_CLOEXEC));
399 if (mntfd < 0) {
400 FAIL() << "Failed to open " << kTestMountpoint << Errno();
401 }
402 struct fscrypt_remove_key_arg arg;
403 memset(&arg, 0, sizeof(arg));
404 arg.key_spec = master_key_specifier_;
405
406 if (ioctl(mntfd, FS_IOC_REMOVE_ENCRYPTION_KEY, &arg) != 0) {
407 FAIL() << "FS_IOC_REMOVE_ENCRYPTION_KEY failed on " << kTestMountpoint
408 << Errno();
409 }
410 }
411 }
412
413 // Adds |master_key| to kTestMountpoint and places the resulting key identifier
414 // in master_key_specifier_.
SetMasterKey(const std::vector<uint8_t> & master_key,uint32_t flags,bool required)415 bool FBEPolicyTest::SetMasterKey(const std::vector<uint8_t> &master_key,
416 uint32_t flags, bool required) {
417 size_t allocsize = sizeof(struct fscrypt_add_key_arg) + master_key.size();
418 std::unique_ptr<struct fscrypt_add_key_arg> arg(
419 new (::operator new(allocsize)) struct fscrypt_add_key_arg);
420 memset(arg.get(), 0, allocsize);
421 arg->key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
422 arg->__flags = flags;
423 arg->raw_size = master_key.size();
424 std::copy(master_key.begin(), master_key.end(), arg->raw);
425
426 GTEST_LOG_(INFO) << "Adding fscrypt master key, flags are 0x" << std::hex
427 << flags << std::dec << ", raw bytes are "
428 << BytesToHex(master_key);
429 android::base::unique_fd mntfd(
430 open(kTestMountpoint, O_RDONLY | O_DIRECTORY | O_CLOEXEC));
431 if (mntfd < 0) {
432 ADD_FAILURE() << "Failed to open " << kTestMountpoint << Errno();
433 return false;
434 }
435 if (ioctl(mntfd, FS_IOC_ADD_ENCRYPTION_KEY, arg.get()) != 0) {
436 if (required || (errno != EINVAL && errno != EOPNOTSUPP)) {
437 ADD_FAILURE() << "FS_IOC_ADD_ENCRYPTION_KEY failed on " << kTestMountpoint
438 << Errno();
439 }
440 return false;
441 }
442 master_key_specifier_ = arg->key_spec;
443 GTEST_LOG_(INFO) << "Master key identifier is "
444 << BytesToHex(master_key_specifier_.u.identifier);
445 key_added_ = true;
446 if (!(flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) &&
447 !VerifyKeyIdentifier(master_key))
448 return false;
449 return true;
450 }
451
452 // Creates a hardware-wrapped key, adds it to the filesystem, and derives the
453 // corresponding inline encryption key |enc_key| and software secret
454 // |sw_secret|. Returns false if unsuccessful (either the test failed, or the
455 // device doesn't support hardware-wrapped keys so the test should be skipped).
CreateAndSetHwWrappedKey(std::vector<uint8_t> * enc_key,std::vector<uint8_t> * sw_secret)456 bool FBEPolicyTest::CreateAndSetHwWrappedKey(std::vector<uint8_t> *enc_key,
457 std::vector<uint8_t> *sw_secret) {
458 std::vector<uint8_t> master_key, exported_key;
459 if (!CreateHwWrappedKey(&master_key, &exported_key)) return false;
460
461 if (!SetMasterKey(exported_key, __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED, false)) {
462 if (!HasFailure()) {
463 GTEST_LOG_(INFO) << "Skipping test because kernel doesn't support "
464 "hardware-wrapped keys";
465 }
466 return false;
467 }
468
469 if (!DeriveHwWrappedEncryptionKey(master_key, enc_key)) return false;
470 if (!DeriveHwWrappedRawSecret(master_key, sw_secret)) return false;
471
472 if (!VerifyKeyIdentifier(*sw_secret)) return false;
473
474 return true;
475 }
476
477 enum {
478 kSkipIfNoPolicySupport = 1 << 0,
479 kSkipIfNoCryptoAPISupport = 1 << 1,
480 kSkipIfNoHardwareSupport = 1 << 2,
481 };
482
483 // Returns 0 if encryption policies that include the inode number in the IVs
484 // (e.g. IV_INO_LBLK_64) are guaranteed to be settable on the test filesystem.
485 // Else returns kSkipIfNoPolicySupport.
486 //
487 // On f2fs, they're always settable. On ext4, they're only settable if the
488 // filesystem has the 'stable_inodes' feature flag. Android only sets
489 // 'stable_inodes' if the device uses one of these encryption policies "for
490 // real", e.g. "fileencryption=::inlinecrypt_optimized" in fstab. Since the
491 // fstab could contain something else, we have to allow the tests for these
492 // encryption policies to be skipped on ext4.
GetSkipFlagsForInoBasedEncryption()493 int FBEPolicyTest::GetSkipFlagsForInoBasedEncryption() {
494 if (fs_info_.type == "ext4") return kSkipIfNoPolicySupport;
495 return 0;
496 }
497
498 // Sets a v2 encryption policy on the test directory. The policy will use the
499 // test key and the specified encryption modes and flags. If the kernel doesn't
500 // support setting or using the encryption policy, then a failure will be added,
501 // unless the reason is covered by a bit set in |skip_flags|.
SetEncryptionPolicy(int contents_mode,int filenames_mode,int flags,int skip_flags)502 bool FBEPolicyTest::SetEncryptionPolicy(int contents_mode, int filenames_mode,
503 int flags, int skip_flags) {
504 if (!key_added_) {
505 ADD_FAILURE() << "SetEncryptionPolicy called but no key added";
506 return false;
507 }
508
509 struct fscrypt_policy_v2 policy;
510 memset(&policy, 0, sizeof(policy));
511 policy.version = FSCRYPT_POLICY_V2;
512 policy.contents_encryption_mode = contents_mode;
513 policy.filenames_encryption_mode = filenames_mode;
514 // Always give PAD_16, to match the policies that Android sets for real.
515 // It doesn't affect contents encryption, though.
516 policy.flags = flags | FSCRYPT_POLICY_FLAGS_PAD_16;
517 memcpy(policy.master_key_identifier, master_key_specifier_.u.identifier,
518 FSCRYPT_KEY_IDENTIFIER_SIZE);
519
520 android::base::unique_fd dirfd(
521 open(kTestDir, O_RDONLY | O_DIRECTORY | O_CLOEXEC));
522 if (dirfd < 0) {
523 ADD_FAILURE() << "Failed to open " << kTestDir << Errno();
524 return false;
525 }
526 GTEST_LOG_(INFO) << "Setting encryption policy on " << kTestDir;
527 if (ioctl(dirfd, FS_IOC_SET_ENCRYPTION_POLICY, &policy) != 0) {
528 if (errno == EINVAL && (skip_flags & kSkipIfNoPolicySupport)) {
529 GTEST_LOG_(INFO) << "Skipping test because encryption policy is "
530 "unsupported on this filesystem / kernel";
531 return false;
532 }
533 ADD_FAILURE() << "FS_IOC_SET_ENCRYPTION_POLICY failed on " << kTestDir
534 << " using contents_mode=" << contents_mode
535 << ", filenames_mode=" << filenames_mode << ", flags=0x"
536 << std::hex << flags << std::dec << Errno();
537 return false;
538 }
539 if (skip_flags & (kSkipIfNoCryptoAPISupport | kSkipIfNoHardwareSupport)) {
540 android::base::unique_fd fd(
541 open(kTestFile, O_WRONLY | O_CREAT | O_CLOEXEC, 0600));
542 if (fd < 0) {
543 // Setting an encryption policy that uses modes that aren't enabled in the
544 // kernel's crypto API (e.g. FSCRYPT_MODE_ADIANTUM when the kernel lacks
545 // CONFIG_CRYPTO_ADIANTUM) will still succeed, but actually creating a
546 // file will fail with ENOPKG. Make sure to check for this case.
547 if (errno == ENOPKG && (skip_flags & kSkipIfNoCryptoAPISupport)) {
548 GTEST_LOG_(INFO)
549 << "Skipping test because encryption policy is "
550 "unsupported on this kernel, due to missing crypto API support";
551 return false;
552 }
553 // We get EINVAL here when using a hardware-wrapped key and the inline
554 // encryption hardware supports wrapped keys but doesn't support the
555 // number of DUN bytes that the file contents encryption requires.
556 if (errno == EINVAL && (skip_flags & kSkipIfNoHardwareSupport)) {
557 GTEST_LOG_(INFO)
558 << "Skipping test because encryption policy is not compatible with "
559 "this device's inline encryption hardware";
560 return false;
561 }
562 }
563 unlink(kTestFile);
564 }
565 return true;
566 }
567
568 // Generates some test data, writes it to a file in the test directory, and
569 // returns in |info| the file's plaintext, the file's raw ciphertext read from
570 // disk, and other information about the file.
GenerateTestFile(TestFileInfo * info)571 bool FBEPolicyTest::GenerateTestFile(TestFileInfo *info) {
572 info->plaintext.resize(kTestFileBytes);
573 RandomBytesForTesting(info->plaintext);
574
575 if (!WriteTestFile(info->plaintext, kTestFile, fs_info_.raw_blk_device,
576 &info->actual_ciphertext))
577 return false;
578
579 android::base::unique_fd fd(open(kTestFile, O_RDONLY | O_CLOEXEC));
580 if (fd < 0) {
581 ADD_FAILURE() << "Failed to open " << kTestFile << Errno();
582 return false;
583 }
584
585 // Get the file's inode number.
586 if (!GetInodeNumber(kTestFile, &info->inode_number)) return false;
587 GTEST_LOG_(INFO) << "Inode number: " << info->inode_number;
588
589 // Get the file's nonce.
590 if (ioctl(fd, FS_IOC_GET_ENCRYPTION_NONCE, info->nonce.bytes) != 0) {
591 ADD_FAILURE() << "FS_IOC_GET_ENCRYPTION_NONCE failed on " << kTestFile
592 << Errno();
593 return false;
594 }
595 GTEST_LOG_(INFO) << "File nonce: " << BytesToHex(info->nonce.bytes);
596 return true;
597 }
598
InitHkdfInfo(FscryptHkdfContext context)599 static std::vector<uint8_t> InitHkdfInfo(FscryptHkdfContext context) {
600 return {
601 'f', 's', 'c', 'r', 'y', 'p', 't', '\0', static_cast<uint8_t>(context)};
602 }
603
DeriveKey(const std::vector<uint8_t> & master_key,const std::vector<uint8_t> & hkdf_info,std::vector<uint8_t> & out)604 static bool DeriveKey(const std::vector<uint8_t> &master_key,
605 const std::vector<uint8_t> &hkdf_info,
606 std::vector<uint8_t> &out) {
607 if (HKDF(out.data(), out.size(), EVP_sha512(), master_key.data(),
608 master_key.size(), nullptr, 0, hkdf_info.data(),
609 hkdf_info.size()) != 1) {
610 ADD_FAILURE() << "BoringSSL HKDF-SHA512 call failed";
611 return false;
612 }
613 GTEST_LOG_(INFO) << "Derived subkey " << BytesToHex(out)
614 << " using HKDF info " << BytesToHex(hkdf_info);
615 return true;
616 }
617
618 // Derives the key identifier from |master_key| and verifies that it matches the
619 // value the kernel returned in |master_key_specifier_|.
VerifyKeyIdentifier(const std::vector<uint8_t> & master_key)620 bool FBEPolicyTest::VerifyKeyIdentifier(
621 const std::vector<uint8_t> &master_key) {
622 std::vector<uint8_t> hkdf_info = InitHkdfInfo(HKDF_CONTEXT_KEY_IDENTIFIER);
623 std::vector<uint8_t> computed_key_identifier(FSCRYPT_KEY_IDENTIFIER_SIZE);
624 if (!DeriveKey(master_key, hkdf_info, computed_key_identifier)) return false;
625
626 std::vector<uint8_t> actual_key_identifier(
627 std::begin(master_key_specifier_.u.identifier),
628 std::end(master_key_specifier_.u.identifier));
629 EXPECT_EQ(actual_key_identifier, computed_key_identifier);
630 return actual_key_identifier == computed_key_identifier;
631 }
632
633 // Derives a per-mode encryption key from |master_key|, |mode|, |context|, and
634 // (if needed for the context) the filesystem UUID.
DerivePerModeEncryptionKey(const std::vector<uint8_t> & master_key,int mode,FscryptHkdfContext context,std::vector<uint8_t> & enc_key)635 bool FBEPolicyTest::DerivePerModeEncryptionKey(
636 const std::vector<uint8_t> &master_key, int mode,
637 FscryptHkdfContext context, std::vector<uint8_t> &enc_key) {
638 std::vector<uint8_t> hkdf_info = InitHkdfInfo(context);
639
640 hkdf_info.push_back(mode);
641 if (context == HKDF_CONTEXT_IV_INO_LBLK_64_KEY ||
642 context == HKDF_CONTEXT_IV_INO_LBLK_32_KEY)
643 hkdf_info.insert(hkdf_info.end(), fs_info_.uuid.bytes,
644 std::end(fs_info_.uuid.bytes));
645
646 return DeriveKey(master_key, hkdf_info, enc_key);
647 }
648
649 // Derives a per-file encryption key from |master_key| and |nonce|.
DerivePerFileEncryptionKey(const std::vector<uint8_t> & master_key,const FscryptFileNonce & nonce,std::vector<uint8_t> & enc_key)650 bool FBEPolicyTest::DerivePerFileEncryptionKey(
651 const std::vector<uint8_t> &master_key, const FscryptFileNonce &nonce,
652 std::vector<uint8_t> &enc_key) {
653 std::vector<uint8_t> hkdf_info = InitHkdfInfo(HKDF_CONTEXT_PER_FILE_ENC_KEY);
654
655 hkdf_info.insert(hkdf_info.end(), nonce.bytes, std::end(nonce.bytes));
656
657 return DeriveKey(master_key, hkdf_info, enc_key);
658 }
659
660 // For IV_INO_LBLK_32: Hashes the |inode_number| using the SipHash key derived
661 // from |master_key|. Returns the resulting hash in |hash|.
HashInodeNumber(const std::vector<uint8_t> & master_key,uint64_t inode_number,uint32_t * hash)662 static bool HashInodeNumber(const std::vector<uint8_t> &master_key,
663 uint64_t inode_number, uint32_t *hash) {
664 union {
665 uint64_t words[2];
666 __le64 le_words[2];
667 } siphash_key;
668 union {
669 __le64 inode_number;
670 uint8_t bytes[8];
671 } input;
672
673 std::vector<uint8_t> hkdf_info = InitHkdfInfo(HKDF_CONTEXT_INODE_HASH_KEY);
674 std::vector<uint8_t> ino_hash_key(sizeof(siphash_key));
675 if (!DeriveKey(master_key, hkdf_info, ino_hash_key)) return false;
676
677 memcpy(&siphash_key, &ino_hash_key[0], sizeof(siphash_key));
678 siphash_key.words[0] = __le64_to_cpu(siphash_key.le_words[0]);
679 siphash_key.words[1] = __le64_to_cpu(siphash_key.le_words[1]);
680
681 GTEST_LOG_(INFO) << "Inode hash key is {" << std::hex << "0x"
682 << siphash_key.words[0] << ", 0x" << siphash_key.words[1]
683 << "}" << std::dec;
684
685 input.inode_number = __cpu_to_le64(inode_number);
686
687 *hash = SIPHASH_24(siphash_key.words, input.bytes, sizeof(input));
688 GTEST_LOG_(INFO) << "Hashed inode number " << inode_number << " to 0x"
689 << std::hex << *hash << std::dec;
690 return true;
691 }
692
VerifyCiphertext(const std::vector<uint8_t> & enc_key,const FscryptIV & starting_iv,const Cipher & cipher,const TestFileInfo & file_info)693 void FBEPolicyTest::VerifyCiphertext(const std::vector<uint8_t> &enc_key,
694 const FscryptIV &starting_iv,
695 const Cipher &cipher,
696 const TestFileInfo &file_info) {
697 const std::vector<uint8_t> &plaintext = file_info.plaintext;
698
699 GTEST_LOG_(INFO) << "Verifying correctness of encrypted data";
700 FscryptIV iv = starting_iv;
701
702 std::vector<uint8_t> computed_ciphertext(plaintext.size());
703
704 // Encrypt each filesystem block of file contents.
705 for (size_t i = 0; i < plaintext.size(); i += kFilesystemBlockSize) {
706 int block_size =
707 std::min<size_t>(kFilesystemBlockSize, plaintext.size() - i);
708
709 ASSERT_GE(sizeof(iv.bytes), cipher.ivsize());
710 ASSERT_TRUE(cipher.Encrypt(enc_key, iv.bytes, &plaintext[i],
711 &computed_ciphertext[i], block_size));
712
713 // Update the IV by incrementing the file logical block number.
714 iv.lblk_num = __cpu_to_le32(__le32_to_cpu(iv.lblk_num) + 1);
715 }
716
717 ASSERT_EQ(file_info.actual_ciphertext, computed_ciphertext);
718 }
719
InitIVForPerFileKey(FscryptIV * iv)720 static bool InitIVForPerFileKey(FscryptIV *iv) {
721 memset(iv, 0, kFscryptMaxIVSize);
722 return true;
723 }
724
InitIVForDirectKey(const FscryptFileNonce & nonce,FscryptIV * iv)725 static bool InitIVForDirectKey(const FscryptFileNonce &nonce, FscryptIV *iv) {
726 memset(iv, 0, kFscryptMaxIVSize);
727 memcpy(iv->file_nonce, nonce.bytes, kFscryptFileNonceSize);
728 return true;
729 }
730
InitIVForInoLblk64(uint64_t inode_number,FscryptIV * iv)731 static bool InitIVForInoLblk64(uint64_t inode_number, FscryptIV *iv) {
732 if (inode_number > UINT32_MAX) {
733 ADD_FAILURE() << "inode number doesn't fit in 32 bits";
734 return false;
735 }
736 memset(iv, 0, kFscryptMaxIVSize);
737 iv->inode_number = __cpu_to_le32(inode_number);
738 return true;
739 }
740
InitIVForInoLblk32(const std::vector<uint8_t> & master_key,uint64_t inode_number,FscryptIV * iv)741 static bool InitIVForInoLblk32(const std::vector<uint8_t> &master_key,
742 uint64_t inode_number, FscryptIV *iv) {
743 uint32_t hash;
744 if (!HashInodeNumber(master_key, inode_number, &hash)) return false;
745 memset(iv, 0, kFscryptMaxIVSize);
746 iv->lblk_num = __cpu_to_le32(hash);
747 return true;
748 }
749
750 // Tests a policy matching "fileencryption=aes-256-xts:aes-256-cts:v2"
751 // (or simply "fileencryption=" on devices launched with R or higher)
TEST_F(FBEPolicyTest,TestAesPerFileKeysPolicy)752 TEST_F(FBEPolicyTest, TestAesPerFileKeysPolicy) {
753 if (skip_test_) return;
754
755 auto master_key = GenerateTestKey(kFscryptMasterKeySize);
756 ASSERT_TRUE(SetMasterKey(master_key));
757
758 if (!SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
759 0, 0))
760 return;
761
762 TestFileInfo file_info;
763 ASSERT_TRUE(GenerateTestFile(&file_info));
764
765 std::vector<uint8_t> enc_key(kAes256XtsKeySize);
766 ASSERT_TRUE(DerivePerFileEncryptionKey(master_key, file_info.nonce, enc_key));
767
768 FscryptIV iv;
769 ASSERT_TRUE(InitIVForPerFileKey(&iv));
770 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
771 }
772
773 // Tests a policy matching
774 // "fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized"
775 // (or simply "fileencryption=::inlinecrypt_optimized" on devices launched with
776 // R or higher)
TEST_F(FBEPolicyTest,TestAesInlineCryptOptimizedPolicy)777 TEST_F(FBEPolicyTest, TestAesInlineCryptOptimizedPolicy) {
778 if (skip_test_) return;
779
780 auto master_key = GenerateTestKey(kFscryptMasterKeySize);
781 ASSERT_TRUE(SetMasterKey(master_key));
782
783 if (!SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
784 FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64,
785 GetSkipFlagsForInoBasedEncryption()))
786 return;
787
788 TestFileInfo file_info;
789 ASSERT_TRUE(GenerateTestFile(&file_info));
790
791 std::vector<uint8_t> enc_key(kAes256XtsKeySize);
792 ASSERT_TRUE(DerivePerModeEncryptionKey(master_key, FSCRYPT_MODE_AES_256_XTS,
793 HKDF_CONTEXT_IV_INO_LBLK_64_KEY,
794 enc_key));
795
796 FscryptIV iv;
797 ASSERT_TRUE(InitIVForInoLblk64(file_info.inode_number, &iv));
798 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
799 }
800
801 // Tests a policy matching
802 // "fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized+wrappedkey_v0"
803 // (or simply "fileencryption=::inlinecrypt_optimized+wrappedkey_v0" on devices
804 // launched with R or higher)
TEST_F(FBEPolicyTest,TestAesInlineCryptOptimizedHwWrappedKeyPolicy)805 TEST_F(FBEPolicyTest, TestAesInlineCryptOptimizedHwWrappedKeyPolicy) {
806 if (skip_test_) return;
807
808 std::vector<uint8_t> enc_key, sw_secret;
809 if (!CreateAndSetHwWrappedKey(&enc_key, &sw_secret)) return;
810
811 if (!SetEncryptionPolicy(
812 FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
813 FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64,
814 // 64-bit DUN support is not guaranteed.
815 kSkipIfNoHardwareSupport | GetSkipFlagsForInoBasedEncryption()))
816 return;
817
818 TestFileInfo file_info;
819 ASSERT_TRUE(GenerateTestFile(&file_info));
820
821 FscryptIV iv;
822 ASSERT_TRUE(InitIVForInoLblk64(file_info.inode_number, &iv));
823 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
824 }
825
826 // With IV_INO_LBLK_32, the DUN (IV) can wrap from UINT32_MAX to 0 in the middle
827 // of the file. This method tests that this case appears to be handled
828 // correctly, by doing I/O across the place where the DUN wraps around. Assumes
829 // that kTestDir has already been set up with an IV_INO_LBLK_32 policy.
TestEmmcOptimizedDunWraparound(const std::vector<uint8_t> & master_key,const std::vector<uint8_t> & enc_key)830 void FBEPolicyTest::TestEmmcOptimizedDunWraparound(
831 const std::vector<uint8_t> &master_key,
832 const std::vector<uint8_t> &enc_key) {
833 // We'll test writing 'block_count' filesystem blocks. The first
834 // 'block_count_1' blocks will have DUNs [..., UINT32_MAX - 1, UINT32_MAX].
835 // The remaining 'block_count_2' blocks will have DUNs [0, 1, ...].
836 constexpr uint32_t block_count_1 = 3;
837 constexpr uint32_t block_count_2 = 7;
838 constexpr uint32_t block_count = block_count_1 + block_count_2;
839 constexpr size_t data_size = block_count * kFilesystemBlockSize;
840
841 // Assumed maximum file size. Unfortunately there isn't a syscall to get
842 // this. ext4 allows ~16TB and f2fs allows ~4TB. However, an underestimate
843 // works fine for our purposes, so just go with 1TB.
844 constexpr off_t max_file_size = 1000000000000;
845 constexpr off_t max_file_blocks = max_file_size / kFilesystemBlockSize;
846
847 // Repeatedly create empty files until we find one that can be used for DUN
848 // wraparound testing, due to SipHash(inode_number) being almost UINT32_MAX.
849 std::string path;
850 TestFileInfo file_info;
851 uint32_t lblk_with_dun_0;
852 for (int i = 0;; i++) {
853 // The probability of finding a usable file is about 'max_file_blocks /
854 // UINT32_MAX', or about 5.6%. So on average we'll need about 18 tries.
855 // The probability we'll need over 1000 tries is less than 1e-25.
856 ASSERT_LT(i, 1000) << "Tried too many times to find a usable test file";
857
858 path = android::base::StringPrintf("%s/file%d", kTestDir, i);
859 android::base::unique_fd fd(
860 open(path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600));
861 ASSERT_GE(fd, 0) << "Failed to create " << path << Errno();
862
863 ASSERT_TRUE(GetInodeNumber(path, &file_info.inode_number));
864 uint32_t hash;
865 ASSERT_TRUE(HashInodeNumber(master_key, file_info.inode_number, &hash));
866 // Negating the hash gives the distance to DUN 0, and hence the 0-based
867 // logical block number of the block which has DUN 0.
868 lblk_with_dun_0 = -hash;
869 if (lblk_with_dun_0 >= block_count_1 &&
870 static_cast<off_t>(lblk_with_dun_0) + block_count_2 < max_file_blocks)
871 break;
872 }
873
874 GTEST_LOG_(INFO) << "DUN wraparound test: path=" << path
875 << ", inode_number=" << file_info.inode_number
876 << ", lblk_with_dun_0=" << lblk_with_dun_0;
877
878 // Write some data across the DUN wraparound boundary and verify that the
879 // resulting on-disk ciphertext is as expected. Note that we don't actually
880 // have to fill the file until the boundary; we can just write to the needed
881 // part and leave a hole before it.
882 for (int i = 0; i < 2; i++) {
883 // Try both buffered I/O and direct I/O.
884 int open_flags = O_RDWR | O_CLOEXEC;
885 if (i == 1) open_flags |= O_DIRECT;
886
887 android::base::unique_fd fd(open(path.c_str(), open_flags));
888 ASSERT_GE(fd, 0) << "Failed to open " << path << Errno();
889
890 // Generate some test data.
891 file_info.plaintext.resize(data_size);
892 RandomBytesForTesting(file_info.plaintext);
893
894 // Write the test data. To support O_DIRECT, use a block-aligned buffer.
895 std::unique_ptr<void, void (*)(void *)> buf_mem(
896 aligned_alloc(kFilesystemBlockSize, data_size), free);
897 ASSERT_TRUE(buf_mem != nullptr);
898 memcpy(buf_mem.get(), &file_info.plaintext[0], data_size);
899 off_t pos = static_cast<off_t>(lblk_with_dun_0 - block_count_1) *
900 kFilesystemBlockSize;
901 ASSERT_EQ(data_size, pwrite(fd, buf_mem.get(), data_size, pos))
902 << "Error writing data to " << path << Errno();
903
904 // Verify the ciphertext.
905 ASSERT_TRUE(ReadRawDataOfFile(fd, fs_info_.raw_blk_device, data_size,
906 &file_info.actual_ciphertext));
907 FscryptIV iv;
908 memset(&iv, 0, sizeof(iv));
909 iv.lblk_num = __cpu_to_le32(-block_count_1);
910 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
911 }
912 }
913
914 // Tests a policy matching
915 // "fileencryption=aes-256-xts:aes-256-cts:v2+emmc_optimized" (or simply
916 // "fileencryption=::emmc_optimized" on devices launched with R or higher)
TEST_F(FBEPolicyTest,TestAesEmmcOptimizedPolicy)917 TEST_F(FBEPolicyTest, TestAesEmmcOptimizedPolicy) {
918 if (skip_test_) return;
919
920 auto master_key = GenerateTestKey(kFscryptMasterKeySize);
921 ASSERT_TRUE(SetMasterKey(master_key));
922
923 if (!SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
924 FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32,
925 GetSkipFlagsForInoBasedEncryption()))
926 return;
927
928 TestFileInfo file_info;
929 ASSERT_TRUE(GenerateTestFile(&file_info));
930
931 std::vector<uint8_t> enc_key(kAes256XtsKeySize);
932 ASSERT_TRUE(DerivePerModeEncryptionKey(master_key, FSCRYPT_MODE_AES_256_XTS,
933 HKDF_CONTEXT_IV_INO_LBLK_32_KEY,
934 enc_key));
935
936 FscryptIV iv;
937 ASSERT_TRUE(InitIVForInoLblk32(master_key, file_info.inode_number, &iv));
938 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
939
940 TestEmmcOptimizedDunWraparound(master_key, enc_key);
941 }
942
943 // Tests a policy matching
944 // "fileencryption=aes-256-xts:aes-256-cts:v2+emmc_optimized+wrappedkey_v0"
945 // (or simply "fileencryption=::emmc_optimized+wrappedkey_v0" on devices
946 // launched with R or higher)
TEST_F(FBEPolicyTest,TestAesEmmcOptimizedHwWrappedKeyPolicy)947 TEST_F(FBEPolicyTest, TestAesEmmcOptimizedHwWrappedKeyPolicy) {
948 if (skip_test_) return;
949
950 std::vector<uint8_t> enc_key, sw_secret;
951 if (!CreateAndSetHwWrappedKey(&enc_key, &sw_secret)) return;
952
953 if (!SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
954 FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32,
955 GetSkipFlagsForInoBasedEncryption()))
956 return;
957
958 TestFileInfo file_info;
959 ASSERT_TRUE(GenerateTestFile(&file_info));
960
961 FscryptIV iv;
962 ASSERT_TRUE(InitIVForInoLblk32(sw_secret, file_info.inode_number, &iv));
963 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
964
965 TestEmmcOptimizedDunWraparound(sw_secret, enc_key);
966 }
967
968 // Tests a policy matching "fileencryption=adiantum:adiantum:v2" (or simply
969 // "fileencryption=adiantum" on devices launched with R or higher)
TEST_F(FBEPolicyTest,TestAdiantumPolicy)970 TEST_F(FBEPolicyTest, TestAdiantumPolicy) {
971 if (skip_test_) return;
972
973 auto master_key = GenerateTestKey(kFscryptMasterKeySize);
974 ASSERT_TRUE(SetMasterKey(master_key));
975
976 // Adiantum support isn't required (since CONFIG_CRYPTO_ADIANTUM can be unset
977 // in the kernel config), so we may skip the test here.
978 //
979 // We don't need to use GetSkipFlagsForInoBasedEncryption() here, since the
980 // "DIRECT_KEY" IV generation method doesn't include inode numbers in the IVs.
981 if (!SetEncryptionPolicy(FSCRYPT_MODE_ADIANTUM, FSCRYPT_MODE_ADIANTUM,
982 FSCRYPT_POLICY_FLAG_DIRECT_KEY,
983 kSkipIfNoCryptoAPISupport))
984 return;
985
986 TestFileInfo file_info;
987 ASSERT_TRUE(GenerateTestFile(&file_info));
988
989 std::vector<uint8_t> enc_key(kAdiantumKeySize);
990 ASSERT_TRUE(DerivePerModeEncryptionKey(master_key, FSCRYPT_MODE_ADIANTUM,
991 HKDF_CONTEXT_DIRECT_KEY, enc_key));
992
993 FscryptIV iv;
994 ASSERT_TRUE(InitIVForDirectKey(file_info.nonce, &iv));
995 VerifyCiphertext(enc_key, iv, AdiantumCipher(), file_info);
996 }
997
998 // Tests adding a corrupted wrapped key to fscrypt keyring.
999 // If wrapped key is corrupted, fscrypt should return a failure.
TEST_F(FBEPolicyTest,TestHwWrappedKeyCorruption)1000 TEST_F(FBEPolicyTest, TestHwWrappedKeyCorruption) {
1001 if (skip_test_) return;
1002
1003 std::vector<uint8_t> master_key, exported_key;
1004 if (!CreateHwWrappedKey(&master_key, &exported_key)) return;
1005
1006 for (int i = 0; i < exported_key.size(); i++) {
1007 std::vector<uint8_t> corrupt_key(exported_key.begin(), exported_key.end());
1008 corrupt_key[i] = ~corrupt_key[i];
1009 ASSERT_FALSE(
1010 SetMasterKey(corrupt_key, __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED, false));
1011 }
1012 }
1013
1014 // Tests that if the device uses FBE, then the ciphertext for file contents in
1015 // encrypted directories seems to be random.
1016 //
1017 // This isn't as strong a test as the correctness tests, but it's useful because
1018 // it applies regardless of the encryption format and key. Thus it runs even on
1019 // old devices, including ones that used a vendor-specific encryption format.
TEST(FBETest,TestFileContentsRandomness)1020 TEST(FBETest, TestFileContentsRandomness) {
1021 constexpr const char *path_1 = "/data/local/tmp/vts-test-file-1";
1022 constexpr const char *path_2 = "/data/local/tmp/vts-test-file-2";
1023
1024 if (android::base::GetProperty("ro.crypto.type", "") != "file") {
1025 // FBE has been required since Android Q.
1026 int first_api_level;
1027 ASSERT_TRUE(GetFirstApiLevel(&first_api_level));
1028 ASSERT_LE(first_api_level, __ANDROID_API_P__)
1029 << "File-based encryption is required";
1030 GTEST_LOG_(INFO)
1031 << "Skipping test because device doesn't use file-based encryption";
1032 return;
1033 }
1034 FilesystemInfo fs_info;
1035 ASSERT_TRUE(GetFilesystemInfo("/data", &fs_info));
1036
1037 std::vector<uint8_t> zeroes(kTestFileBytes, 0);
1038 std::vector<uint8_t> ciphertext_1;
1039 std::vector<uint8_t> ciphertext_2;
1040 ASSERT_TRUE(
1041 WriteTestFile(zeroes, path_1, fs_info.raw_blk_device, &ciphertext_1));
1042 ASSERT_TRUE(
1043 WriteTestFile(zeroes, path_2, fs_info.raw_blk_device, &ciphertext_2));
1044
1045 GTEST_LOG_(INFO) << "Verifying randomness of ciphertext";
1046
1047 // Each individual file's ciphertext should be random.
1048 ASSERT_TRUE(VerifyDataRandomness(ciphertext_1));
1049 ASSERT_TRUE(VerifyDataRandomness(ciphertext_2));
1050
1051 // The files' ciphertext concatenated should also be random.
1052 // I.e., each file should be encrypted differently.
1053 std::vector<uint8_t> concatenated_ciphertext;
1054 concatenated_ciphertext.insert(concatenated_ciphertext.end(),
1055 ciphertext_1.begin(), ciphertext_1.end());
1056 concatenated_ciphertext.insert(concatenated_ciphertext.end(),
1057 ciphertext_2.begin(), ciphertext_2.end());
1058 ASSERT_TRUE(VerifyDataRandomness(concatenated_ciphertext));
1059
1060 ASSERT_EQ(unlink(path_1), 0);
1061 ASSERT_EQ(unlink(path_2), 0);
1062 }
1063
1064 } // namespace kernel
1065 } // namespace android
1066