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