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