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