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