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/f2fs.h>
64 #include <linux/fiemap.h>
65 #include <linux/fs.h>
66 #include <linux/fscrypt.h>
67 #include <lz4.h>
68 #include <openssl/evp.h>
69 #include <openssl/hkdf.h>
70 #include <openssl/siphash.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <sys/ioctl.h>
74 #include <unistd.h>
75
76 #include <chrono>
77 #include <thread>
78
79 #include "vts_kernel_encryption.h"
80
81 /* These values are missing from <linux/f2fs.h> */
82 enum f2fs_compress_algorithm {
83 F2FS_COMPRESS_LZO,
84 F2FS_COMPRESS_LZ4,
85 F2FS_COMPRESS_ZSTD,
86 F2FS_COMPRESS_LZORLE,
87 F2FS_COMPRESS_MAX,
88 };
89
90 namespace android {
91 namespace kernel {
92
93 // The main mountpoint of the filesystem the test will use to test FBE.
94 constexpr const char *kTestMountpoint = "/data";
95
96 // A directory on the kTestMountpoint filesystem that doesn't already have an
97 // encryption policy, and therefore allows the creation of subdirectories with
98 // custom encryption policies.
99 constexpr const char *kUnencryptedDir = "/data/unencrypted";
100
101 // A directory on the kTestMountpoint filesystem that already has an encryption
102 // policy. Any files created in this directory will be encrypted using the
103 // encryption settings that Android is configured to use.
104 constexpr const char *kTmpDir = "/data/local/tmp";
105
106 // Assumed size of filesystem blocks, in bytes
107 constexpr int kFilesystemBlockSize = 4096;
108
109 // Size of the test file in filesystem blocks
110 constexpr int kTestFileBlocks = 256;
111
112 // Size of the test file in bytes
113 constexpr int kTestFileBytes = kFilesystemBlockSize * kTestFileBlocks;
114
115 // fscrypt master key size in bytes
116 constexpr int kFscryptMasterKeySize = 64;
117
118 // fscrypt maximum IV size in bytes
119 constexpr int kFscryptMaxIVSize = 32;
120
121 // fscrypt per-file nonce size in bytes
122 constexpr int kFscryptFileNonceSize = 16;
123
124 // fscrypt HKDF context bytes, from kernel fs/crypto/fscrypt_private.h
125 enum FscryptHkdfContext {
126 HKDF_CONTEXT_KEY_IDENTIFIER = 1,
127 HKDF_CONTEXT_PER_FILE_ENC_KEY = 2,
128 HKDF_CONTEXT_DIRECT_KEY = 3,
129 HKDF_CONTEXT_IV_INO_LBLK_64_KEY = 4,
130 HKDF_CONTEXT_DIRHASH_KEY = 5,
131 HKDF_CONTEXT_IV_INO_LBLK_32_KEY = 6,
132 HKDF_CONTEXT_INODE_HASH_KEY = 7,
133 };
134
135 struct FscryptFileNonce {
136 uint8_t bytes[kFscryptFileNonceSize];
137 };
138
139 // Format of the initialization vector
140 union FscryptIV {
141 struct {
142 __le32 lblk_num; // file logical block number, starts at 0
143 __le32 inode_number; // only used for IV_INO_LBLK_64
144 uint8_t file_nonce[kFscryptFileNonceSize]; // only used for DIRECT_KEY
145 };
146 uint8_t bytes[kFscryptMaxIVSize];
147 };
148
149 struct TestFileInfo {
150 std::vector<uint8_t> plaintext;
151 std::vector<uint8_t> actual_ciphertext;
152 uint64_t inode_number;
153 FscryptFileNonce nonce;
154 };
155
GetInodeNumber(const std::string & path,uint64_t * inode_number)156 static bool GetInodeNumber(const std::string &path, uint64_t *inode_number) {
157 struct stat stbuf;
158 if (stat(path.c_str(), &stbuf) != 0) {
159 ADD_FAILURE() << "Failed to stat " << path << Errno();
160 return false;
161 }
162 *inode_number = stbuf.st_ino;
163 return true;
164 }
165
166 //
167 // Checks whether the kernel has support for the following fscrypt features:
168 //
169 // - Filesystem-level keyring (FS_IOC_ADD_ENCRYPTION_KEY and
170 // FS_IOC_REMOVE_ENCRYPTION_KEY)
171 // - v2 encryption policies
172 // - The IV_INO_LBLK_64 encryption policy flag
173 // - The FS_IOC_GET_ENCRYPTION_NONCE ioctl
174 // - The IV_INO_LBLK_32 encryption policy flag
175 //
176 // To do this it's sufficient to just check whether FS_IOC_ADD_ENCRYPTION_KEY is
177 // available, as the other features were added in the same AOSP release.
178 //
179 // The easiest way to do this is to just execute the ioctl with a NULL argument.
180 // If available it will fail with EFAULT; otherwise it will fail with ENOTTY (or
181 // EOPNOTSUPP if encryption isn't enabled on the filesystem; that happens on old
182 // devices that aren't using FBE and are upgraded to a new kernel).
183 //
IsFscryptV2Supported(const std::string & mountpoint)184 static bool IsFscryptV2Supported(const std::string &mountpoint) {
185 android::base::unique_fd fd(
186 open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
187 if (fd < 0) {
188 ADD_FAILURE() << "Failed to open " << mountpoint << Errno();
189 return false;
190 }
191
192 if (ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, nullptr) == 0) {
193 ADD_FAILURE()
194 << "FS_IOC_ADD_ENCRYPTION_KEY(nullptr) unexpectedly succeeded on "
195 << mountpoint;
196 return false;
197 }
198 switch (errno) {
199 case EFAULT:
200 return true;
201 case EOPNOTSUPP:
202 case ENOTTY:
203 GTEST_LOG_(INFO) << "No support for FS_IOC_ADD_ENCRYPTION_KEY on "
204 << mountpoint;
205 return false;
206 default:
207 ADD_FAILURE()
208 << "Unexpected error from FS_IOC_ADD_ENCRYPTION_KEY(nullptr) on "
209 << mountpoint << Errno();
210 return false;
211 }
212 }
213
214 // Helper class to freeze / unfreeze a filesystem, to prevent the filesystem
215 // from moving the file's blocks while the test is accessing them via the
216 // underlying device. ext4 doesn't need this, but f2fs does because f2fs does
217 // background garbage collection. We cannot use F2FS_IOC_SET_PIN_FILE because
218 // F2FS_IOC_SET_PIN_FILE doesn't support compressed files.
219 //
220 // The fd given can be any fd to a file or directory on the filesystem.
221 // FIFREEZE operates on the whole filesystem, not on the individual file given.
222 class ScopedFsFreezer {
223 public:
ScopedFsFreezer(int fd)224 explicit ScopedFsFreezer(int fd) {
225 auto start = std::chrono::steady_clock::now();
226 do {
227 if (ioctl(fd, FIFREEZE, NULL) == 0) {
228 fd_ = fd;
229 return;
230 }
231 if (errno == EBUSY || errno == EINVAL) {
232 // EBUSY means the filesystem is already frozen, perhaps by a concurrent
233 // execution of this same test. Since we don't have control over
234 // exactly when another process unfreezes the filesystem, we don't
235 // continue on with the test but rather just keep retrying the freeze
236 // until it works.
237 //
238 // Very rarely, on f2fs FIFREEZE fails with EINVAL (b/255800104).
239 // Unfortunately, the reason for this is still unknown. Enter the retry
240 // loop in this case too, in the hope that it helps.
241 //
242 // Both of these errors are rare, so this sleep should not normally be
243 // executed.
244 std::this_thread::sleep_for(std::chrono::milliseconds(100));
245 continue;
246 }
247 ADD_FAILURE() << "Failed to freeze filesystem" << Errno();
248 return;
249 } while (std::chrono::steady_clock::now() - start <
250 std::chrono::seconds(20));
251 ADD_FAILURE() << "Timed out while waiting to freeze filesystem";
252 }
253
~ScopedFsFreezer()254 ~ScopedFsFreezer() {
255 if (fd_ != -1 && ioctl(fd_, FITHAW, NULL) != 0) {
256 ADD_FAILURE() << "Failed to thaw filesystem" << Errno();
257 }
258 }
259
260 private:
261 int fd_ = -1;
262 };
263
264 // Reads the raw data of the file specified by |fd| from its underlying block
265 // device |blk_device|. The file has |expected_data_size| bytes of initialized
266 // data; this must be a multiple of the filesystem block size
267 // kFilesystemBlockSize. The file may contain holes, in which case only the
268 // 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)269 static bool ReadRawDataOfFile(int fd, const std::string &blk_device,
270 int expected_data_size,
271 std::vector<uint8_t> *raw_data) {
272 int max_extents = expected_data_size / kFilesystemBlockSize;
273
274 EXPECT_TRUE(expected_data_size % kFilesystemBlockSize == 0);
275
276 if (fsync(fd) != 0) {
277 ADD_FAILURE() << "Failed to sync file" << Errno();
278 return false;
279 }
280
281 // Freeze the filesystem containing the file.
282 ScopedFsFreezer freezer(fd);
283
284 // Query the file's extents.
285 size_t allocsize = offsetof(struct fiemap, fm_extents[max_extents]);
286 std::unique_ptr<struct fiemap> map(
287 new (::operator new(allocsize)) struct fiemap);
288 memset(map.get(), 0, allocsize);
289 map->fm_flags = 0;
290 map->fm_length = UINT64_MAX;
291 map->fm_extent_count = max_extents;
292 if (ioctl(fd, FS_IOC_FIEMAP, map.get()) != 0) {
293 ADD_FAILURE() << "Failed to get extents of file" << Errno();
294 return false;
295 }
296
297 // Read the raw data, using direct I/O to avoid getting any stale cached data.
298 // Direct I/O requires using a block size aligned buffer.
299
300 std::unique_ptr<void, void (*)(void *)> buf_mem(
301 aligned_alloc(kFilesystemBlockSize, expected_data_size), free);
302 if (buf_mem == nullptr) {
303 ADD_FAILURE() << "Out of memory";
304 return false;
305 }
306 uint8_t *buf = static_cast<uint8_t *>(buf_mem.get());
307 int offset = 0;
308
309 android::base::unique_fd blk_fd(
310 open(blk_device.c_str(), O_RDONLY | O_DIRECT | O_CLOEXEC));
311 if (blk_fd < 0) {
312 ADD_FAILURE() << "Failed to open raw block device " << blk_device
313 << Errno();
314 return false;
315 }
316
317 for (int i = 0; i < map->fm_mapped_extents; i++) {
318 const struct fiemap_extent &extent = map->fm_extents[i];
319
320 GTEST_LOG_(INFO) << "Extent " << i + 1 << " of " << map->fm_mapped_extents
321 << " is logical offset " << extent.fe_logical
322 << ", physical offset " << extent.fe_physical
323 << ", length " << extent.fe_length << ", flags 0x"
324 << std::hex << extent.fe_flags << std::dec;
325 // Make sure the flags indicate that fe_physical is actually valid.
326 if (extent.fe_flags & (FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_UNWRITTEN)) {
327 ADD_FAILURE() << "Unsupported extent flags: 0x" << std::hex
328 << extent.fe_flags << std::dec;
329 return false;
330 }
331 if (extent.fe_length % kFilesystemBlockSize != 0) {
332 ADD_FAILURE() << "Extent is not aligned to filesystem block size";
333 return false;
334 }
335 if (extent.fe_length > expected_data_size - offset) {
336 ADD_FAILURE() << "File is longer than expected";
337 return false;
338 }
339 if (pread(blk_fd, &buf[offset], extent.fe_length, extent.fe_physical) !=
340 extent.fe_length) {
341 ADD_FAILURE() << "Error reading raw data from block device" << Errno();
342 return false;
343 }
344 offset += extent.fe_length;
345 }
346 if (offset != expected_data_size) {
347 ADD_FAILURE() << "File is shorter than expected";
348 return false;
349 }
350 *raw_data = std::vector<uint8_t>(&buf[0], &buf[offset]);
351 return true;
352 }
353
354 // Writes |plaintext| to a file |path| located on the block device |blk_device|.
355 // 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,const struct f2fs_comp_option * compress_options,std::vector<uint8_t> * ciphertext)356 static bool WriteTestFile(const std::vector<uint8_t> &plaintext,
357 const std::string &path,
358 const std::string &blk_device,
359 const struct f2fs_comp_option *compress_options,
360 std::vector<uint8_t> *ciphertext) {
361 GTEST_LOG_(INFO) << "Creating test file " << path << " containing "
362 << plaintext.size() << " bytes of data";
363 android::base::unique_fd fd(
364 open(path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600));
365 if (fd < 0) {
366 ADD_FAILURE() << "Failed to create " << path << Errno();
367 return false;
368 }
369
370 if (compress_options != nullptr) {
371 if (ioctl(fd, F2FS_IOC_SET_COMPRESS_OPTION, compress_options) != 0) {
372 ADD_FAILURE() << "Error setting compression options on " << path
373 << Errno();
374 return false;
375 }
376 }
377
378 if (!android::base::WriteFully(fd, plaintext.data(), plaintext.size())) {
379 ADD_FAILURE() << "Error writing to " << path << Errno();
380 return false;
381 }
382
383 if (compress_options != nullptr) {
384 // With compress_mode=user, files in a compressed directory inherit the
385 // compression flag but aren't actually compressed unless
386 // F2FS_IOC_COMPRESS_FILE is called. The ioctl compresses existing data
387 // only, so it must be called *after* writing the data. With
388 // compress_mode=fs, the ioctl is unnecessary and fails with EOPNOTSUPP.
389 if (ioctl(fd, F2FS_IOC_COMPRESS_FILE, NULL) != 0 && errno != EOPNOTSUPP) {
390 ADD_FAILURE() << "F2FS_IOC_COMPRESS_FILE failed on " << path << Errno();
391 return false;
392 }
393 }
394
395 GTEST_LOG_(INFO) << "Reading the raw ciphertext of " << path << " from disk";
396 if (!ReadRawDataOfFile(fd, blk_device, plaintext.size(), ciphertext)) {
397 ADD_FAILURE() << "Failed to read the raw ciphertext of " << path;
398 return false;
399 }
400 return true;
401 }
402
403 // See MakeSomeCompressibleClusters() for explanation.
IsCompressibleCluster(int cluster_num)404 static bool IsCompressibleCluster(int cluster_num) {
405 return cluster_num % 2 == 0;
406 }
407
408 // Given some random data that will be written to the test file, modifies every
409 // other compression cluster to be compressible by at least 1 filesystem block.
410 //
411 // This testing strategy is adapted from the xfstest "f2fs/002". We use some
412 // compressible clusters and some incompressible clusters because we want to
413 // test that the encryption works correctly with both. We also don't make the
414 // data *too* compressible, since we want to have enough compressed blocks in
415 // each cluster to see the IVs being incremented.
MakeSomeCompressibleClusters(std::vector<uint8_t> & bytes,int log_cluster_size)416 static bool MakeSomeCompressibleClusters(std::vector<uint8_t> &bytes,
417 int log_cluster_size) {
418 int cluster_bytes = kFilesystemBlockSize << log_cluster_size;
419 if (bytes.size() % cluster_bytes != 0) {
420 ADD_FAILURE() << "Test file size (" << bytes.size()
421 << " bytes) is not divisible by compression cluster size ("
422 << cluster_bytes << " bytes)";
423 return false;
424 }
425 int num_clusters = bytes.size() / cluster_bytes;
426 for (int i = 0; i < num_clusters; i++) {
427 if (IsCompressibleCluster(i)) {
428 memset(&bytes[i * cluster_bytes], 0, 2 * kFilesystemBlockSize);
429 }
430 }
431 return true;
432 }
433
434 // On-disk format of an f2fs compressed cluster
435 struct f2fs_compressed_cluster {
436 __le32 clen;
437 __le32 reserved[5];
438 uint8_t cdata[];
439 } __attribute__((packed));
440
DecompressLZ4Cluster(const uint8_t * in,uint8_t * out,int cluster_bytes)441 static bool DecompressLZ4Cluster(const uint8_t *in, uint8_t *out,
442 int cluster_bytes) {
443 const struct f2fs_compressed_cluster *cluster =
444 reinterpret_cast<const struct f2fs_compressed_cluster *>(in);
445 uint32_t clen = __le32_to_cpu(cluster->clen);
446
447 if (clen > cluster_bytes - kFilesystemBlockSize - sizeof(*cluster)) {
448 ADD_FAILURE() << "Invalid compressed cluster (bad compressed size)";
449 return false;
450 }
451 if (LZ4_decompress_safe(reinterpret_cast<const char *>(cluster->cdata),
452 reinterpret_cast<char *>(out), clen,
453 cluster_bytes) != cluster_bytes) {
454 ADD_FAILURE() << "Invalid compressed cluster (LZ4 decompression error)";
455 return false;
456 }
457
458 // As long as we're here, do a regression test for kernel commit 7fa6d59816e7
459 // ("f2fs: fix leaking uninitialized memory in compressed clusters").
460 // Note that if this fails, we can still continue with the rest of the test.
461 size_t full_clen = offsetof(struct f2fs_compressed_cluster, cdata[clen]);
462 if (full_clen % kFilesystemBlockSize != 0) {
463 size_t remainder =
464 kFilesystemBlockSize - (full_clen % kFilesystemBlockSize);
465 std::vector<uint8_t> zeroes(remainder, 0);
466 std::vector<uint8_t> actual(&cluster->cdata[clen],
467 &cluster->cdata[clen + remainder]);
468 EXPECT_EQ(zeroes, actual);
469 }
470 return true;
471 }
472
473 class FBEPolicyTest : public ::testing::Test {
474 protected:
475 void SetUp() override;
476 void TearDown() override;
477 bool SetMasterKey(const std::vector<uint8_t> &master_key, uint32_t flags = 0,
478 bool required = true);
479 bool CreateAndSetHwWrappedKey(std::vector<uint8_t> *enc_key,
480 std::vector<uint8_t> *sw_secret);
481 int GetSkipFlagsForInoBasedEncryption();
482 bool SetEncryptionPolicy(int contents_mode, int filenames_mode, int flags,
483 int skip_flags);
484 bool GenerateTestFile(
485 TestFileInfo *info,
486 const struct f2fs_comp_option *compress_options = nullptr);
487 bool VerifyKeyIdentifier(const std::vector<uint8_t> &master_key);
488 bool DerivePerModeEncryptionKey(const std::vector<uint8_t> &master_key,
489 int mode, FscryptHkdfContext context,
490 std::vector<uint8_t> &enc_key);
491 bool DerivePerFileEncryptionKey(const std::vector<uint8_t> &master_key,
492 const FscryptFileNonce &nonce,
493 std::vector<uint8_t> &enc_key);
494 void VerifyCiphertext(const std::vector<uint8_t> &enc_key,
495 const FscryptIV &starting_iv, const Cipher &cipher,
496 const TestFileInfo &file_info);
497 void TestEmmcOptimizedDunWraparound(const std::vector<uint8_t> &master_key,
498 const std::vector<uint8_t> &enc_key);
499 bool EnableF2fsCompressionOnTestDir();
500 bool F2fsCompressOptionsSupported(const struct f2fs_comp_option &opts);
501 std::string test_dir_;
502 std::string test_file_;
503 struct fscrypt_key_specifier master_key_specifier_;
504 bool skip_test_ = false;
505 bool key_added_ = false;
506 FilesystemInfo fs_info_;
507 };
508
509 // Test setup procedure. Creates a test directory test_dir_ and does other
510 // preparations. skip_test_ is set to true if the test should be skipped.
SetUp()511 void FBEPolicyTest::SetUp() {
512 if (!IsFscryptV2Supported(kTestMountpoint)) {
513 int first_api_level;
514 ASSERT_TRUE(GetFirstApiLevel(&first_api_level));
515 // Devices launching with R or higher must support fscrypt v2.
516 ASSERT_LE(first_api_level, __ANDROID_API_Q__);
517 GTEST_LOG_(INFO) << "Skipping test because fscrypt v2 is unsupported";
518 skip_test_ = true;
519 return;
520 }
521
522 // Make sure that if multiple test processes run simultaneously, they generate
523 // different encryption keys.
524 srand(getpid());
525
526 test_dir_ = android::base::StringPrintf("%s/FBEPolicyTest.%d",
527 kUnencryptedDir, getpid());
528 test_file_ = test_dir_ + "/file";
529
530 ASSERT_TRUE(GetFilesystemInfo(kTestMountpoint, &fs_info_));
531
532 DeleteRecursively(test_dir_);
533 if (mkdir(test_dir_.c_str(), 0700) != 0) {
534 FAIL() << "Failed to create " << test_dir_ << Errno();
535 }
536 }
537
TearDown()538 void FBEPolicyTest::TearDown() {
539 DeleteRecursively(test_dir_);
540
541 // Remove the test key from kTestMountpoint.
542 if (key_added_) {
543 android::base::unique_fd mntfd(
544 open(kTestMountpoint, O_RDONLY | O_DIRECTORY | O_CLOEXEC));
545 if (mntfd < 0) {
546 FAIL() << "Failed to open " << kTestMountpoint << Errno();
547 }
548 struct fscrypt_remove_key_arg arg;
549 memset(&arg, 0, sizeof(arg));
550 arg.key_spec = master_key_specifier_;
551
552 if (ioctl(mntfd, FS_IOC_REMOVE_ENCRYPTION_KEY, &arg) != 0) {
553 FAIL() << "FS_IOC_REMOVE_ENCRYPTION_KEY failed on " << kTestMountpoint
554 << Errno();
555 }
556 }
557 }
558
559 // Adds |master_key| to kTestMountpoint and places the resulting key identifier
560 // in master_key_specifier_.
SetMasterKey(const std::vector<uint8_t> & master_key,uint32_t flags,bool required)561 bool FBEPolicyTest::SetMasterKey(const std::vector<uint8_t> &master_key,
562 uint32_t flags, bool required) {
563 size_t allocsize = sizeof(struct fscrypt_add_key_arg) + master_key.size();
564 std::unique_ptr<struct fscrypt_add_key_arg> arg(
565 new (::operator new(allocsize)) struct fscrypt_add_key_arg);
566 memset(arg.get(), 0, allocsize);
567 arg->key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
568 arg->__flags = flags;
569 arg->raw_size = master_key.size();
570 std::copy(master_key.begin(), master_key.end(), arg->raw);
571
572 GTEST_LOG_(INFO) << "Adding fscrypt master key, flags are 0x" << std::hex
573 << flags << std::dec << ", raw bytes are "
574 << BytesToHex(master_key);
575 android::base::unique_fd mntfd(
576 open(kTestMountpoint, O_RDONLY | O_DIRECTORY | O_CLOEXEC));
577 if (mntfd < 0) {
578 ADD_FAILURE() << "Failed to open " << kTestMountpoint << Errno();
579 return false;
580 }
581 if (ioctl(mntfd, FS_IOC_ADD_ENCRYPTION_KEY, arg.get()) != 0) {
582 if (required || (errno != EINVAL && errno != EOPNOTSUPP)) {
583 ADD_FAILURE() << "FS_IOC_ADD_ENCRYPTION_KEY failed on " << kTestMountpoint
584 << Errno();
585 }
586 return false;
587 }
588 master_key_specifier_ = arg->key_spec;
589 GTEST_LOG_(INFO) << "Master key identifier is "
590 << BytesToHex(master_key_specifier_.u.identifier);
591 key_added_ = true;
592 if (!(flags & __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED) &&
593 !VerifyKeyIdentifier(master_key))
594 return false;
595 return true;
596 }
597
598 // Creates a hardware-wrapped key, adds it to the filesystem, and derives the
599 // corresponding inline encryption key |enc_key| and software secret
600 // |sw_secret|. Returns false if unsuccessful (either the test failed, or the
601 // 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)602 bool FBEPolicyTest::CreateAndSetHwWrappedKey(std::vector<uint8_t> *enc_key,
603 std::vector<uint8_t> *sw_secret) {
604 std::vector<uint8_t> master_key, exported_key;
605 if (!CreateHwWrappedKey(&master_key, &exported_key)) return false;
606
607 if (!SetMasterKey(exported_key, __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED, false)) {
608 if (!HasFailure()) {
609 GTEST_LOG_(INFO) << "Skipping test because kernel doesn't support "
610 "hardware-wrapped keys";
611 }
612 return false;
613 }
614
615 if (!DeriveHwWrappedEncryptionKey(master_key, enc_key)) return false;
616 if (!DeriveHwWrappedRawSecret(master_key, sw_secret)) return false;
617
618 if (!VerifyKeyIdentifier(*sw_secret)) return false;
619
620 return true;
621 }
622
623 enum {
624 kSkipIfNoPolicySupport = 1 << 0,
625 kSkipIfNoCryptoAPISupport = 1 << 1,
626 kSkipIfInlineEncryptionNotUsable = 1 << 2,
627 };
628
629 // Returns 0 if encryption policies that include the inode number in the IVs
630 // (e.g. IV_INO_LBLK_64) are guaranteed to be settable on the test filesystem.
631 // Else returns kSkipIfNoPolicySupport.
632 //
633 // On f2fs, they're always settable. On ext4, they're only settable if the
634 // filesystem has the 'stable_inodes' feature flag. Android only sets
635 // 'stable_inodes' if the device uses one of these encryption policies "for
636 // real", e.g. "fileencryption=::inlinecrypt_optimized" in fstab. Since the
637 // fstab could contain something else, we have to allow the tests for these
638 // encryption policies to be skipped on ext4.
GetSkipFlagsForInoBasedEncryption()639 int FBEPolicyTest::GetSkipFlagsForInoBasedEncryption() {
640 if (fs_info_.type == "ext4") return kSkipIfNoPolicySupport;
641 return 0;
642 }
643
644 // Sets a v2 encryption policy on the test directory. The policy will use the
645 // test key and the specified encryption modes and flags. If the kernel doesn't
646 // support setting or using the encryption policy, then a failure will be added,
647 // unless the reason is covered by a bit set in |skip_flags|.
SetEncryptionPolicy(int contents_mode,int filenames_mode,int flags,int skip_flags)648 bool FBEPolicyTest::SetEncryptionPolicy(int contents_mode, int filenames_mode,
649 int flags, int skip_flags) {
650 if (!key_added_) {
651 ADD_FAILURE() << "SetEncryptionPolicy called but no key added";
652 return false;
653 }
654
655 struct fscrypt_policy_v2 policy;
656 memset(&policy, 0, sizeof(policy));
657 policy.version = FSCRYPT_POLICY_V2;
658 policy.contents_encryption_mode = contents_mode;
659 policy.filenames_encryption_mode = filenames_mode;
660 // Always give PAD_16, to match the policies that Android sets for real.
661 // It doesn't affect contents encryption, though.
662 policy.flags = flags | FSCRYPT_POLICY_FLAGS_PAD_16;
663 memcpy(policy.master_key_identifier, master_key_specifier_.u.identifier,
664 FSCRYPT_KEY_IDENTIFIER_SIZE);
665
666 android::base::unique_fd dirfd(
667 open(test_dir_.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
668 if (dirfd < 0) {
669 ADD_FAILURE() << "Failed to open " << test_dir_ << Errno();
670 return false;
671 }
672 GTEST_LOG_(INFO) << "Setting encryption policy on " << test_dir_;
673 if (ioctl(dirfd, FS_IOC_SET_ENCRYPTION_POLICY, &policy) != 0) {
674 if (errno == EINVAL && (skip_flags & kSkipIfNoPolicySupport)) {
675 GTEST_LOG_(INFO) << "Skipping test because encryption policy is "
676 "unsupported on this filesystem / kernel";
677 return false;
678 }
679 ADD_FAILURE() << "FS_IOC_SET_ENCRYPTION_POLICY failed on " << test_dir_
680 << " using contents_mode=" << contents_mode
681 << ", filenames_mode=" << filenames_mode << ", flags=0x"
682 << std::hex << flags << std::dec << Errno();
683 return false;
684 }
685 if (skip_flags &
686 (kSkipIfNoCryptoAPISupport | kSkipIfInlineEncryptionNotUsable)) {
687 android::base::unique_fd fd(
688 open(test_file_.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600));
689 if (fd < 0) {
690 // Setting an encryption policy that uses modes that aren't enabled in the
691 // kernel's crypto API (e.g. FSCRYPT_MODE_ADIANTUM when the kernel lacks
692 // CONFIG_CRYPTO_ADIANTUM) will still succeed, but actually creating a
693 // file will fail with ENOPKG. Make sure to check for this case.
694 if (errno == ENOPKG && (skip_flags & kSkipIfNoCryptoAPISupport)) {
695 GTEST_LOG_(INFO)
696 << "Skipping test because encryption policy is "
697 "unsupported on this kernel, due to missing crypto API support";
698 return false;
699 }
700 // We get EINVAL here when we're using a hardware-wrapped key, the device
701 // has inline encryption hardware that supports hardware-wrapped keys, and
702 // there are hardware or kernel limitations that make it impossible for
703 // inline encryption to actually be used with the policy. For example:
704 //
705 // - The device's inline encryption hardware doesn't support the number
706 // of DUN bytes needed for file contents encryption.
707 //
708 // - The policy uses the IV_INO_LBLK_32 flag, and the filesystem block
709 // size differs from the page size. (Kernel limitation.)
710 if (errno == EINVAL && (skip_flags & kSkipIfInlineEncryptionNotUsable)) {
711 GTEST_LOG_(INFO)
712 << "Skipping test because encryption policy requires inline "
713 "encryption, but inline encryption is unsupported with this "
714 "policy on this device due to hardware or kernel limitations";
715 return false;
716 }
717 }
718 unlink(test_file_.c_str());
719 }
720 return true;
721 }
722
723 // Generates some test data, writes it to a file in the test directory, and
724 // returns in |info| the file's plaintext, the file's raw ciphertext read from
725 // disk, and other information about the file.
GenerateTestFile(TestFileInfo * info,const struct f2fs_comp_option * compress_options)726 bool FBEPolicyTest::GenerateTestFile(
727 TestFileInfo *info, const struct f2fs_comp_option *compress_options) {
728 info->plaintext.resize(kTestFileBytes);
729 RandomBytesForTesting(info->plaintext);
730
731 if (compress_options != nullptr &&
732 !MakeSomeCompressibleClusters(info->plaintext,
733 compress_options->log_cluster_size))
734 return false;
735
736 if (!WriteTestFile(info->plaintext, test_file_, fs_info_.raw_blk_device,
737 compress_options, &info->actual_ciphertext))
738 return false;
739
740 android::base::unique_fd fd(open(test_file_.c_str(), O_RDONLY | O_CLOEXEC));
741 if (fd < 0) {
742 ADD_FAILURE() << "Failed to open " << test_file_ << Errno();
743 return false;
744 }
745
746 // Get the file's inode number.
747 if (!GetInodeNumber(test_file_, &info->inode_number)) return false;
748 GTEST_LOG_(INFO) << "Inode number: " << info->inode_number;
749
750 // Get the file's nonce.
751 if (ioctl(fd, FS_IOC_GET_ENCRYPTION_NONCE, info->nonce.bytes) != 0) {
752 ADD_FAILURE() << "FS_IOC_GET_ENCRYPTION_NONCE failed on " << test_file_
753 << Errno();
754 return false;
755 }
756 GTEST_LOG_(INFO) << "File nonce: " << BytesToHex(info->nonce.bytes);
757 return true;
758 }
759
InitHkdfInfo(FscryptHkdfContext context)760 static std::vector<uint8_t> InitHkdfInfo(FscryptHkdfContext context) {
761 return {
762 'f', 's', 'c', 'r', 'y', 'p', 't', '\0', static_cast<uint8_t>(context)};
763 }
764
DeriveKey(const std::vector<uint8_t> & master_key,const std::vector<uint8_t> & hkdf_info,std::vector<uint8_t> & out)765 static bool DeriveKey(const std::vector<uint8_t> &master_key,
766 const std::vector<uint8_t> &hkdf_info,
767 std::vector<uint8_t> &out) {
768 if (HKDF(out.data(), out.size(), EVP_sha512(), master_key.data(),
769 master_key.size(), nullptr, 0, hkdf_info.data(),
770 hkdf_info.size()) != 1) {
771 ADD_FAILURE() << "BoringSSL HKDF-SHA512 call failed";
772 return false;
773 }
774 GTEST_LOG_(INFO) << "Derived subkey " << BytesToHex(out)
775 << " using HKDF info " << BytesToHex(hkdf_info);
776 return true;
777 }
778
779 // Derives the key identifier from |master_key| and verifies that it matches the
780 // value the kernel returned in |master_key_specifier_|.
VerifyKeyIdentifier(const std::vector<uint8_t> & master_key)781 bool FBEPolicyTest::VerifyKeyIdentifier(
782 const std::vector<uint8_t> &master_key) {
783 std::vector<uint8_t> hkdf_info = InitHkdfInfo(HKDF_CONTEXT_KEY_IDENTIFIER);
784 std::vector<uint8_t> computed_key_identifier(FSCRYPT_KEY_IDENTIFIER_SIZE);
785 if (!DeriveKey(master_key, hkdf_info, computed_key_identifier)) return false;
786
787 std::vector<uint8_t> actual_key_identifier(
788 std::begin(master_key_specifier_.u.identifier),
789 std::end(master_key_specifier_.u.identifier));
790 EXPECT_EQ(actual_key_identifier, computed_key_identifier);
791 return actual_key_identifier == computed_key_identifier;
792 }
793
794 // Derives a per-mode encryption key from |master_key|, |mode|, |context|, and
795 // (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)796 bool FBEPolicyTest::DerivePerModeEncryptionKey(
797 const std::vector<uint8_t> &master_key, int mode,
798 FscryptHkdfContext context, std::vector<uint8_t> &enc_key) {
799 std::vector<uint8_t> hkdf_info = InitHkdfInfo(context);
800
801 hkdf_info.push_back(mode);
802 if (context == HKDF_CONTEXT_IV_INO_LBLK_64_KEY ||
803 context == HKDF_CONTEXT_IV_INO_LBLK_32_KEY)
804 hkdf_info.insert(hkdf_info.end(), fs_info_.uuid.bytes,
805 std::end(fs_info_.uuid.bytes));
806
807 return DeriveKey(master_key, hkdf_info, enc_key);
808 }
809
810 // 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)811 bool FBEPolicyTest::DerivePerFileEncryptionKey(
812 const std::vector<uint8_t> &master_key, const FscryptFileNonce &nonce,
813 std::vector<uint8_t> &enc_key) {
814 std::vector<uint8_t> hkdf_info = InitHkdfInfo(HKDF_CONTEXT_PER_FILE_ENC_KEY);
815
816 hkdf_info.insert(hkdf_info.end(), nonce.bytes, std::end(nonce.bytes));
817
818 return DeriveKey(master_key, hkdf_info, enc_key);
819 }
820
821 // For IV_INO_LBLK_32: Hashes the |inode_number| using the SipHash key derived
822 // from |master_key|. Returns the resulting hash in |hash|.
HashInodeNumber(const std::vector<uint8_t> & master_key,uint64_t inode_number,uint32_t * hash)823 static bool HashInodeNumber(const std::vector<uint8_t> &master_key,
824 uint64_t inode_number, uint32_t *hash) {
825 union {
826 uint64_t words[2];
827 __le64 le_words[2];
828 } siphash_key;
829 union {
830 __le64 inode_number;
831 uint8_t bytes[8];
832 } input;
833
834 std::vector<uint8_t> hkdf_info = InitHkdfInfo(HKDF_CONTEXT_INODE_HASH_KEY);
835 std::vector<uint8_t> ino_hash_key(sizeof(siphash_key));
836 if (!DeriveKey(master_key, hkdf_info, ino_hash_key)) return false;
837
838 memcpy(&siphash_key, &ino_hash_key[0], sizeof(siphash_key));
839 siphash_key.words[0] = __le64_to_cpu(siphash_key.le_words[0]);
840 siphash_key.words[1] = __le64_to_cpu(siphash_key.le_words[1]);
841
842 GTEST_LOG_(INFO) << "Inode hash key is {" << std::hex << "0x"
843 << siphash_key.words[0] << ", 0x" << siphash_key.words[1]
844 << "}" << std::dec;
845
846 input.inode_number = __cpu_to_le64(inode_number);
847
848 *hash = SIPHASH_24(siphash_key.words, input.bytes, sizeof(input));
849 GTEST_LOG_(INFO) << "Hashed inode number " << inode_number << " to 0x"
850 << std::hex << *hash << std::dec;
851 return true;
852 }
853
VerifyCiphertext(const std::vector<uint8_t> & enc_key,const FscryptIV & starting_iv,const Cipher & cipher,const TestFileInfo & file_info)854 void FBEPolicyTest::VerifyCiphertext(const std::vector<uint8_t> &enc_key,
855 const FscryptIV &starting_iv,
856 const Cipher &cipher,
857 const TestFileInfo &file_info) {
858 const std::vector<uint8_t> &plaintext = file_info.plaintext;
859
860 GTEST_LOG_(INFO) << "Verifying correctness of encrypted data";
861 FscryptIV iv = starting_iv;
862
863 std::vector<uint8_t> computed_ciphertext(plaintext.size());
864
865 // Encrypt each filesystem block of file contents.
866 for (size_t i = 0; i < plaintext.size(); i += kFilesystemBlockSize) {
867 int block_size =
868 std::min<size_t>(kFilesystemBlockSize, plaintext.size() - i);
869
870 ASSERT_GE(sizeof(iv.bytes), cipher.ivsize());
871 ASSERT_TRUE(cipher.Encrypt(enc_key, iv.bytes, &plaintext[i],
872 &computed_ciphertext[i], block_size));
873
874 // Update the IV by incrementing the file logical block number.
875 iv.lblk_num = __cpu_to_le32(__le32_to_cpu(iv.lblk_num) + 1);
876 }
877
878 ASSERT_EQ(file_info.actual_ciphertext, computed_ciphertext);
879 }
880
InitIVForPerFileKey(FscryptIV * iv)881 static bool InitIVForPerFileKey(FscryptIV *iv) {
882 memset(iv, 0, kFscryptMaxIVSize);
883 return true;
884 }
885
InitIVForDirectKey(const FscryptFileNonce & nonce,FscryptIV * iv)886 static bool InitIVForDirectKey(const FscryptFileNonce &nonce, FscryptIV *iv) {
887 memset(iv, 0, kFscryptMaxIVSize);
888 memcpy(iv->file_nonce, nonce.bytes, kFscryptFileNonceSize);
889 return true;
890 }
891
InitIVForInoLblk64(uint64_t inode_number,FscryptIV * iv)892 static bool InitIVForInoLblk64(uint64_t inode_number, FscryptIV *iv) {
893 if (inode_number > UINT32_MAX) {
894 ADD_FAILURE() << "inode number doesn't fit in 32 bits";
895 return false;
896 }
897 memset(iv, 0, kFscryptMaxIVSize);
898 iv->inode_number = __cpu_to_le32(inode_number);
899 return true;
900 }
901
InitIVForInoLblk32(const std::vector<uint8_t> & master_key,uint64_t inode_number,FscryptIV * iv)902 static bool InitIVForInoLblk32(const std::vector<uint8_t> &master_key,
903 uint64_t inode_number, FscryptIV *iv) {
904 uint32_t hash;
905 if (!HashInodeNumber(master_key, inode_number, &hash)) return false;
906 memset(iv, 0, kFscryptMaxIVSize);
907 iv->lblk_num = __cpu_to_le32(hash);
908 return true;
909 }
910
911 // Tests a policy matching "fileencryption=aes-256-xts:aes-256-cts:v2"
912 // (or simply "fileencryption=" on devices launched with R or higher)
TEST_F(FBEPolicyTest,TestAesPerFileKeysPolicy)913 TEST_F(FBEPolicyTest, TestAesPerFileKeysPolicy) {
914 if (skip_test_) return;
915
916 auto master_key = GenerateTestKey(kFscryptMasterKeySize);
917 ASSERT_TRUE(SetMasterKey(master_key));
918
919 if (!SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
920 0, 0))
921 return;
922
923 TestFileInfo file_info;
924 ASSERT_TRUE(GenerateTestFile(&file_info));
925
926 std::vector<uint8_t> enc_key(kAes256XtsKeySize);
927 ASSERT_TRUE(DerivePerFileEncryptionKey(master_key, file_info.nonce, enc_key));
928
929 FscryptIV iv;
930 ASSERT_TRUE(InitIVForPerFileKey(&iv));
931 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
932 }
933
934 // Tests a policy matching
935 // "fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized"
936 // (or simply "fileencryption=::inlinecrypt_optimized" on devices launched with
937 // R or higher)
TEST_F(FBEPolicyTest,TestAesInlineCryptOptimizedPolicy)938 TEST_F(FBEPolicyTest, TestAesInlineCryptOptimizedPolicy) {
939 if (skip_test_) return;
940
941 auto master_key = GenerateTestKey(kFscryptMasterKeySize);
942 ASSERT_TRUE(SetMasterKey(master_key));
943
944 if (!SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
945 FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64,
946 GetSkipFlagsForInoBasedEncryption()))
947 return;
948
949 TestFileInfo file_info;
950 ASSERT_TRUE(GenerateTestFile(&file_info));
951
952 std::vector<uint8_t> enc_key(kAes256XtsKeySize);
953 ASSERT_TRUE(DerivePerModeEncryptionKey(master_key, FSCRYPT_MODE_AES_256_XTS,
954 HKDF_CONTEXT_IV_INO_LBLK_64_KEY,
955 enc_key));
956
957 FscryptIV iv;
958 ASSERT_TRUE(InitIVForInoLblk64(file_info.inode_number, &iv));
959 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
960 }
961
962 // Tests a policy matching
963 // "fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized+wrappedkey_v0"
964 // (or simply "fileencryption=::inlinecrypt_optimized+wrappedkey_v0" on devices
965 // launched with R or higher)
TEST_F(FBEPolicyTest,TestAesInlineCryptOptimizedHwWrappedKeyPolicy)966 TEST_F(FBEPolicyTest, TestAesInlineCryptOptimizedHwWrappedKeyPolicy) {
967 if (skip_test_) return;
968
969 std::vector<uint8_t> enc_key, sw_secret;
970 if (!CreateAndSetHwWrappedKey(&enc_key, &sw_secret)) return;
971
972 if (!SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
973 FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64,
974 // 64-bit DUN support is not guaranteed.
975 kSkipIfInlineEncryptionNotUsable |
976 GetSkipFlagsForInoBasedEncryption()))
977 return;
978
979 TestFileInfo file_info;
980 ASSERT_TRUE(GenerateTestFile(&file_info));
981
982 FscryptIV iv;
983 ASSERT_TRUE(InitIVForInoLblk64(file_info.inode_number, &iv));
984 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
985 }
986
987 // With IV_INO_LBLK_32, the DUN (IV) can wrap from UINT32_MAX to 0 in the middle
988 // of the file. This method tests that this case appears to be handled
989 // correctly, by doing I/O across the place where the DUN wraps around. Assumes
990 // that test_dir_ 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)991 void FBEPolicyTest::TestEmmcOptimizedDunWraparound(
992 const std::vector<uint8_t> &master_key,
993 const std::vector<uint8_t> &enc_key) {
994 // We'll test writing 'block_count' filesystem blocks. The first
995 // 'block_count_1' blocks will have DUNs [..., UINT32_MAX - 1, UINT32_MAX].
996 // The remaining 'block_count_2' blocks will have DUNs [0, 1, ...].
997 constexpr uint32_t block_count_1 = 3;
998 constexpr uint32_t block_count_2 = 7;
999 constexpr uint32_t block_count = block_count_1 + block_count_2;
1000 constexpr size_t data_size = block_count * kFilesystemBlockSize;
1001
1002 // Assumed maximum file size. Unfortunately there isn't a syscall to get
1003 // this. ext4 allows ~16TB and f2fs allows ~4TB. However, an underestimate
1004 // works fine for our purposes, so just go with 1TB.
1005 constexpr off_t max_file_size = 1000000000000;
1006 constexpr off_t max_file_blocks = max_file_size / kFilesystemBlockSize;
1007
1008 // Repeatedly create empty files until we find one that can be used for DUN
1009 // wraparound testing, due to SipHash(inode_number) being almost UINT32_MAX.
1010 std::string path;
1011 TestFileInfo file_info;
1012 uint32_t lblk_with_dun_0;
1013 for (int i = 0;; i++) {
1014 // The probability of finding a usable file is about 'max_file_blocks /
1015 // UINT32_MAX', or about 5.6%. So on average we'll need about 18 tries.
1016 // The probability we'll need over 1000 tries is less than 1e-25.
1017 ASSERT_LT(i, 1000) << "Tried too many times to find a usable test file";
1018
1019 path = android::base::StringPrintf("%s/file%d", test_dir_.c_str(), i);
1020 android::base::unique_fd fd(
1021 open(path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, 0600));
1022 ASSERT_GE(fd, 0) << "Failed to create " << path << Errno();
1023
1024 ASSERT_TRUE(GetInodeNumber(path, &file_info.inode_number));
1025 uint32_t hash;
1026 ASSERT_TRUE(HashInodeNumber(master_key, file_info.inode_number, &hash));
1027 // Negating the hash gives the distance to DUN 0, and hence the 0-based
1028 // logical block number of the block which has DUN 0.
1029 lblk_with_dun_0 = -hash;
1030 if (lblk_with_dun_0 >= block_count_1 &&
1031 static_cast<off_t>(lblk_with_dun_0) + block_count_2 < max_file_blocks)
1032 break;
1033 }
1034
1035 GTEST_LOG_(INFO) << "DUN wraparound test: path=" << path
1036 << ", inode_number=" << file_info.inode_number
1037 << ", lblk_with_dun_0=" << lblk_with_dun_0;
1038
1039 // Write some data across the DUN wraparound boundary and verify that the
1040 // resulting on-disk ciphertext is as expected. Note that we don't actually
1041 // have to fill the file until the boundary; we can just write to the needed
1042 // part and leave a hole before it.
1043 for (int i = 0; i < 2; i++) {
1044 // Try both buffered I/O and direct I/O.
1045 int open_flags = O_RDWR | O_CLOEXEC;
1046 if (i == 1) open_flags |= O_DIRECT;
1047
1048 android::base::unique_fd fd(open(path.c_str(), open_flags));
1049 ASSERT_GE(fd, 0) << "Failed to open " << path << Errno();
1050
1051 // Generate some test data.
1052 file_info.plaintext.resize(data_size);
1053 RandomBytesForTesting(file_info.plaintext);
1054
1055 // Write the test data. To support O_DIRECT, use a block-aligned buffer.
1056 std::unique_ptr<void, void (*)(void *)> buf_mem(
1057 aligned_alloc(kFilesystemBlockSize, data_size), free);
1058 ASSERT_TRUE(buf_mem != nullptr);
1059 memcpy(buf_mem.get(), &file_info.plaintext[0], data_size);
1060 off_t pos = static_cast<off_t>(lblk_with_dun_0 - block_count_1) *
1061 kFilesystemBlockSize;
1062 ASSERT_EQ(data_size, pwrite(fd, buf_mem.get(), data_size, pos))
1063 << "Error writing data to " << path << Errno();
1064
1065 // Verify the ciphertext.
1066 ASSERT_TRUE(ReadRawDataOfFile(fd, fs_info_.raw_blk_device, data_size,
1067 &file_info.actual_ciphertext));
1068 FscryptIV iv;
1069 memset(&iv, 0, sizeof(iv));
1070 iv.lblk_num = __cpu_to_le32(-block_count_1);
1071 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
1072 }
1073 }
1074
1075 // Tests a policy matching
1076 // "fileencryption=aes-256-xts:aes-256-cts:v2+emmc_optimized" (or simply
1077 // "fileencryption=::emmc_optimized" on devices launched with R or higher)
TEST_F(FBEPolicyTest,TestAesEmmcOptimizedPolicy)1078 TEST_F(FBEPolicyTest, TestAesEmmcOptimizedPolicy) {
1079 if (skip_test_) return;
1080
1081 auto master_key = GenerateTestKey(kFscryptMasterKeySize);
1082 ASSERT_TRUE(SetMasterKey(master_key));
1083
1084 if (!SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
1085 FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32,
1086 GetSkipFlagsForInoBasedEncryption()))
1087 return;
1088
1089 TestFileInfo file_info;
1090 ASSERT_TRUE(GenerateTestFile(&file_info));
1091
1092 std::vector<uint8_t> enc_key(kAes256XtsKeySize);
1093 ASSERT_TRUE(DerivePerModeEncryptionKey(master_key, FSCRYPT_MODE_AES_256_XTS,
1094 HKDF_CONTEXT_IV_INO_LBLK_32_KEY,
1095 enc_key));
1096
1097 FscryptIV iv;
1098 ASSERT_TRUE(InitIVForInoLblk32(master_key, file_info.inode_number, &iv));
1099 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
1100
1101 TestEmmcOptimizedDunWraparound(master_key, enc_key);
1102 }
1103
1104 // Tests a policy matching
1105 // "fileencryption=aes-256-xts:aes-256-cts:v2+emmc_optimized+wrappedkey_v0"
1106 // (or simply "fileencryption=::emmc_optimized+wrappedkey_v0" on devices
1107 // launched with R or higher)
TEST_F(FBEPolicyTest,TestAesEmmcOptimizedHwWrappedKeyPolicy)1108 TEST_F(FBEPolicyTest, TestAesEmmcOptimizedHwWrappedKeyPolicy) {
1109 if (skip_test_) return;
1110
1111 std::vector<uint8_t> enc_key, sw_secret;
1112 if (!CreateAndSetHwWrappedKey(&enc_key, &sw_secret)) return;
1113
1114 int skip_flags = GetSkipFlagsForInoBasedEncryption();
1115 if (kFilesystemBlockSize != getpagesize())
1116 skip_flags |= kSkipIfInlineEncryptionNotUsable;
1117
1118 if (!SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS, FSCRYPT_MODE_AES_256_CTS,
1119 FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32, skip_flags))
1120 return;
1121
1122 TestFileInfo file_info;
1123 ASSERT_TRUE(GenerateTestFile(&file_info));
1124
1125 FscryptIV iv;
1126 ASSERT_TRUE(InitIVForInoLblk32(sw_secret, file_info.inode_number, &iv));
1127 VerifyCiphertext(enc_key, iv, Aes256XtsCipher(), file_info);
1128
1129 TestEmmcOptimizedDunWraparound(sw_secret, enc_key);
1130 }
1131
1132 // Tests a policy matching "fileencryption=adiantum:adiantum:v2" (or simply
1133 // "fileencryption=adiantum" on devices launched with R or higher)
TEST_F(FBEPolicyTest,TestAdiantumPolicy)1134 TEST_F(FBEPolicyTest, TestAdiantumPolicy) {
1135 if (skip_test_) return;
1136
1137 auto master_key = GenerateTestKey(kFscryptMasterKeySize);
1138 ASSERT_TRUE(SetMasterKey(master_key));
1139
1140 // Adiantum support isn't required (since CONFIG_CRYPTO_ADIANTUM can be unset
1141 // in the kernel config), so we may skip the test here.
1142 //
1143 // We don't need to use GetSkipFlagsForInoBasedEncryption() here, since the
1144 // "DIRECT_KEY" IV generation method doesn't include inode numbers in the IVs.
1145 if (!SetEncryptionPolicy(FSCRYPT_MODE_ADIANTUM, FSCRYPT_MODE_ADIANTUM,
1146 FSCRYPT_POLICY_FLAG_DIRECT_KEY,
1147 kSkipIfNoCryptoAPISupport))
1148 return;
1149
1150 TestFileInfo file_info;
1151 ASSERT_TRUE(GenerateTestFile(&file_info));
1152
1153 std::vector<uint8_t> enc_key(kAdiantumKeySize);
1154 ASSERT_TRUE(DerivePerModeEncryptionKey(master_key, FSCRYPT_MODE_ADIANTUM,
1155 HKDF_CONTEXT_DIRECT_KEY, enc_key));
1156
1157 FscryptIV iv;
1158 ASSERT_TRUE(InitIVForDirectKey(file_info.nonce, &iv));
1159 VerifyCiphertext(enc_key, iv, AdiantumCipher(), file_info);
1160 }
1161
1162 // Tests adding a corrupted wrapped key to fscrypt keyring.
1163 // If wrapped key is corrupted, fscrypt should return a failure.
TEST_F(FBEPolicyTest,TestHwWrappedKeyCorruption)1164 TEST_F(FBEPolicyTest, TestHwWrappedKeyCorruption) {
1165 if (skip_test_) return;
1166
1167 std::vector<uint8_t> master_key, exported_key;
1168 if (!CreateHwWrappedKey(&master_key, &exported_key)) return;
1169
1170 for (int i = 0; i < exported_key.size(); i++) {
1171 std::vector<uint8_t> corrupt_key(exported_key.begin(), exported_key.end());
1172 corrupt_key[i] = ~corrupt_key[i];
1173 ASSERT_FALSE(
1174 SetMasterKey(corrupt_key, __FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED, false));
1175 }
1176 }
1177
EnableF2fsCompressionOnTestDir()1178 bool FBEPolicyTest::EnableF2fsCompressionOnTestDir() {
1179 android::base::unique_fd fd(open(test_dir_.c_str(), O_RDONLY | O_CLOEXEC));
1180 if (fd < 0) {
1181 ADD_FAILURE() << "Failed to open " << test_dir_ << Errno();
1182 return false;
1183 }
1184
1185 int flags;
1186 if (ioctl(fd, FS_IOC_GETFLAGS, &flags) != 0) {
1187 ADD_FAILURE() << "Unexpected error getting flags of " << test_dir_
1188 << Errno();
1189 return false;
1190 }
1191 flags |= FS_COMPR_FL;
1192 if (ioctl(fd, FS_IOC_SETFLAGS, &flags) != 0) {
1193 if (errno == EOPNOTSUPP) {
1194 GTEST_LOG_(INFO)
1195 << "Skipping test because f2fs compression is not supported on "
1196 << kTestMountpoint;
1197 return false;
1198 }
1199 ADD_FAILURE() << "Unexpected error enabling compression on " << test_dir_
1200 << Errno();
1201 return false;
1202 }
1203 return true;
1204 }
1205
F2fsCompressAlgorithmName(int algorithm)1206 static std::string F2fsCompressAlgorithmName(int algorithm) {
1207 switch (algorithm) {
1208 case F2FS_COMPRESS_LZO:
1209 return "LZO";
1210 case F2FS_COMPRESS_LZ4:
1211 return "LZ4";
1212 case F2FS_COMPRESS_ZSTD:
1213 return "ZSTD";
1214 case F2FS_COMPRESS_LZORLE:
1215 return "LZORLE";
1216 default:
1217 return android::base::StringPrintf("%d", algorithm);
1218 }
1219 }
1220
F2fsCompressOptionsSupported(const struct f2fs_comp_option & opts)1221 bool FBEPolicyTest::F2fsCompressOptionsSupported(
1222 const struct f2fs_comp_option &opts) {
1223 android::base::unique_fd fd(
1224 open(test_file_.c_str(), O_WRONLY | O_CREAT, 0600));
1225 if (fd < 0) {
1226 // If the filesystem has the compression feature flag enabled but f2fs
1227 // compression support was compiled out of the kernel, then setting
1228 // FS_COMPR_FL on the directory will succeed, but creating a file in the
1229 // directory will fail with EOPNOTSUPP.
1230 if (errno == EOPNOTSUPP) {
1231 GTEST_LOG_(INFO)
1232 << "Skipping test because kernel doesn't support f2fs compression";
1233 return false;
1234 }
1235 ADD_FAILURE() << "Unexpected error creating " << test_file_
1236 << " after enabling f2fs compression on parent directory"
1237 << Errno();
1238 return false;
1239 }
1240
1241 if (ioctl(fd, F2FS_IOC_SET_COMPRESS_OPTION, &opts) != 0) {
1242 if (errno == ENOTTY || errno == EOPNOTSUPP) {
1243 GTEST_LOG_(INFO) << "Skipping test because kernel doesn't support "
1244 "F2FS_IOC_SET_COMPRESS_OPTION on "
1245 << kTestMountpoint;
1246 return false;
1247 }
1248 ADD_FAILURE() << "Unexpected error from F2FS_IOC_SET_COMPRESS_OPTION"
1249 << Errno();
1250 return false;
1251 }
1252 // Unsupported compression algorithms aren't detected until the file is
1253 // reopened.
1254 fd.reset(open(test_file_.c_str(), O_WRONLY));
1255 if (fd < 0) {
1256 if (errno == EOPNOTSUPP || errno == ENOPKG) {
1257 GTEST_LOG_(INFO) << "Skipping test because kernel doesn't support "
1258 << F2fsCompressAlgorithmName(opts.algorithm)
1259 << " compression";
1260 return false;
1261 }
1262 ADD_FAILURE() << "Unexpected error when reopening file after "
1263 "F2FS_IOC_SET_COMPRESS_OPTION"
1264 << Errno();
1265 return false;
1266 }
1267 unlink(test_file_.c_str());
1268 return true;
1269 }
1270
1271 // Tests that encryption is done correctly on compressed files.
1272 //
1273 // This works by creating a compressed+encrypted file, then decrypting the
1274 // file's on-disk data, then decompressing it, then comparing the result to the
1275 // original data. We don't do it the other way around (compress+encrypt the
1276 // original data and compare to the on-disk data) because different
1277 // implementations of a compression algorithm can produce different results.
1278 //
1279 // This is adapted from the xfstest "f2fs/002"; see there for some more details.
1280 //
1281 // This test will skip itself if any of the following is true:
1282 // - f2fs compression isn't enabled on /data
1283 // - f2fs compression isn't enabled in the kernel (CONFIG_F2FS_FS_COMPRESSION)
1284 // - The kernel doesn't support the needed algorithm (CONFIG_F2FS_FS_LZ4)
1285 // - The kernel doesn't support the F2FS_IOC_SET_COMPRESS_OPTION ioctl
1286 //
1287 // Note, this test will be flaky if the kernel is missing commit 093f0bac32b
1288 // ("f2fs: change fiemap way in printing compression chunk").
1289 //
1290 // This test is currently disabled because the test is still flaky even with the
1291 // above fix, and it hasn't been able to be root-caused. TODO(b/329449658):
1292 // root cause the issue and re-enable the test.
TEST_F(FBEPolicyTest,DISABLED_TestF2fsCompression)1293 TEST_F(FBEPolicyTest, DISABLED_TestF2fsCompression) {
1294 if (skip_test_) return;
1295
1296 // Currently, only f2fs supports compression+encryption.
1297 if (fs_info_.type != "f2fs") {
1298 GTEST_LOG_(INFO) << "Skipping test because device uses " << fs_info_.type
1299 << ", not f2fs";
1300 return;
1301 }
1302
1303 // Enable compression and encryption on the test directory. Afterwards, both
1304 // of these features will be inherited by any file created in this directory.
1305 //
1306 // If compression is not supported, skip the test. Use the default encryption
1307 // settings, which should always be supported.
1308 if (!EnableF2fsCompressionOnTestDir()) return;
1309 auto master_key = GenerateTestKey(kFscryptMasterKeySize);
1310 ASSERT_TRUE(SetMasterKey(master_key));
1311 ASSERT_TRUE(SetEncryptionPolicy(FSCRYPT_MODE_AES_256_XTS,
1312 FSCRYPT_MODE_AES_256_CTS, 0, 0));
1313
1314 // This test will use LZ4 compression with a cluster size of 2^2 = 4 blocks.
1315 // Check that this setting is supported.
1316 //
1317 // Note that the precise choice of algorithm and cluster size isn't too
1318 // important for this test. We just (somewhat arbitrarily) chose a setting
1319 // which is commonly used and for which a decompression library is available.
1320 const int log_cluster_size = 2;
1321 const int cluster_bytes = kFilesystemBlockSize << log_cluster_size;
1322 struct f2fs_comp_option comp_opt;
1323 memset(&comp_opt, 0, sizeof(comp_opt));
1324 comp_opt.algorithm = F2FS_COMPRESS_LZ4;
1325 comp_opt.log_cluster_size = log_cluster_size;
1326 if (!F2fsCompressOptionsSupported(comp_opt)) return;
1327
1328 // Generate the test file and retrieve its on-disk data. Note: despite being
1329 // compressed, the on-disk data here will still be |kTestFileBytes| long.
1330 // This is because FS_IOC_FIEMAP doesn't natively support compression, and the
1331 // way that f2fs handles it on compressed files results in us reading extra
1332 // blocks appended to the compressed clusters. It works out in the end
1333 // though, since these extra blocks get ignored during decompression.
1334 TestFileInfo file_info;
1335 ASSERT_TRUE(GenerateTestFile(&file_info, &comp_opt));
1336
1337 GTEST_LOG_(INFO) << "Decrypting the blocks of the compressed file";
1338 std::vector<uint8_t> enc_key(kAes256XtsKeySize);
1339 ASSERT_TRUE(DerivePerFileEncryptionKey(master_key, file_info.nonce, enc_key));
1340 std::vector<uint8_t> decrypted_data(kTestFileBytes);
1341 FscryptIV iv;
1342 memset(&iv, 0, sizeof(iv));
1343 ASSERT_EQ(0, kTestFileBytes % kFilesystemBlockSize);
1344 for (int i = 0; i < kTestFileBytes; i += kFilesystemBlockSize) {
1345 int block_num = i / kFilesystemBlockSize;
1346 int cluster_num = i / cluster_bytes;
1347
1348 // In compressed clusters, IVs start at 1 higher than the expected value.
1349 // Fortunately, due to the compression there is no overlap...
1350 if (IsCompressibleCluster(cluster_num)) block_num++;
1351
1352 iv.lblk_num = __cpu_to_le32(block_num);
1353 ASSERT_TRUE(Aes256XtsCipher().Decrypt(
1354 enc_key, iv.bytes, &file_info.actual_ciphertext[i], &decrypted_data[i],
1355 kFilesystemBlockSize));
1356 }
1357
1358 GTEST_LOG_(INFO) << "Decompressing the decrypted blocks of the file";
1359 std::vector<uint8_t> decompressed_data(kTestFileBytes);
1360 ASSERT_EQ(0, kTestFileBytes % cluster_bytes);
1361 for (int i = 0; i < kTestFileBytes; i += cluster_bytes) {
1362 int cluster_num = i / cluster_bytes;
1363 if (IsCompressibleCluster(cluster_num)) {
1364 // We had filled this cluster with compressible data, so it should have
1365 // been stored compressed.
1366 ASSERT_TRUE(DecompressLZ4Cluster(&decrypted_data[i],
1367 &decompressed_data[i], cluster_bytes));
1368 } else {
1369 // We had filled this cluster with random data, so it should have been
1370 // incompressible and thus stored uncompressed.
1371 memcpy(&decompressed_data[i], &decrypted_data[i], cluster_bytes);
1372 }
1373 }
1374
1375 // Finally do the actual test. The data we got after decryption+decompression
1376 // should match the original file contents.
1377 GTEST_LOG_(INFO) << "Comparing the result to the original data";
1378 ASSERT_EQ(file_info.plaintext, decompressed_data);
1379 }
1380
DeviceUsesFBE()1381 static bool DeviceUsesFBE() {
1382 if (android::base::GetProperty("ro.crypto.type", "") == "file") return true;
1383 // FBE has been required since Android Q.
1384 int first_api_level;
1385 if (!GetFirstApiLevel(&first_api_level)) return true;
1386 if (first_api_level >= __ANDROID_API_Q__) {
1387 ADD_FAILURE() << "File-based encryption is required";
1388 } else {
1389 GTEST_LOG_(INFO)
1390 << "Skipping test because device doesn't use file-based encryption";
1391 }
1392 return false;
1393 }
1394
1395 // Retrieves the encryption key specifier used in the file-based encryption
1396 // policy of |dir|. This isn't the key itself, but rather a "name" for the key.
1397 // If the key specifier cannot be retrieved, e.g. due to the directory being
1398 // unencrypted, then false is returned and a failure is added.
GetKeyUsedByDir(const std::string & dir,std::string * key_specifier)1399 static bool GetKeyUsedByDir(const std::string &dir,
1400 std::string *key_specifier) {
1401 android::base::unique_fd fd(open(dir.c_str(), O_RDONLY));
1402 if (fd < 0) {
1403 ADD_FAILURE() << "Failed to open " << dir << Errno();
1404 return false;
1405 }
1406 struct fscrypt_get_policy_ex_arg arg = {.policy_size = sizeof(arg.policy)};
1407 int res = ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY_EX, &arg);
1408 if (res != 0 && errno == ENOTTY) {
1409 // Handle old kernels that don't support FS_IOC_GET_ENCRYPTION_POLICY_EX.
1410 res = ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &arg.policy.v1);
1411 }
1412 if (res != 0) {
1413 if (errno == ENODATA) {
1414 ADD_FAILURE() << "Directory " << dir << " is not encrypted!";
1415 } else {
1416 ADD_FAILURE() << "Failed to get encryption policy of " << dir << Errno();
1417 }
1418 return false;
1419 }
1420 switch (arg.policy.version) {
1421 case FSCRYPT_POLICY_V1:
1422 *key_specifier = BytesToHex(arg.policy.v1.master_key_descriptor);
1423 return true;
1424 case FSCRYPT_POLICY_V2:
1425 *key_specifier = BytesToHex(arg.policy.v2.master_key_identifier);
1426 return true;
1427 default:
1428 ADD_FAILURE() << dir << " uses unknown encryption policy version ("
1429 << arg.policy.version << ")";
1430 return false;
1431 }
1432 }
1433
1434 // Tests that if the device uses FBE, then the ciphertext for file contents in
1435 // encrypted directories seems to be random.
1436 //
1437 // This isn't as strong a test as the correctness tests, but it's useful because
1438 // it applies regardless of the encryption format and key. Thus it runs even on
1439 // old devices, including ones that used a vendor-specific encryption format.
TEST(FBETest,TestFileContentsRandomness)1440 TEST(FBETest, TestFileContentsRandomness) {
1441 const std::string path_1 =
1442 android::base::StringPrintf("%s/FBETest-1.%d", kTmpDir, getpid());
1443 const std::string path_2 =
1444 android::base::StringPrintf("%s/FBETest-2.%d", kTmpDir, getpid());
1445
1446 if (!DeviceUsesFBE()) return;
1447
1448 FilesystemInfo fs_info;
1449 ASSERT_TRUE(GetFilesystemInfo(kTestMountpoint, &fs_info));
1450
1451 std::vector<uint8_t> zeroes(kTestFileBytes, 0);
1452 std::vector<uint8_t> ciphertext_1;
1453 std::vector<uint8_t> ciphertext_2;
1454 ASSERT_TRUE(WriteTestFile(zeroes, path_1, fs_info.raw_blk_device, nullptr,
1455 &ciphertext_1));
1456 ASSERT_TRUE(WriteTestFile(zeroes, path_2, fs_info.raw_blk_device, nullptr,
1457 &ciphertext_2));
1458
1459 GTEST_LOG_(INFO) << "Verifying randomness of ciphertext";
1460
1461 // Each individual file's ciphertext should be random.
1462 ASSERT_TRUE(VerifyDataRandomness(ciphertext_1));
1463 ASSERT_TRUE(VerifyDataRandomness(ciphertext_2));
1464
1465 // The files' ciphertext concatenated should also be random.
1466 // I.e., each file should be encrypted differently.
1467 std::vector<uint8_t> concatenated_ciphertext;
1468 concatenated_ciphertext.insert(concatenated_ciphertext.end(),
1469 ciphertext_1.begin(), ciphertext_1.end());
1470 concatenated_ciphertext.insert(concatenated_ciphertext.end(),
1471 ciphertext_2.begin(), ciphertext_2.end());
1472 ASSERT_TRUE(VerifyDataRandomness(concatenated_ciphertext));
1473
1474 ASSERT_EQ(unlink(path_1.c_str()), 0);
1475 ASSERT_EQ(unlink(path_2.c_str()), 0);
1476 }
1477
1478 // Tests that all of user 0's directories that should be encrypted actually are,
1479 // and that user 0's CE and DE keys are different.
TEST(FBETest,TestUserDirectoryPolicies)1480 TEST(FBETest, TestUserDirectoryPolicies) {
1481 if (!DeviceUsesFBE()) return;
1482
1483 std::string user0_ce_key, user0_de_key;
1484 EXPECT_TRUE(GetKeyUsedByDir("/data/user/0", &user0_ce_key));
1485 EXPECT_TRUE(GetKeyUsedByDir("/data/user_de/0", &user0_de_key));
1486 EXPECT_NE(user0_ce_key, user0_de_key) << "CE and DE keys must differ";
1487
1488 // Check the CE directories other than /data/user/0.
1489 for (const std::string &dir : {"/data/media/0", "/data/misc_ce/0",
1490 "/data/system_ce/0", "/data/vendor_ce/0"}) {
1491 std::string key;
1492 EXPECT_TRUE(GetKeyUsedByDir(dir, &key));
1493 EXPECT_EQ(key, user0_ce_key) << dir << " must be encrypted with CE key";
1494 }
1495
1496 // Check the DE directories other than /data/user_de/0.
1497 for (const std::string &dir :
1498 {"/data/misc_de/0", "/data/system_de/0", "/data/vendor_de/0"}) {
1499 std::string key;
1500 EXPECT_TRUE(GetKeyUsedByDir(dir, &key));
1501 EXPECT_EQ(key, user0_de_key) << dir << " must be encrypted with DE key";
1502 }
1503 }
1504
1505 } // namespace kernel
1506 } // namespace android
1507